-
Notifications
You must be signed in to change notification settings - Fork 11
Description
ETH JSON PRC中的 eth_call 是ETH与Solidity合约进行交互的方法
JSON PRC中eth_call的参数手动生成过程
回家看了下Solidity Contract的文档, 配合Stack Overflow上的一个问题, 大概知道那一串data是怎么生成的了, 可以来看看这个相关回答
Get token balance with Ethereum RPC?
简单来说就是几个步骤
-
对合约方法做一次
keccak-256 hash运算eg:
**Web3.sha3("balanceOf(address)")**得HexBytes('0x70a08231b98ef4ca268c9cc3f6b4590e4bfec28280db06bb5d45e689f2a360be') -
💡 取前
4 bytes(16进制字符串的8个字符) 得**70a08231** -
💡 合约地址前面补齐到
32 bytes得**0000000000000000000000000b88516a6d22bf8e0d3657effbd41577c5fd4cb7** -
拼接步骤2, 步骤3 所得的字符串 最后结果得到
**0x70a082310000000000000000000000000b88516a6d22bf8e0d3657effbd41577c5fd4cb7** -
将所得的到的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 方法, 而是调用其他方法, 我顺藤摸瓜找到了
- 合约地址: https://etherscan.io/address/0xeefba1e63905ef1d7acba5a8513c70307c1ce441#contracts
- GItHub地址: https://github.com/makerdao/multicall
- 相关论文 https://odr.chalmers.se/bitstream/20.500.12380/300760/1/CSE 20-07 Hughes ODR.pdf
总结说就是他们在ETH部署了一个可以并发调用合约方法的合约方法, 名字叫 multiCall
也难怪他们的data有50kb多