---
title: How VERI differs from a modern ERC-20
description: VERI is 2017 code whose initial allocation and ownership transfer emit no Transfer event, whose decimals() returns uint256, whose failed transfers throw instead of returning false, which has no zero-address checks, and whose transferOwnership moves the owner's whole balance to the new owner, as its one call on 24 Apr 2017 did with all 100,000,000 VERI.
url: https://veri.how/veri/erc20-quirks
area: veri
kind: reference
updated: 2026-10-15T00:00:00Z
author: Patryk Dwórznik
license: CC BY 4.0
contracts:
  - id: eip155:1:0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374
    name: Veritaseum
    verified:
      date: 2026-10-13
sources:
  - title: VERI verified source, Etherscan
    url: https://etherscan.io/address/0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374#code
  - title: VERI contract creation transaction, Etherscan
    url: https://etherscan.io/tx/0xfda7aad54c81d9bc8e7a67e68821a24009c2bcd5e9b9a47b71f40d5a45f3a6fc
  - title: The transferOwnership transaction of 24 Apr 2017, Etherscan
    url: https://etherscan.io/tx/0x5d7d007e7dbf534a2983880be117100691cf351fdc45d6adb2249c6fd3a8d4b1
  - title: The transferOwnership transaction of 24 Apr 2017, Blockscout
    url: https://eth.blockscout.com/tx/0x5d7d007e7dbf534a2983880be117100691cf351fdc45d6adb2249c6fd3a8d4b1
  - title: "EIP-20: Token Standard"
    url: https://eips.ethereum.org/EIPS/eip-20
---

# How VERI differs from a modern ERC-20

VERI is 2017 code whose initial allocation and ownership transfer emit no Transfer event, whose decimals() returns uint256, whose failed transfers throw instead of returning false, which has no zero-address checks, and whose transferOwnership moves the owner's whole balance to the new owner, as its one call on 24 Apr 2017 did with all 100,000,000 VERI.

## Facts

| Fact | Value |
| --- | --- |
| Address | [0x8f3470A7388c05eE4e7AF3d01D8C722b0FF52374](https://etherscan.io/token/0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374) |
| Chain | [Ethereum (eip155:1)](https://etherscan.io) |
| Standard | [ERC-20](https://eips.ethereum.org/EIPS/eip-20) |
| Symbol | [VERI](https://etherscan.io/token/0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374) |
| Decimals | [18](https://etherscan.io/address/0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374#code) |
| Deployed | [Block 3,586,472 · 23 Apr 2017](https://etherscan.io/tx/0xfda7aad54c81d9bc8e7a67e68821a24009c2bcd5e9b9a47b71f40d5a45f3a6fc) |
| Owner | [0x82c48875C17EE5812f909a9d75C0F64f7A8719FE](https://etherscan.io/address/0x82c48875c17ee5812f909a9d75c0f64f7a8719fe) |
| Source | [Verified on Etherscan](https://etherscan.io/address/0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374#code) |
| Transactions | [All transactions](https://etherscan.io/address/0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374) |
| ABI | [veri.json](https://veri.how/abi/veri.json) |
| Last verified | 13 Oct 2026 |

The VERI contract predates the final [EIP-20](https://eips.ethereum.org/EIPS/eip-20) text and most of the conventions that grew around it. It works with every wallet and tool that calls `balanceOf` and `transfer`, but an indexer, a wrapper or a strict ABI decoder meets the differences below. Each one is read from the [verified source](https://etherscan.io/address/0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374#code).

## Two balance changes emit no Transfer event

Modern tokens emit `Transfer(0x0, to, amount)` when tokens are created, so that the sum of all `Transfer` logs equals every balance. VERI changes balances twice without a log:

1. **The initial allocation.** The constructor writes `balances[msg.sender] = totalSupply` directly. The [creation transaction](https://etherscan.io/tx/0xfda7aad54c81d9bc8e7a67e68821a24009c2bcd5e9b9a47b71f40d5a45f3a6fc) has no logs, so 100,000,000 VERI appeared with no `Transfer`.
2. **`transferOwnership`.** It copies the owner's balance to the new owner and zeroes the old one, with no event. The [one call on record](#the-one-call-on-record) moved all 100,000,000 VERI with no `Transfer`.

An indexer that rebuilds balances from `Transfer` logs therefore puts the whole supply nowhere, and every later balance it computes for the first holders is off. Read `balanceOf` instead, as in [Check a VERI balance](https://veri.how/veri/check-balance.md).

## decimals() returns uint256

```solidity
uint public decimals = 18;
```

EIP-20 specifies `decimals()` as `uint8`. VERI declares it as `uint`, so the ABI and the return word are `uint256`. The value is 18, and a decoder that reads the low byte of the 32-byte word gets the same answer. A strictly typed client that expects `uint8` in the ABI needs the committed [ABI](https://veri.how/abi/veri.json), which says `uint256`.

## Failures throw; successes return true

`transfer`, `transferFrom` and `approve` all `return true`. VERI does not have the "missing return value" problem of some tokens from the same year. But they never return `false`: an insufficient balance or allowance reaches `SafeMath.safeSub`, whose custom `assert` calls `throw`:

```solidity
function safeSub(uint a, uint b) internal returns (uint) {
  assert(b <= a);
  return a - b;
}

function assert(bool assertion) internal {
  if (!assertion) {
    throw;
  }
}
```

`throw` in Solidity 0.4.8 compiles to an invalid opcode, which reverts the state and consumes all the gas sent with the transaction. A wrapper that checks the return value for failure never sees one; it has to treat a revert as the failure.

## No zero-address checks

`transfer` and `transferFrom` accept any `_to`, including `0x0`. Tokens sent there are not burned: they sit in `balances[0x0]`, still count in `totalSupply`, and show up when you call `balanceOf` for the zero address (the command in [VERI supply is fixed at 100,000,000](https://veri.how/veri/supply.md#check-it-yourself) reads it).

## approve overwrites, with no increase or decrease

```solidity
function approve(address _spender, uint _value) returns (bool success) {
  allowed[msg.sender][_spender] = _value;
  Approval(msg.sender, _spender, _value);
  return true;
}
```

`approve` sets the allowance to `_value` whatever it was before, which is the approve/transferFrom race described in EIP-20. There is no `increaseAllowance`, `decreaseAllowance` or `permit`. The safe pattern is to set the allowance to zero before setting a new value.

## transferOwnership moves the owner's whole balance

In most contracts, `transferOwnership` changes an address and nothing else. In VERI it also moves tokens.

### The code

`VeritaseumToken` overrides the `transferOwnership` it inherits from `Ownable` ([verified source](https://etherscan.io/address/0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374#code)):

```solidity
// VeritaseumToken
function transferOwnership(address _newOwner) onlyOwner {
    balances[_newOwner] = balances[owner];
    balances[owner] = 0;
    Ownable.transferOwnership(_newOwner);
}

// Ownable
function transferOwnership(address newOwner) onlyOwner {
    if (newOwner != address(0)) {
        owner = newOwner;
    }
}
```

### What one call does

Only the current owner can call it (`onlyOwner` throws for anyone else). A successful call does three things, in this order:

1. **Overwrites the new owner's balance with the owner's balance.** It is an assignment, not an addition. Whatever `_newOwner` held before is gone.
2. **Sets the old owner's balance to zero.**
3. **Changes `owner`**, but only if `_newOwner` is not the zero address.

Three things it does not do:

- **It emits no event.** There is no `Transfer` for the moved balance and no `OwnershipTransferred`. A balance rebuilt from `Transfer` logs misses this move entirely (see [above](#two-balance-changes-emit-no-transfer-event)).
- **It does not change `totalSupply`**, even when step 1 destroys tokens. The [supply](https://veri.how/veri/supply.md) stays at 100,000,000.
- **It does not move allowances.** Anything the old owner approved stays in `allowed[oldOwner][spender]`, attached to an address whose balance is now zero.

Ownership carries exactly one power: calling this function again. The owner cannot mint, burn, pause or touch anyone else's balance or allowance.

### Edge cases

These follow from the code; none has happened on chain.

| `_newOwner` is                     | Result                                                                                               |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------- |
| an address that already holds VERI | its balance is replaced by the owner's; the VERI it held is destroyed and `totalSupply` is unchanged |
| the owner itself                   | step 1 is a no-op and step 2 zeroes the owner: the owner's whole balance is destroyed                |
| the zero address                   | the balance moves to `0x0`, the owner is zeroed, and `owner` stays as it was: the tokens are lost    |

### The one call on record

The deployer, 0x44CAb6F6DC7045FD4AcD1d0f3d09Fc7a83004bd3, called `transferOwnership(0x82c48875C17EE5812f909a9d75C0F64f7A8719FE)` in block [3,589,599](https://etherscan.io/block/3589599) on 24 Apr 2017 at 01:37:44 UTC, the day after deployment ([transaction](https://etherscan.io/tx/0x5d7d007e7dbf534a2983880be117100691cf351fdc45d6adb2249c6fd3a8d4b1)). It used 40,088 gas and emitted no log.

Read from an archive node, the balances around that block are:

| Address                                                | Block 3,589,598  | Block 3,589,599  |
| ------------------------------------------------------ | ---------------- | ---------------- |
| 0x44CAb6F6DC7045FD4AcD1d0f3d09Fc7a83004bd3 (deployer)  | 100,000,000 VERI | 0                |
| 0x82c48875C17EE5812f909a9d75C0F64f7A8719FE (new owner) | 0                | 100,000,000 VERI |

So the call moved the full supply. `owner()` has returned 0x82c48875C17EE5812f909a9d75C0F64f7A8719FE ever since; the address is an externally owned account. Every transaction sent to the contract was checked on 13 Oct 2026 for the `transferOwnership` selector `0xf2fde38b`. This is the only successful call. One other [attempt](https://etherscan.io/tx/0x54637b5bca5dbfe2e3dedafaf5f13e85e6d9e0e5657d2867520fa0427e9f52e6), from an address that was not the owner, threw in `onlyOwner` on 26 Dec 2017 and changed nothing. Since the owner has always been an externally owned account, no contract could have called the function on its behalf.

## What else is missing

- `totalSupply` is declared twice (in the abstract `ERC20` and again in `VeritaseumToken`); the getter returns the initialised one, 10^26. See [VERI supply is fixed at 100,000,000](https://veri.how/veri/supply.md#two-declarations-one-getter).
- No ERC-165 `supportsInterface`, no transfer hooks, no pause, no mint and no burn.
- No `delegatecall` and no proxy, so none of the above can be fixed in place.

## Check it yourself

The commands are [`eth_call`](https://ethereum.org/developers/docs/apis/json-rpc/#eth-call) and [`eth_getTransactionReceipt`](https://ethereum.org/developers/docs/apis/json-rpc/#eth-gettransactionreceipt) requests to public Ethereum JSON-RPC endpoints.

```sh
# decimals(): a full 32-byte word, 0x0000…0012
curl -s https://ethereum-rpc.publicnode.com -X POST -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374","data":"0x313ce567"},"latest"]}'

# The creation receipt: "logs": [], so the 100,000,000 VERI allocation emitted no Transfer
curl -s https://eth.drpc.org -X POST -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["0xfda7aad54c81d9bc8e7a67e68821a24009c2bcd5e9b9a47b71f40d5a45f3a6fc"]}'

# The transferOwnership receipt: "logs": [] again, and "gasUsed": "0x9c98" (40,088)
curl -s https://eth.drpc.org -X POST -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionReceipt","params":["0x5d7d007e7dbf534a2983880be117100691cf351fdc45d6adb2249c6fd3a8d4b1"]}'

# owner(): 0x…82c48875c17ee5812f909a9d75c0f64f7a8719fe
curl -s https://ethereum-rpc.publicnode.com -X POST -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374","data":"0x8da5cb5b"},"latest"]}'
```

The balances before and after the call need an archive node. `https://eth.drpc.org` serves historical `eth_call` without a key: pass `"0x36c5de"` (3,589,598) or `"0x36c5df"` (3,589,599) instead of `"latest"`, with `balanceOf` calldata as in [Check a VERI balance](https://veri.how/veri/check-balance.md).

With [Foundry](https://www.getfoundry.sh/introduction/installation) installed, its `cast` command runs the same calls and decodes the answers:

```sh
export ETH_RPC_URL=https://eth.drpc.org

# 18; the ABI says uint256, so that is the return type to decode with
cast call 0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374 'decimals()(uint256)'

# Both receipts print logs []
cast receipt 0xfda7aad54c81d9bc8e7a67e68821a24009c2bcd5e9b9a47b71f40d5a45f3a6fc logs
cast receipt 0x5d7d007e7dbf534a2983880be117100691cf351fdc45d6adb2249c6fd3a8d4b1 logs

# 0x82c48875C17EE5812f909a9d75C0F64f7A8719FE
cast call 0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374 'owner()(address)'

# The transferOwnership input, decoded: "transferOwnership(address)" 0x82c48875C17EE5812f909a9d75C0F64f7A8719FE
cast tx 0x5d7d007e7dbf534a2983880be117100691cf351fdc45d6adb2249c6fd3a8d4b1 input | xargs cast 4byte-decode

# The deployer before and after: 100000000000000000000000000 [1e26], then 0
cast call 0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374 'balanceOf(address)(uint256)' 0x44CAb6F6DC7045FD4AcD1d0f3d09Fc7a83004bd3 --block 3589598
cast call 0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374 'balanceOf(address)(uint256)' 0x44CAb6F6DC7045FD4AcD1d0f3d09Fc7a83004bd3 --block 3589599

# The new owner before and after: 0, then 100000000000000000000000000 [1e26]
cast call 0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374 'balanceOf(address)(uint256)' 0x82c48875C17EE5812f909a9d75C0F64f7A8719FE --block 3589598
cast call 0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374 'balanceOf(address)(uint256)' 0x82c48875C17EE5812f909a9d75C0F64f7A8719FE --block 3589599
```

## Sources

1. [VERI verified source, Etherscan](https://etherscan.io/address/0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374#code)
2. [VERI contract creation transaction, Etherscan](https://etherscan.io/tx/0xfda7aad54c81d9bc8e7a67e68821a24009c2bcd5e9b9a47b71f40d5a45f3a6fc)
3. [The transferOwnership transaction of 24 Apr 2017, Etherscan](https://etherscan.io/tx/0x5d7d007e7dbf534a2983880be117100691cf351fdc45d6adb2249c6fd3a8d4b1)
4. [The transferOwnership transaction of 24 Apr 2017, Blockscout](https://eth.blockscout.com/tx/0x5d7d007e7dbf534a2983880be117100691cf351fdc45d6adb2249c6fd3a8d4b1)
5. [EIP-20: Token Standard](https://eips.ethereum.org/EIPS/eip-20)

## Related

- [VERI token contract 0x8f3470A7388c05eE4e7AF3d01D8C722b0FF52374](https://veri.how/veri/contract.md): VERI is an ERC-20 token at 0x8f3470A7388c05eE4e7AF3d01D8C722b0FF52374 on Ethereum mainnet, deployed on 23 Apr 2017 with a fixed supply of 100,000,000 and no proxy, so the code that runs today is the code deployed then.
- [VERI supply is fixed at 100,000,000](https://veri.how/veri/supply.md): The VERI contract sets totalSupply to 100,000,000 tokens (10^26 base units at 18 decimals) once, when it is deployed, and has no mint, burn or pause function, so the supply cannot change.
- [Check a VERI balance](https://veri.how/veri/check-balance.md): Call balanceOf(address) on the VERI contract through a public Ethereum JSON-RPC endpoint with curl and divide the result by 10^18; read the balance rather than summing Transfer logs, which miss two balance changes.
