My Answer:
Ok, the problem is really with Ganache ... If I use geth, everything is alright.
... ... sorry for your time ...
---------------- The Original Question --------------------
My understanding is that ERC20 Token balances are stored in the storage trie which will change over time. Also, token.balanceOf(accountHash, {}, blockNumber)
seems to return only the most recent balance no matter what that blockNumber
is. I am wondering if the Ethereum chain rolls back and then grows along a new chain, how are ERC20 token balances treated?
I want to clarify a bit regarding the Rollback
here. Consider a simplified chain with only 8 blocks, labeled by the order they are appended to the chain, (not the block number which defines the height of block.)
# blocks are labeled by the order they are added to the chain
/--[6]<--[7]<--[8]
/
[1]<--[2]<--[3]<--[4]<--[5]
Say there are transactions about a token (ERC20) in all these blocks.
When [5]
is added to chain, it is in the longest chain and token.balanceOf['0xAA']
gives me balance1
.
Now assume [6][7][8]
are appended to [3]
, this branch becomes the longest, and all transactions in [4]
and [5]
become invalid.
Now assume I want to be safe so I only care about balance of a ERC20 token (not ETH) at the (N-4)th block. How can I get this balance.
I did my search and the only way is to use etherscan's API, which is not ok for heavy use. There are other people here and there asking similar questions and I totally feel their frustration.
Thank you.
Update on Apr 5.
I want to give more details about my attempts so far.
1) I am using Ubuntu 16.04 and geth 1.8.2-stable.
2) I started with running Ganache, the app with graphical UI.
3) My token is almost the same as the one in the official doc https://ethereum.org/token.
4) I deployed the token using eth.accounts[0]
in geth (ganache generates 10 accounts with each holding 100 initial ETH for me)
$ geth attach http://localhost:8545
var tokenABI = [...];
var tokenFactory = eth.conract(tokenABI);
var byteCode = "0x" + "606..."
var token = tokenFactory.new(
100,
"TestCoin",
"TSC",
{
from: eth.accounts[0], // owner
data: byteCode,
gas: 4700000
}, function(e, contract) {});
5) I did the following transactions:
// 3 ETH transactions
eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(5, "ether") });
eth.sendTransaction({from: eth.accounts[1], to: eth.accounts[2], value: web3.toWei(3, "ether") });
eth.sendTransaction({from: eth.accounts[2], to: eth.accounts[3], value: web3.toWei(1, "ether") });
// 3 token transfers
token.transfer(eth.accounts[1], web3.toWei(5, 'ether'), { from: eth.accounts[0] }, function(err, contract) {})
token.transfer(eth.accounts[2], web3.toWei(3, 'ether'), { from: eth.accounts[1] })
token.transfer(eth.accounts[3], web3.toWei(1, 'ether'), { from: eth.accounts[2] })
For the token, I expect the ending balance to be
account 0: 95
account 1: 2
account 2: 2
account 3: 1
My eth.blockNumber
shows 7 blocks, which is correct (3 eth transfer, 1 contract creating, 3 token transfer). Any balance of account 3 is definitely less than 1 in ealier blocks. However, the following command returns 1 ether (in unit of Wei) for me:
> token.balanceOf(eth.accounts[3], 0, function(err, res) {console.log(err, res};)
null 1000000000000000000
undefined
No matter how I change that number, from 0 to 7, I always get the same output.
BTW, I have no trouble retrieving ETH holding in earlier blocks. This only happens with the Token. One thing I did notice is that my eth.syncing
returns false
, maybe because I am using Ganache?
rollback
in blockchains. You may be referring to chain split, when someone mines 2 forks of a chain of blocks. The longer chain wins, and the node just deletes the shortest chain , and switches to the longest chain. Tokens are variables in the state , so the variables on the longest chain are chosen, that's it.token.balanceOf(accountHash, {}, blockNumber)
? It makes no sense to me that this function should exist on-chain. Also, all storage is reverted when the chain is forked; thus mappings also. Ethereum chain rollbacks should never happen, this ruins the entire idea behind Ethereum, since now a centralized organisation can choose to do a "hard-fork" of the entire chain.balanceOf
function, I read it here ethereum.stackexchange.com/questions/42783/…