使用 Metamask 进行 RPC 调用

RPC call with Metamask

我想使用 metamask 从我的应用创建一个 RPC 调用(研究目的)。

我的合同方法是:

function sayHelloMyName(string memory _name) external pure returns (string memory) {      
        require(bytes(_name).length != 0, "insert your name");
        return string(abi.encodePacked("hello ", _name));
    }

它的哈希值是:

$ web3.utils.keccak256("sayHelloMyName(string)").substr(0, 10)
> '0x10a7b27a'

我想传递我的名字 foo,其中十六进制小数是 0x666f6f

web3.utils.toHex('foo')
'0x666f6f'

所以我的电话是:

ethereum
    .request({
      method: 'eth_call',
      params: [
        {
          from: currentAccount,
          to: contractAddress,
          data: 0x10a7b27a0000000000000000000000000000000000000000000000000000000000666f6f
        }, "latest"],
    })
    .then((txHash) => {
      console.log(txHash);
      $('#info').html(txHash);
    })
    .catch((error) => {
      console.error;
      $('#info').text(JSON.stringify(error.message));
    });

其中数据是方法签名,以及我的十六进制名称和填充(共 32 个字节) 不幸的是,我得到了它的还原。

{
    "jsonrpc": "2.0",
    "id": 1,
    "error": {
        "code": -32000,
        "message": "execution reverted"
    }
}

代码有效,我可以将它与 web3 库一起使用。

Solidity string 被编码为 dynamic-length 字节数组,包括指向数组开始位置的第一个 32 字节槽和包含字符串长度的第二个 32 字节槽。含义:不仅仅是您传递的字符串的十六进制值

它与 web3js 一起工作,因为 JS 库 解码 十六进制返回字符串 (web3 假定输入是十六进制,因为它以 0x),然后 将其正确编码 到字节数组,同时填充 data 字段。

查看此 web3js 片段的输出

const data = web3.eth.abi.encodeFunctionCall({
    name: 'sayHelloMyName',
    type: 'function',
    inputs: [{
        type: 'string',
        name: '_name'
    }]
}, [
    'foo',
]);
console.log(data);

打印

# formatted for readability
0x10a7b27a
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000003
666f6f0000000000000000000000000000000000000000000000000000000000
  • 第一个槽是指向数组开始位置的指针。在这种情况下 (hex20 == dec32) 这是第二个插槽的开始。
  • 第二个插槽(值 3)是值的长度
  • 第三个插槽包含字符串的实际 hex-encoded 值

解决方案:这个长值(没有换行符)是你需要传递的。