Solidity low-level call 直接通过合约地址和 calldata 读写其他合约
有时候遇到一些没开源且没有找 ABI 的项目,可以通过此技术直接去调用合约,进而实现一些操作。
直接上代码,注意注释中的说明。
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;
contract TestCall {
// 调用其他合约的接口,注意不要被滥用,这个接口可以让调用人以当前合约地址的身份执行任意操作
function call(address payable to, bytes calldata data)
public
returns (bool, bytes memory)
{
return to.call(data);
}
// 测试的读接口,测试时直接部署两个实例互相调用即可
function testRead(uint256 x) public pure returns (uint256) {
return x;
}
uint256 public y;
// 测试的写接口,从 A 合约的 call 调用 B 合约的写接口,然后看 B 合约的 y 值是否成功被更新
function testWrite(uint256 x) public {
y = x;
}
// 计算方法的 sig,注意参数是不需要名称的,也不需要返回值,只需要方法名和参数类型列表
function getFuncSig(string calldata sig) public pure returns (bytes4) {
// testRead(uint256)
// testWrite(uint256)
return bytes4(keccak256(bytes(sig)));
}
// 编码要调用的方法和参数
function getCallData(bytes4 sig, uint256 x)
public
pure
returns (bytes memory)
{
return abi.encodeWithSelector(sig, x);
}
}
当我们学会这种 low-level call 之后后面遇到想要操作的项目,不需要知道 abi 也可以操作了。