我最近在重新學 solidity,鞏固一下細節,也寫一個「Solidity 極簡入門」,供小白們使用(程式設計大佬可以另找教程),每周更新 1-3 講。
所有代碼和教程開源在 github:github.com/AmazingAng/WTFSolidity
當我們調用智慧合約的函數時,發送的位元組碼的前4個字節是 selector(函數選擇器)。 這一講,我們將介紹 selector 是什麼,以及如何使用。
msg.data 是 solidity 中的一個全域變數,值為完整的 calldata(調用函數的位元組碼)。
在下面的代碼中,我們可以通過Log事件來輸出調用mint函數的 calldata:
當參數為 0x2c44b726ADF1963cA47Af88B284C06f30380fC78 時,輸出的 calldata 為
這段很亂的位元組碼可以分成兩部分:
其實 calldata 就是告訴智慧合約,我要調用哪個函數,以及參數是什麼。
selector 定義為函數簽名的哈希的前 4 個字節,那麼函數簽名是什麼?
其實在第 21 講中,我們簡單介紹了函數簽名,為“函數名(逗號分隔的參數類型)”。 舉個例子,上面代碼中mint的函數簽名為“mint(address)”。 在智慧合約中,不同的函數有不同的函數簽名,因此我們可以通過函數簽名來確定要調用哪個函數。
注意,在函數簽名中,uint 和 int 要寫為 uint256 和 int256。
我們寫一個函數,來驗證mint函數的 selector 是否為 0x6a627842。 大家可以運行下面的函數,看看結果。
我們可以利用 selector 來調用目標函數。 例如我想調用 mint 函數,我只需要利用 abi.encodeWithSelector 將 mint 函數的 selector 和參數打包編碼,傳給 call 函數:
在日誌中,我們可以看到mint函數被成功調用,並輸出Log事件。
這一講,我們介紹了什麼是函數選擇器(selector),它和 msg.data、函數簽名的關係,以及如何使用它調用目標函數。