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 也可以操作了。

Comments