什么是智能合约 ABI
ABI = Specification for encoding and decoding
非常精炼的一句话:一套用来编码和解码的规范。
注意与合约字节码(bytecode)要区分开,字节码只是一串用十六进制数表示的 EVM 操作码。
在 Solidity 文档中描述为:
“ABI 是与以太坊生态系统中的合约交互的标准方式。既来自区块链外部,也用于合约之间的交互”。
什么是合约的JSON ABI
JSON ABI specification for functions
JSON ABI specification for events
合约内部函数和事件的编码规范。
(1)abi.encodeWithSignature
函数签名:
abi.encodeWithSignature(string memory signature, …args) returns (bytes memory)
代码示例:
// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.7.0 <0.9.0;contract A {function callBTest(address _address,uint256 _num,string memory _message) public returns (bool) {(bool success, ) = _address.call(abi.encodeWithSignature("test(uint256,string)", _num, _message));return success;}}contract B {uint256 public num;string public message;function test(uint256 _num, string memory _message)publicreturns (uint256, string memory){num = _num;message = _message;return (num, message);}}
我们在合约A中通过call的方式,使用内置函数abi.encodeWithSignature对合约B的test函数进行调用。第一个参数为被调用函数的签名(不能包含形参和空格),后面是类似js的剩余参数,给被调用函数传参的(顺序要对应)。
注:test(uint256,string)与test(uint,string)签名哈希是不一样的!
测试:
(2)abi.encode和abi.encodePacked
bytes4 sig = bytes4(keccak256("test(uint256,string)"));bytes memory _bNum = abi.encode(_num);bytes memory _bMessage = abi.encode(_message);(bool success,) = _address.call(abi.encodePacked(sig, _bNum, _bMessage));return success;
与上面编码不同的是,这里的函数签名sig是用keccak256算法计算结果取前4个字节得来的,另外其余的参数也都使用abi.encode包装了,最后在统一放入abi.encodePacked函数中(属于非标准编码模式)。
测试过程上同。
(3)abi.encodeWithSelector
bytes4 sig = bytes4(keccak256("test(uint256,string)"));(bool success, ) = _address.call(abi.encodeWithSelector(sig, _num, _message));
这种需要函数签名哈希的前4个字节,参数不变,作用相同。
早在v0.4版本是使用abi.encode(…)函数,不过已废弃了。
测试过程上同。
另外额外一种普通调用其它合约方法的写法:
B contractB = B(_address);(uint256 num, string memory message) = contractB.test(_num, _message);return true;
可能会提示有些变量没有用到,问题不大(或者可以写入event),也是能达到同样效果的。
ABI 不仅仅是人类和 EVM之间交互的链接。最重要的是,ABI定义了如何对数据和合约调用进行编码和解码的明确规范。ABI 有助于进一步概念化合约,通过参数列表及其类型可以调用哪些函数以及如何调用。ABI 仅包含有关函数和事件的信息,不包括有关状态变量或修饰符的信息(状态变量定义为public时除外,此时将创建一个全局的getter方法)。
参考:Contract ABI Specification — Solidity 0.8.17 documentation
https://coinsbench.com/solidity-tutorial-all-about-abi-46da8b517e7