optimism
optimism copied to clipboard
State trie does not include account balance
(NOTE: I'm doing this all on Kovan.)
There is an account (not a contract, so no code) 0xbb6e024b9cffacb947a71991e386681b1cd1477d which has one transaction (so nonce of 1) and has a balance of 0xdb622511b495578. If I call {"id":1,"jsonrpc":"2.0","method":"eth_getProof","params":["0xbb6e024b9cffacb947a71991e386681b1cd1477d",[],"0x71e5f"]} I get the following account proof (as an array, of course).
0xf90211a006c430227b546beba3164b6d84b621e90dc3f477584252f26ac9057ed924e1caa061e84e6665c09cf8c489ef9603fd4d01283688110a76a70ef397691b22576dfba038d24f342998553fff71509a2265fff8be70cbfa350e9821ee2e53f4e3c602ffa050c2d2fe2e2cc30782481c01ce40e551c099a37204efd217f3e9e05f48f2c01ba0887e25d963867772a2a171728adf8d061fa9b8e2d8df3452b8807bd5892acc75a0080641c78b6d2917ba0471a6619df079622d2f5b6868244633419bd0a3a401f5a0c99eef36065f4beb1330e58fcc4a48d9734ce3844f5d9f14d245597d4701168da02b578f305eb2d7b46b1732330c6eb0deadec58234efa555e3a5ba55847fbb9fba03edcc2b3869aa3b2fb2dcebce053d6c1621bab3ad6130e842f24d528f66349d4a05df5703c246c1cd9b1014c9938d0fef3003849d968e9b111a14424609f0da533a04e3d535c127d699e371782ffaa06a0fd75347ab43b972cafd6979135fc62380aa00560aedaea819e3d1764a362b7034bd39d3383575e3e6681035a2627615839e3a00fc423c1199f1557d4855a5f046182e738b3340628547f4f59341f49aa04e36ca041c2e9903217c3cf0e51818f6a630eb8647e0710acb785e5ed0c99787d9f4199a0750a6ace4c84cccaa83f817b8846ec63aa12c357e4ff8d1dab51a7dbcbdffe77a010b098d8957c680c09529e5debcd5e6937b7a34412635fd6e00cef176f11b70780
0xf90211a0e6a2bc2b5a4f0ef037a7b0c62cddf2461ca19a7bf61a20967b71a6649e6a6616a07f835477b15578c807a8c0f36afdf258010103c878041af3a834e2c51b506008a045b194548be66e2fecce695beda43f9abb10f5494ef900d24e38fd514b4b6ec7a0b7b99a9f74df9691fb200df5a150a66e5e07c6e9c2d77e456bbb3d3ff24d1023a0f3c74d209d0954716e051f3dddd43562a2586547ddaa96152ba447b1cdecd800a002c131838a3043be03d19cebef5915d29c4cc302cc06a865295439fc13ff811fa0783d04384a6d3ce3fc42620d5b7c34f53aa95893a663898a6b263152ff425097a0b52b8e09f6d1d1ba106b305afbad3441b4f01a34cf062de1e8c7612ab69543e0a0c920a8f26a0b84575aa2afabbc183c5820f092a745d4a61dc3bf1d413faceb4da0d8c1a66cf4093e6b76a5cd6573558f58269d1738a3afafe8930e8b285c5d519da0acef5025c9b5c47cda4b8fd773c8c9287f615dd98c951ceff6e5a0354d2454b7a0b8dbac1b3a9815d5aa2dc48bd2e02c67772cf6d85f44ca21e789542bb55da767a04e8b0608667f7d79691a40bc2029d142858bfa9551109ea49282a8ee3da11d86a052ea6fbeac9e7e132d769a69b8789bdfbbe197ba9cb24a6715e38b64404aa660a0387d7cbac23ac82464ca82c78fa241cb33200ce103db301ec735a4edf2f0ab1ea0859e20f884a05691ec0f8267ea244d9e81a6782650954c62518213ab424e820680
0xf90211a04b2851f64d4acf1d18dec51e5e7ac62c192541f6611ab928bfcd39c758352989a0e9d084e45d0842e6ebb229af53d51154a59a49871ec1047b91220617a706d997a0fb3e538a445788f3ed319c79c168dc58b85180770a213f68ec98f5be36b17f6ba052baf22a1636293fe428710d68def39ad5a3a8e150989e5cb7fd77930e5cdcc7a09643ef3202ef9c6ca509683a808c100f61335caf04edf91dec0dbcb36ac3177ba058d1ca5eb72fccc2ebdc900a0b7b47db78f5e8d77355ae75ded62c634de6cc99a041200707b1365119a9b472d7828012176134f76baa7e6aa6fe4399dd034d23e3a0f7dd18bc54ea05cff0ca1b38a773ee4cfa2be0c894371acc348562c06cf28ff6a09304c2c3e2fa7af582d0fb7cafc8726fd68bff757daf4f4029e46c5137410721a0d2217b1facded685a9a9115ce8af33445dee89c34c9f33ff75ca5a35316f0bbba016cf471a0b93ec04a7bd8e844b7e044fb52e2733b2d2df247c924243c2d93b8da0e84676af6d5fdf706a6ac6e1fd176140f5761986f008e805d36863bfb296bc97a0417f487c12f90bfb04a4b27143b21b7cdce7e43574d4ca8726c86e61faa72635a081125d04f8b6e60770cad301cbb76407ff3ea2fdb7119ae7b1dd97614c82180ea079c6c0cb4cf947da4e6588e01524c1ac483bbd9d62847ded16c13e879f68ced2a0ad83db9f71843840651418ae1d56f23c67e49d4a454d34dd156847cecc4d08f280
0xf90211a0b94b7e5ba6dde76d261466c89b5f69fa0d745100f39bab5b71ceda8840bd9507a0cf0aa7e20d836923808222b12dcd3d7e98db5eaf823456932960024caf473e68a00005370699cb8861bbb8d47aaedbc9d85f2967ba8d954feea3a7ea999d36f3fea09c826f9c1bde6493abd77f86a6b8cc8b930ce95bb44d6ea6e8108c1d396ebb7da0ee6fb5d314fd9d59f2ad812218f89467fc1699a14e39abd7cd16b35ad085f300a0bee7e2fb4e1296880da9b7efd78189679bcd7884656a8a8d452e583e2b0738eda099c30aa65eda1dc649398c599cf1b681c66e27e5deaed8ee9086a033a0927b79a0ac7535b93a2eac84be1b1a88b87b16785bb75e4d28c26b0428f8f58716c08cb8a0588a282aada2bcba58d0d166fa20b774a711f303426f3ab395c40cb3eb581e61a084d18a3c9a834bff8b2113e57002286a9a33fe7113b5f11e21f556388db20d8aa0d50a47da1f6901315885d00e13f74b235ea98608ff2097e2c858dbaa4e50fe40a038c7776f3c9b76253c092e1d169030214b060c20044423719a106909827bc664a0673c5d78b86bd91158dad473b0a1d019d49bda2e2a61708b7069089671f3e917a0568ab1887bb31b1b657f5d3b2ac999d3cdc831cd7d1e0174f3e483acec5a3c1ba0c7d0f9c1e9f52efb0b251b9dbfd969d6ce162f627d8f4bd78f346f1fd5087a6ba0349096ce53c1a4807efbe0d04bc83518c857ef7a1ba09ab6d0d4784ad8b80a7280
0xf87180808080a0f01ef1fb2ff272c22313714c9ec9c69d6f7bb111cd0de717e40e50427271643280a0e71126df0ccae05cdb11a52bab6e3d5906f5837e3d2d2c7e8b40653ebe735439a01b2acb35425d8f0691d5b275c9c78bb3fc06b99cc36f3bffc7f636347c247369808080808080808080
0xf8679e3b8cadc5141e6bbd119c6c5180930088f5fe3dcd28e24883d0825eb8dd01b846f8440180a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
Here is then the hashes of those 6 nodes, for reference.
0x1e35ea0142f552715bfc84fd915137ccbf034b79c93f883ff06f1ebf7dd44700
0x2b578f305eb2d7b46b1732330c6eb0deadec58234efa555e3a5ba55847fbb9fb
0x859e20f884a05691ec0f8267ea244d9e81a6782650954c62518213ab424e8206
0x9643ef3202ef9c6ca509683a808c100f61335caf04edf91dec0dbcb36ac3177b
0xee6fb5d314fd9d59f2ad812218f89467fc1699a14e39abd7cd16b35ad085f300
0x1b2acb35425d8f0691d5b275c9c78bb3fc06b99cc36f3bffc7f636347c247369
The state root for block 0x71e5f is in fact 0x1e35ea0142f552715bfc84fd915137ccbf034b79c93f883ff06f1ebf7dd44700, so this is at least going in the right direction, as the root node has the correct hash.
We are looking for 0xbb6e024b9cffacb947a71991e386681b1cd1477d, which hashes to 0x7f447b8cadc5141e6bbd119c6c5180930088f5fe3dcd28e24883d0825eb8dd01. Let's work through each layer and verify the proof.
0:{06c430227b546beba3164b6d84b621e90dc3f477584252f26ac9057ed924e1ca}
1:{61e84e6665c09cf8c489ef9603fd4d01283688110a76a70ef397691b22576dfb}
2:{38d24f342998553fff71509a2265fff8be70cbfa350e9821ee2e53f4e3c602ff}
3:{50c2d2fe2e2cc30782481c01ce40e551c099a37204efd217f3e9e05f48f2c01b}
4:{887e25d963867772a2a171728adf8d061fa9b8e2d8df3452b8807bd5892acc75}
5:{080641c78b6d2917ba0471a6619df079622d2f5b6868244633419bd0a3a401f5}
6:{c99eef36065f4beb1330e58fcc4a48d9734ce3844f5d9f14d245597d4701168d}
7:{2b578f305eb2d7b46b1732330c6eb0deadec58234efa555e3a5ba55847fbb9fb}
8:{3edcc2b3869aa3b2fb2dcebce053d6c1621bab3ad6130e842f24d528f66349d4}
9:{5df5703c246c1cd9b1014c9938d0fef3003849d968e9b111a14424609f0da533}
A:{4e3d535c127d699e371782ffaa06a0fd75347ab43b972cafd6979135fc62380a}
B:{0560aedaea819e3d1764a362b7034bd39d3383575e3e6681035a2627615839e3}
C:{0fc423c1199f1557d4855a5f046182e738b3340628547f4f59341f49aa04e36c}
D:{41c2e9903217c3cf0e51818f6a630eb8647e0710acb785e5ed0c99787d9f4199}
E:{750a6ace4c84cccaa83f817b8846ec63aa12c357e4ff8d1dab51a7dbcbdffe77}
F:{10b098d8957c680c09529e5debcd5e6937b7a34412635fd6e00cef176f11b707}
X:{}
7 is 0x2b578f305eb2d7b46b1732330c6eb0deadec58234efa555e3a5ba55847fbb9fb: good.
0:{e6a2bc2b5a4f0ef037a7b0c62cddf2461ca19a7bf61a20967b71a6649e6a6616}
1:{7f835477b15578c807a8c0f36afdf258010103c878041af3a834e2c51b506008}
2:{45b194548be66e2fecce695beda43f9abb10f5494ef900d24e38fd514b4b6ec7}
3:{b7b99a9f74df9691fb200df5a150a66e5e07c6e9c2d77e456bbb3d3ff24d1023}
4:{f3c74d209d0954716e051f3dddd43562a2586547ddaa96152ba447b1cdecd800}
5:{02c131838a3043be03d19cebef5915d29c4cc302cc06a865295439fc13ff811f}
6:{783d04384a6d3ce3fc42620d5b7c34f53aa95893a663898a6b263152ff425097}
7:{b52b8e09f6d1d1ba106b305afbad3441b4f01a34cf062de1e8c7612ab69543e0}
8:{c920a8f26a0b84575aa2afabbc183c5820f092a745d4a61dc3bf1d413faceb4d}
9:{d8c1a66cf4093e6b76a5cd6573558f58269d1738a3afafe8930e8b285c5d519d}
A:{acef5025c9b5c47cda4b8fd773c8c9287f615dd98c951ceff6e5a0354d2454b7}
B:{b8dbac1b3a9815d5aa2dc48bd2e02c67772cf6d85f44ca21e789542bb55da767}
C:{4e8b0608667f7d79691a40bc2029d142858bfa9551109ea49282a8ee3da11d86}
D:{52ea6fbeac9e7e132d769a69b8789bdfbbe197ba9cb24a6715e38b64404aa660}
E:{387d7cbac23ac82464ca82c78fa241cb33200ce103db301ec735a4edf2f0ab1e}
F:{859e20f884a05691ec0f8267ea244d9e81a6782650954c62518213ab424e8206}
X:{}
F is 0x859e20f884a05691ec0f8267ea244d9e81a6782650954c62518213ab424e8206: good.
0:{4b2851f64d4acf1d18dec51e5e7ac62c192541f6611ab928bfcd39c758352989}
1:{e9d084e45d0842e6ebb229af53d51154a59a49871ec1047b91220617a706d997}
2:{fb3e538a445788f3ed319c79c168dc58b85180770a213f68ec98f5be36b17f6b}
3:{52baf22a1636293fe428710d68def39ad5a3a8e150989e5cb7fd77930e5cdcc7}
4:{9643ef3202ef9c6ca509683a808c100f61335caf04edf91dec0dbcb36ac3177b}
5:{58d1ca5eb72fccc2ebdc900a0b7b47db78f5e8d77355ae75ded62c634de6cc99}
6:{41200707b1365119a9b472d7828012176134f76baa7e6aa6fe4399dd034d23e3}
7:{f7dd18bc54ea05cff0ca1b38a773ee4cfa2be0c894371acc348562c06cf28ff6}
8:{9304c2c3e2fa7af582d0fb7cafc8726fd68bff757daf4f4029e46c5137410721}
9:{d2217b1facded685a9a9115ce8af33445dee89c34c9f33ff75ca5a35316f0bbb}
A:{16cf471a0b93ec04a7bd8e844b7e044fb52e2733b2d2df247c924243c2d93b8d}
B:{e84676af6d5fdf706a6ac6e1fd176140f5761986f008e805d36863bfb296bc97}
C:{417f487c12f90bfb04a4b27143b21b7cdce7e43574d4ca8726c86e61faa72635}
D:{81125d04f8b6e60770cad301cbb76407ff3ea2fdb7119ae7b1dd97614c82180e}
E:{79c6c0cb4cf947da4e6588e01524c1ac483bbd9d62847ded16c13e879f68ced2}
F:{ad83db9f71843840651418ae1d56f23c67e49d4a454d34dd156847cecc4d08f2}
X:{}
4 is 0x9643ef3202ef9c6ca509683a808c100f61335caf04edf91dec0dbcb36ac3177b: good!
0:{b94b7e5ba6dde76d261466c89b5f69fa0d745100f39bab5b71ceda8840bd9507}
1:{cf0aa7e20d836923808222b12dcd3d7e98db5eaf823456932960024caf473e68}
2:{0005370699cb8861bbb8d47aaedbc9d85f2967ba8d954feea3a7ea999d36f3fe}
3:{9c826f9c1bde6493abd77f86a6b8cc8b930ce95bb44d6ea6e8108c1d396ebb7d}
4:{ee6fb5d314fd9d59f2ad812218f89467fc1699a14e39abd7cd16b35ad085f300}
5:{bee7e2fb4e1296880da9b7efd78189679bcd7884656a8a8d452e583e2b0738ed}
6:{99c30aa65eda1dc649398c599cf1b681c66e27e5deaed8ee9086a033a0927b79}
7:{ac7535b93a2eac84be1b1a88b87b16785bb75e4d28c26b0428f8f58716c08cb8}
8:{588a282aada2bcba58d0d166fa20b774a711f303426f3ab395c40cb3eb581e61}
9:{84d18a3c9a834bff8b2113e57002286a9a33fe7113b5f11e21f556388db20d8a}
A:{d50a47da1f6901315885d00e13f74b235ea98608ff2097e2c858dbaa4e50fe40}
B:{38c7776f3c9b76253c092e1d169030214b060c20044423719a106909827bc664}
C:{673c5d78b86bd91158dad473b0a1d019d49bda2e2a61708b7069089671f3e917}
D:{568ab1887bb31b1b657f5d3b2ac999d3cdc831cd7d1e0174f3e483acec5a3c1b}
E:{c7d0f9c1e9f52efb0b251b9dbfd969d6ce162f627d8f4bd78f346f1fd5087a6b}
F:{349096ce53c1a4807efbe0d04bc83518c857ef7a1ba09ab6d0d4784ad8b80a72}
X:{}
4 is 0xee6fb5d314fd9d59f2ad812218f89467fc1699a14e39abd7cd16b35ad085f300: good!
0:{}
1:{}
2:{}
3:{}
4:{f01ef1fb2ff272c22313714c9ec9c69d6f7bb111cd0de717e40e504272716432}
5:{}
6:{e71126df0ccae05cdb11a52bab6e3d5906f5837e3d2d2c7e8b40653ebe735439}
7:{1b2acb35425d8f0691d5b275c9c78bb3fc06b99cc36f3bffc7f636347c247369}
8:{}
9:{}
A:{}
B:{}
C:{}
D:{}
E:{}
F:{}
X:{}
7 is 0x1b2acb35425d8f0691d5b275c9c78bb3fc06b99cc36f3bffc7f636347c247369: good!
This brings us to the last node in our proof, a leaf node, whose hash we already know is correct. For context, we are still looking for 0x...b8cadc5141e6bbd119c6c5180930088f5fe3dcd28e24883d0825eb8dd01 (having removed 0x7f447... from the front already while drilling down through the trie).
0:{3b8cadc5141e6bbd119c6c5180930088f5fe3dcd28e24883d0825eb8dd01}
1:{f8440180a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470}
I frankly don't remember the deal with the first nibble there (and don't feel a need to look it up), but it is some kind of type code and changes our subsequent offset... whatever: we skip that 3 and the rest of it is correct, so this is clearly the leaf node we are looking for; let's decode it!!
0:{01}
1:{}
2:{56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421}
3:{c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470}
OK: this is supposed to be {0:nonce, 1:balance, 2:storagehash, 3:codehash}. The nonce is correct, the codehash is correct (hash of 0x), the storagehash is also correct (hash of 0x80, which is an empty trie)... but the balance here is 0... which we know is wrong... because it is supposed to be 0xdb622511b495578 :(.
The problem, of course, is that this isn't just some bug in the API result, as I just verified the entire thing down to this leaf node... which makes me think this is actually a pretty deep bug in Optimism, right? :(
Ah I can see how this is confusing. This isn't actually a bug, it has to do with a holdover from the previous version of the OVM. At least for now, balances are being stored in a smart contract and not in the state trie. Here's the snippet of Geth code that pulls out the balances: https://github.com/ethereum-optimism/optimism/blob/ecef6714b8c207b50a8c4e83328b6dd621bcebc0/l2geth/core/state/statedb.go#L243
You can see here that we're extracting the balance from the state of a smart contract (OVM_ETH) and not from the trie. We're hoping to resolve this diff as part of the next major upgrade of the system, with time pressures for the OVM 2.0 upgrade we decided to keep the OVM_ETH contract (and this diff) for now.
We use this contract to mint people ETH on L2 when they make ETH deposits, and it also gave us the option to have ETH be an ERC20 token (see discussion here: https://github.com/ethereum-optimism/optimism/discussions/1444). We will most likely fork out the OVM_ETH contract entirely and transition all balances to the trie.
There's a small snippet about this in the docs: https://community.optimism.io/docs/developers/l2/differences.html#using-eth-in-contracts
For tooling developers and infrastructure providers, please note that ETH is still represented internally as an ERC20 token at the address 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000 (opens new window). As a result, user balances will always be zero inside the state trie and the user's actual balance will be stored in the aforementioned token's storage. It is NOT possible to call this contract directly, it will throw an error.