如何導出映射到賬戶的儲存密鑰?
我試圖通過將帳戶(這裡的帳戶表示 ERC20 餘額映射*映射(地址 => uint256)*中的關鍵地址)映射到奇偶交易跟踪中的相應儲存密鑰來得出帳戶儲存的更改。
交易https://etherscan.io/tx/0x210cfe3d3b62f415ed0327a3c6177086df4937b6280031255360b6d137308554的範例跟踪(通過 web3.py 獲取)是:
{ 'output': '0x', 'stateDiff': { '0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5': { 'balance': { '*': { 'from': '0x122291885d6222bc5ec', 'to': '0x12229193ca3f58565ec' } }, 'code': '=', 'nonce': '=', 'storage': {} }, '0xaddba95f769b5d42c02e144102817eab9d00efd3': { 'balance': '=', 'code': '=', 'nonce': '=', 'storage': { '0x1ded6755a6d7d843883da8cd8948931cf9f8b1e8f8983ad77e1685ece0b92fc2': { '*': { 'from': '0x0000000000000000000000000000000000000000000000000000000000000000', 'to': '0x000000000000000000000000000000000000000000000000000bfb8d0ebc5000' } }, '0x5020d77d5345022a5466af6f78731b10f92d31e17961c23ea6ce5c185dc75d49': { '*': { 'from': '0x0000000000000000000000000000000000000000000000000000000000000000', 'to': '0x0000000000000000000000000000000000000000000000000000e1412a5f1c00' } } } }, '0xf2eeb980b60b9ed146636c65ecc5e8f27a8aed40': { 'balance': { '*': { 'from': '0x2c4c7111f4801a8', 'to': '0x2c410434bee61a8' } }, 'code': '=', 'nonce': { '*': { 'from': '0x143', 'to': '0x144' } }, 'storage': {} } }, 'trace': [{ 'action': { 'callType': 'call', 'from': '0xf2eeb980b60b9ed146636c65ecc5e8f27a8aed40', 'gas': '0x9008', 'input': '0xa9059cbb000000000000000000000000e034e561ce112c5f261f15d447e8f2436d9625040000000000000000000000000000000000000000000000000000e130de0be000', 'to': '0xaddba95f769b5d42c02e144102817eab9d00efd3', 'value': '0x0' }, 'result': { 'gasUsed': '0x3924', 'output': '0x' }, 'subtraces': 0, 'traceAddress': [], 'type': 'call' }], 'vmTrace': None }
根據https://solidity.readthedocs.io/en/v0.4.24/miscellaneous.html#layout-of-state-variables-in-storage,“映射鍵 k 對應的值位於 keccak256(k . p ) 其中 . 是連接”。根據 “keccack(LeftPad32(key, 0), LeftPad32(map position, 0))” https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getstorageat,我知道必要的左墊,儘管散列函式似乎已經在內部處理了這個問題。
我為這個 keccak256 儲存密鑰嘗試了 Web3.sha3(),StackOverflow 上的其他問題提到 Solidity 使用了稍微不同的雜湊算法。然而,還可以通過使用合適的Web3.soliditySha3()我不會在一個雜湊會出現我在跟踪(在這裡,關鍵找到到達0x1ded6755a6d7d843883da8cd8948931cf9f8b1e8f8983ad77e1685ece0b92fc2或0x5020d77d5345022a5466af6f78731b10f92d31e17961c23ea6ce5c185dc75d49)的帳戶0xf2eeb980b60b9ed146636c65ecc5e8f27a8aed40。
什麼是正確的方法(最好使用 web3.py)來散列帳戶和位置以獲得映射儲存密鑰?
正如@jaime 在評論中提到的,您需要映射變數的 來查找和
position
之間的關係。address``storage key
您可以在下面找到我編寫的用於檢測
position
基本 erc20 合約的程式碼(使用 web3.py):import json from web3.auto.infura import w3 from eth_utils import remove_0x_prefix, to_int, to_checksum_address, to_hex # erc20 contract address CONTRACT_ADDRESS = '0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7' # address with non zero token balance HOLDER_ADDRESS = '0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb' def getStorageAtIndex(i): pos = str(i).rjust(64, '0') key = remove_0x_prefix(HOLDER_ADDRESS).rjust(64, '0').lower() storage_key = to_hex(w3.sha3(hexstr=key + pos)) return to_int(w3.eth.getStorageAt(CONTRACT_ADDRESS, storage_key)) for i in range(0, 20): if getStorageAtIndex(i) != 0: print("position is {}".format(i))
結果:
>>> position is 5
一旦你有了正確的位置值,你就可以輕鬆地獲取儲存在合約中的值。
pos = str(5).rjust(64, '0') key = remove_0x_prefix(HOLDER_ADDRESS).rjust(64, '0').lower() storage_key = to_hex(w3.sha3(hexstr=key + pos)) w3.eth.getStorageAt(CONTRACT_ADDRESS, storage_key)