Eth-Call
怒氣沖沖地打電話給另一個契約?
我如何用怒氣呼叫另一個契約?
然後獎勵積分…從通話中返回數據。
假設我有一個具有以下功能的solidity風格合約:
NumberGetter.sol
uint256 myNumber = 777; function getNumber() public view returns (uint256) { return myNumber; }
我如何從
huff
契約中呼叫這個函式?我們需要使用
call
orstaticcall
(讓我們staticcall
在這個例子中使用)。我認為它看起來像這樣:
#define function getNumberFromOtherContract() view returns (uint256) #define constant NUMBER_GETTER_ADDRESS = 0x0000000000000000000000000000000000000000 // Swap out for NumberGetter.sol contract address #define macro GET_NUMBER_FROM_OTHER_CONTRACT() = takes (0) returns (0) { // store the function to call in memory __FUNC_SIG("getNumber()") 0x00 mstore // return size = 0x20 // return offset = 0x00 // arguments size = 0x04 (function selector size) // arguments offset = 0x00 // address = NUMBER_GETTER_ADDRESS // gas = whatever gas is left = gas // staticcall calls our NUMBER_GETTER_ADDRESS contract 0x20 0x00 0x04 0x00 [NUMBER_GETTER_ADDRESS] gas staticcall // size = 0x20 // return data offset = 0x00 // destination in memory offset = 0x00 0x20 0x00 0x00 returndatacopy 0x20 0x00 return }
這很近!
當您儲存四字節函式選擇器時,實際上是在選擇器位於右側的位置儲存了 32 個字節。
0xaabbccdd // [selector] 0x00 // [offset, selector] mstore // [] // MEMORY SLOT 0 AFTER MSTORE: // 0x00000000000000000000000000000000000000000000000000000000aabbccdd
因此,在您的範例中,您希望“參數偏移量”位於記憶體中的第 28 個字節(32 字節字 - 4 個字節)。
#define constant GETTER_ADDR = 0x0000000000000000000000000000000000000000 // Swap out for NumberGetter.sol contract address #define macro GET_NUMBER_FROM_OTHER_CONTRACT() = takes (0) returns (0) { // store the function to call in memory __FUNC_SIG("getNumber()") 0x00 mstore // make call. return size is zero because we can fetch it after the call 0x00 // [ret_size] 0x00 // [ret_offset, ret_size] 0x04 // [args_size, ret_offset, ret_size] 0x1c // [args_offset, args_size, ret_offset, ret_size] [GETTER_ADDR] // [getter_addr, args_offset, args_size, ret_offset, ret_size] gas // [gas, getter_addr, args_offset, args_size, ret_offset, ret_size] staticcall // [successs] // store returndata in memory returndatasize // [returndatasize, success] 0x00 // [mem_offset, returndatasize, success] 0x00 // [destOffset, mem_offset, returndatasize, success] returndatacopy // [success] // this stores the return data in memory // return the returndata from memory to the msg.sender returndatasize // [returndatasize, success] 0x00 // [mem_offset, returndatasize, success] return }
請注意,
staticcall
將“成功”值推送到堆棧,即0x01
呼叫是否成功並且0x00
對 getter 地址的呼叫是否恢復。我把它留在了這個例子的堆棧上,因為它超出了這個問題的範圍,但創建一些邏輯來處理恢復是個好主意!有關處理呼叫恢復的更多資訊,請參閱Huffmate 錯誤。