底层调用,函数选择器生成
底层调用,函数选择器生成
底层调用
在 Solidity 中底层调用分为三个:call
, delegatecall
,staticcall
,在 Solidity 中,使用这些底层调用都需要传递函数选择器,而函数选择器是函数签名的keccak256
哈希值的前4个字节,要生成函数选择器,这时候就需要使用到abi编码和进制转换。
函数选择器生成
主要应用 abi
编码中的 abi.encodeWithSignature()
和bytes4
强制类型转换,来生成函数选择器
详细的 abi 编码请看文章abi编码解码详解
关于进制转换:
高位整数转换到低位整数舍弃高位(eg:uint32 a = 0x12345678 => uint16 b = uint16(a) => b == 0x5678)
低位整数转换到高位整数高位补零(eg:uint16 a = 0x1234 => uint32 b = uint32(a) => a == 0x00001234 ,并且 a == b)
高位字节转换到低位字节舍弃低位(eg:bytes2 a = 0x1234 => bytes1 b = bytes1(a) => b == 0x12)
低位字节转换到高位字节低位补零(eg:bytes1 a = 0x12 => bytes2 b = bytes2(a) => b == 0x1200,并且 a[0] ==b[0] )
详细的进制转换请看文章:Solidity类型转换相关
// create selector
bytes4 selectorA = bytes4(abi.encodeWithSignature("getValue(address,uint256)"))
bytes4 selectorB = bytes4(abi.encodeWithSignature("getValue()"))
使用abi.encodeWithSignature()
和bytes4()
生成函数选择器时要注意:
- 如果函数签名没有参数,也依然要写
()
- 传递函数签名时,两个参数只用
,
隔开,不要在两个参数中间添加空格,这样生成的函数选择器与实际的函数选择器不一样
使用 Foundry 内置的 chisel 试验一下计算函数选择器:
上图中,下面的是真实的函数选择器,可以发现,生成函数选择器时,两个参数之间不能加上空格
上图中,上面的是真实的函数选择器,可以发现,生成函数选择器时,如果函数没有参数,也是需要传递()
的