Solidity
你可以使用函式選擇器呼叫智能合約的內部函式嗎?
我有以下契約:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; contract Selectors { bool public called; function callOtherFunc() public { bytes4 func = this.otherFunc.selector; (bool success, ) = address(this).call(abi.encodeWithSelector(func, true)); } function otherFunc(bool _called) internal { called =_called; } }
但是,我遇到了錯誤:
TypeError: Member "otherFunc" not found or not visible after argument-dependent lookup in contract Selectors.
但如果我
otherFunc
公開,它編譯得很好。此外,其他全域功能似乎不起作用
(bool success, ) = address(this).call(abi.encodeWithSignature("otherFunc(bool)", true));
或者
(bool success, ) = address(this).call(abi.encodeWithSelector(bytes4(keccak256(bytes("otherFunc(bool)"))), true));
這就是它的方式嗎?還有另一種使用選擇器呼叫內部函式的方法嗎?
無法通過函式選擇器直接呼叫內部函式。
合約的入口點基本上是一個帶有額外檢查的跳轉表,在 calldata 的前 4 個字節和合約的暴露函式之間尋找匹配的函式選擇器。
將您的函式標記為內部會將其從該跳轉表中排除,使其無法從外部呼叫中訪問。
採取以下契約:
contract SelectorsPublic { bool public called; function otherFunc(bool _called) public { called =_called; } }
在主函式體中明確檢查函式選擇器(提醒一下:
keccak256("otherFunc(bool)")
==0x64feed76...
):else if (var0 == 0x64feed76) { // Dispatch table entry for 0x64feed76 (unknown) var1 = 0x0073; var2 = 0x006e; var4 = 0x04; var3 = var4 + (msg.data.length - var4); var2 = func_0109(var3, var4); func_006E(var2); stop(); }
反對,本契約(具有內部可見性):
contract SelectorsInternal { bool public called; function otherFunc(bool _called) internal { called =_called; } }
在此處部署和在此處反編譯沒有這樣的檢查。這意味著沒有通往
otherFunc
智能合約主要入口點的路徑。只允許對其進行內部呼叫,外部呼叫將找不到匹配的條目並因此恢復(或者甚至不會像您的範例中那樣編譯)。
編輯:如果從反編譯的字節碼中您想知道檢查的內容
0x50f9b6cd
是什麼:這些與應用於自動生成的 getter 的原理相同:bool public called
,keccak256("called()")
=0x50f9b6cd....
編輯2:
只有外部(或公共)函式具有以下成員:
.address
: 返回函式合約的地址。
.selector
: 返回 ABI 函式選擇器因此,通過使用其中任何一個,您都在“外部”呼叫這些函式。