Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solidity合约调用 #36

Open
wujunchuan opened this issue Nov 29, 2020 · 0 comments
Open

Solidity合约调用 #36

wujunchuan opened this issue Nov 29, 2020 · 0 comments

Comments

@wujunchuan
Copy link
Owner

ETH JSON PRC中的 eth_call 是ETH与Solidity合约进行交互的方法

JSON PRC中eth_call的参数手动生成过程

回家看了下Solidity Contract文档, 配合Stack Overflow上的一个问题, 大概知道那一串data是怎么生成的了, 可以来看看这个相关回答

Get token balance with Ethereum RPC?

简单来说就是几个步骤

  1. 对合约方法做一次 keccak-256 hash 运算

    eg: **Web3.sha3("balanceOf(address)")**HexBytes('0x70a08231b98ef4ca268c9cc3f6b4590e4bfec28280db06bb5d45e689f2a360be')

  2. 💡 取前4 bytes(16进制字符串的8个字符) 得 **70a08231**

  3. 💡 合约地址前面补齐到32 bytes**0000000000000000000000000b88516a6d22bf8e0d3657effbd41577c5fd4cb7**

  4. 拼接步骤2, 步骤3 所得的字符串 最后结果得到 **0x70a082310000000000000000000000000b88516a6d22bf8e0d3657effbd41577c5fd4cb7**

  5. 将所得的到的data作为JSON PRC发送给合约

    curl -X POST --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to": "0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0", "data":"**0x70a082310000000000000000000000000b88516a6d22bf8e0d3657effbd41577c5fd4cb7**"}, "latest"],"id":67}' -H "Content-Type: application/json" [http://127.0.0.1:8545](http://127.0.0.1:8545/)

    得到的响应为

    {"jsonrpc":"2.0","id":67,"result":"**0x00000000000000000000000000000000000000000000014a314d9ff9b20b9800**"}

    这个result就是合约调用的结果了, 以 balanceOf 为例, 一般还会去获取这个Token的精度(同样也是合约方法, decimals)

使用库调用eth_call

搞清楚这一串东西的生成并没有什么卵用, 不过搞清楚了一点, eth_call 协议中的data是包含合约的参数与合约的方法名的, 另外一个参数 to 则是指明了合约地址

我们并不需要每次都去手动生成这一串data与JSON PRC做交互, 还是以前端中的 web3.js 为例

async function getErc20Balance() {
  const from = web3.eth.accounts[0];
  let tokenAddress = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
  let walletAddress = from;
  // ABI是个毛, Contract Application Binary Interface (ABI) 就是描述合约的结构啥的
  let contract = web3.eth.contract(ABI).at(tokenAddress);
  contract.balanceOf(walletAddress, (error, balance) => {
    document.getElementById("getBalanceResult").innerHTML = balance;
    // Get decimals
    contract.decimals((error, decimals) => {
      // calculate a balance
      balance = balance.div(10**decimals);
      document.getElementById("getBalanceResult").innerHTML = balance;
      console.log(balance.toString());
    });
  });
}

什么是multicall

我们已经可以调用ERC20发行的代币合约来获取余额, 也写了一个小Demo实现了对应逻辑, 客户端联调也没问题

那为什么在调试UniSwap 就不行呢?

后来我发现他们的data前缀不一样啊, 就如同开头所说的, 0x70a08231 这个前缀是通过hash合约方法名称得来的, 也就是这个开头的前缀都是调用合约中的 balanceof 方法的JSONPRC调用

问题已经很明显了, UniSwap 这个Dapps并不是调用ERC20合约中的balanceof 方法, 而是调用其他方法, 我顺藤摸瓜找到了

总结说就是他们在ETH部署了一个可以并发调用合约方法的合约方法, 名字叫 multiCall

也难怪他们的data有50kb多

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant