# Solidity极简入门: 29. 函数选择器Selector **Published by:** [0xAA](https://paragraph.com/@wtfacademy/) **Published on:** 2022-05-23 **URL:** https://paragraph.com/@wtfacademy/solidity-29-selector ## Content 我最近在重新学solidity,巩固一下细节,也写一个“Solidity极简入门”,供小白们使用(编程大佬可以另找教程),每周更新1-3讲。 欢迎关注我的推特:@0xAA_Science WTF技术社群discord,内有加微信群方法:链接 所有代码和教程开源在github(1024个star发课程认证,2048个star发社群NFT): github.com/AmazingAng/WTFSolidityselector当我们调用智能合约的函数时,发送的字节码的前4个字节是selector(函数选择器)。这一讲,我们将介绍selector是什么,以及如何使用。msg.datamsg.data是solidity中的一个全局变量,值为完整的calldata(调用函数的字节码)。 在下面的代码中,我们可以通过Log事件来输出调用mint函数的calldata: // event 返回msg.data event Log(bytes data); function mint(address to) external{ emit Log(msg.data); } 当参数为0x2c44b726ADF1963cA47Af88B284C06f30380fC78时,输出的calldata为这段很乱的字节码可以分成两部分:其实calldata就是告诉智能合约,我要调用哪个函数,以及参数是什么。函数签名和selectorselector定义为函数签名的哈希的前4个字节,那么函数签名是什么? 其实在第21讲中,我们简单介绍了函数签名,为"函数名(逗号分隔的参数类型)"。举个例子,上面代码中mint的函数签名为"mint(address)"。在智能合约中,不同的函数有不同的函数签名,因此我们可以通过函数签名来确定要调用哪个函数。 注意,在函数签名中,uint和int要写为uint256和int256。 我们写一个函数,来验证mint函数的selector是否为0x6a627842。大家可以运行下面的函数,看看结果。 function mintSelector() external pure returns(bytes4 mSelector){ return bytes4(keccak256("mint(address)")); } 使用selector我们可以利用selector来调用目标函数。例如我想调用mint函数,我只需要利用abi.encodeWithSelector将mint函数的selector和参数打包编码,传给call函数: function callWithSignature() external returns(bool, bytes memory){ (bool success, bytes memory data) = address(this).call(abi.encodeWithSelector(0x6a627842, "0x2c44b726ADF1963cA47Af88B284C06f30380fC78")); return(success, data); } 在日志中,我们可以看到mint函数被成功调用,并输出Log事件。总结这一讲,我们介绍了什么是函数选择器(selector),它和msg.data、函数签名的关系,以及如何使用它调用目标函数。 ## Publication Information - [0xAA](https://paragraph.com/@wtfacademy/): Publication homepage - [All Posts](https://paragraph.com/@wtfacademy/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@wtfacademy): Subscribe to updates - [Twitter](https://twitter.com/0xAA_Science): Follow on Twitter