以太坊JSON RPC手册

eth_getStorageAt

返回指定地址存储位置的值。

参数

  • DATA - 20字节,存储地址
  • QUANTITY - 存储中的位置号
  • QUANTITY|TAG - 整数块号,或字符串"latest"、"earliest" 或"pending"

返回值

DATA - 指定存储位置的值

示例代码

根据要提取的存储计算正确的位置。考虑下面的合约,由0x391694e7e0b0cce554cb130d723a9d27458f9298 部署在地址0x295a70b2de5e3953354a6a8344e616ed314d7251

contract Storage {
    uint pos0;
    mapping(address => uint) pos1;

    function Storage() {
        pos0 = 1234;
        pos1[msg.sender] = 5678;
    }
}

提取pos0的值很直接:

curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x0", "latest"], "id": 1}' localhost:8545

响应结果:

{"jsonrpc":"2.0","id":1,"result":"0x00000000000000000000000000000000000000000000000000000000000004d2"}

要提取映射表中的成员就难一些了。映射表中成员位置的计算如下:

keccack(LeftPad32(key, 0), LeftPad32(map position, 0))

这意味着为了提取pos1["0x391694e7e0b0cce554cb130d723a9d27458f9298"]的值,我们需要如下计算:

keccak(decodeHex("000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001"))

geth控制台自带的web3库可以用来进行这个计算:

> var key = "000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298" + "0000000000000000000000000000000000000000000000000000000000000001"
undefined
> web3.sha3(key, {"encoding": "hex"})
"0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9"

现在可以提取指定位置的值了:

curl -X POST --data '{"jsonrpc":"2.0", "method": "eth_getStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9", "latest"], "id": 1}' localhost:8545

相应结果如下:

{"jsonrpc":"2.0","id":1,"result":"0x000000000000000000000000000000000000000000000000000000000000162e"}