美文网首页
19. Solidity:函数选择器(函数签名)

19. Solidity:函数选择器(函数签名)

作者: 泡泡龙吐泡泡 | 来源:发表于2023-10-09 08:33 被阅读0次

    19.1 selector

    当我们调用智能合约时,本质上是向目标合约发送了一段calldata,在remix中发送一次交易后,可以在详细信息中看见input即为此次交易的calldata。

    发送的calldata中前4个字节是selector(函数选择器)。
    示例代码,将msg.data作为事件发出:

    contract Selector {
        address public addr;
        event Log(bytes data);
    
        function selector(address _addr) external {
            addr = _addr;
            emit Log(msg.data);
        }
    }
    

    remix日志中的input:


    input

    Log信息(msg.data):

    [
        {
            "from": "0xc5c97AAd92a962396229cbC8392e62585B04DfB3",
            "topic": "0xafabcf2dd47e06a477a89e49c03f8ebe8e0a7e94f775b25bbb24227c9d0110b2",
            "event": "Log",
            "args": {
                "0": "0x91fa5ace0000000000000000000000005b38da6a701c568545dcfcb03fcb875f56beddc4",
                "data": "0x91fa5ace0000000000000000000000005b38da6a701c568545dcfcb03fcb875f56beddc4"
            }
        }
    ]
    

    可见input信息和全局变量msg.data相同,都是此次调用函数的calldata:

    0x91fa5ace0000000000000000000000005b38da6a701c568545dcfcb03fcb875f56beddc4

    前四个字节为函数选择器:
    0x91fa5ace
    后面32字节为传入的参数(20字节的地址补零):
    0000000000000000000000005b38da6a701c568545dcfcb03fcb875f56beddc4

    calldata作用是:告诉智能合约,要调用哪个函数,以及参数是什么。

    19.2 函数签名、selector和method id

    • 函数签名:"函数名(逗号分隔的参数类型)",例如例子中selector()的函数签名是:

      "selector(address)"

    • selector:函数选择器为calldata的前四个字节。
    • method id:函数签名哈希值的前四个字节,例如:

      bytes4(keccak256("selector(address)"))

    实现一个函数获取上述例子中selector()函数的method id:

        function getSelector() external pure returns (bytes4){
            return bytes4(keccak256("selector(address)"));
        }
    

    调用函数的返回值和函数选择器相同,为0x91fa5ace。Solidity中通过函数选择器(selector)匹配method id的方式确定要调用的函数。

    19.3 selector的使用

    我们可以利用selector来调用目标函数。例如我想调用selector()函数,我只需要利用abi.encodeWithSelector将selector()函数的method id作为selector和参数打包编码,传给call函数:

        function useSelector(address _addr) external returns (bool) {
            (bool success, ) = address(this).call(abi.encodeWithSelector(0x91fa5ace, _addr));
            return success;
        }
    

    调用selector()函数成功,输出的Log:

    [
        {
            "from": "0xf02A102153DDf132032B7De5D19F43aA049052Dd",
            "topic": "0xafabcf2dd47e06a477a89e49c03f8ebe8e0a7e94f775b25bbb24227c9d0110b2",
            "event": "Log",
            "args": {
                "0": "0x91fa5ace0000000000000000000000005b38da6a701c568545dcfcb03fcb875f56beddc4",
                "data": "0x91fa5ace0000000000000000000000005b38da6a701c568545dcfcb03fcb875f56beddc4"
            }
        }
    ]
    

    相关文章

      网友评论

          本文标题:19. Solidity:函数选择器(函数签名)

          本文链接:https://www.haomeiwen.com/subject/nvkcbdtx.html