solidity | 选择器
source link: https://benpaodewoniu.github.io/2023/02/20/solidity63/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
selector
当我们调用智能合约时,本质上是向目标合约发送了一段 calldata
,在 remix
中发送一次交易后,可以在详细信息中看见 input
即为此次交易的calldata
。
发送的 calldata
中前 4
个字节是 selector
(函数选择器)。
msg.data
msg.data
是 solidity
中的一个全局变量,值为完整的 calldata
(调用函数时传入的数据)。
在下面的代码中,我们可以通过 Log
事件来输出调用 mint
函数的 calldata
:
// event 返回msg.data
event Log(bytes data);
function mint(address to) external{
emit Log(msg.data);
}
当参数为 0x2c44b726ADF1963cA47Af88B284C06f30380fC78
时,输出的 calldata
为
0x6a6278420000000000000000000000002c44b726adf1963ca47af88b284c06f30380fc78
这段很乱的字节码可以分成两部分:
前 4
个字节为函数选择器 selector
:
0x6a627842
后面32
个字节为输入的参数:
0x0000000000000000000000002c44b726adf1963ca47af88b284c06f30380fc78
其实 calldata
就是告诉智能合约,我要调用哪个函数,以及参数是什么。
method id、selector和函数签名
method id
定义为函数签名的 Keccak
哈希后的前 4
个字节,当selector
与 method id
相匹配时,即表示调用该函数,那么函数签名是什么?
函数签名,为”函数名(逗号分隔的参数类型)”。
举个例子,上面代码中 mint
的函数签名为 mint(address)
。在同一个智能合约中,不同的函数有不同的函数签名,因此我们可以通过函数签名来确定要调用哪个函数。
注意,在函数签名中,uint
和 int
要写为 uint256
和 int256
。
我们写一个函数,来验证 mint
函数的 method id
是否为 0x6a627842
。大家可以运行下面的函数,看看结果。
function mintSelector() external pure returns(bytes4 mSelector){
return bytes4(keccak256("mint(address)"));
}
结果正是 0x6a627842
使用selector
我们可以利用 selector
来调用目标函数。例如我想调用 mint
函数,我只需要利用 abi.encodeWithSelector
将 mint
函数的 method id
作为 selector
和参数打包编码,传给call
函数:
function callWithSignature() external returns(bool, bytes memory){
(bool success, bytes memory data) = address(this).call(abi.encodeWithSelector(0x6a627842, 0x2c44b726ADF1963cA47Af88B284C06f30380fC78));
return(success, data);
}
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK