Eth-Call

怒氣沖沖地打電話給另一個契約?

  • August 4, 2022

我如何用怒氣呼叫另一個契約?

然後獎勵積分…從通話中返回數據。

假設我有一個具有以下功能的solidity風格合約:

NumberGetter.sol

uint256 myNumber = 777;

function getNumber() public view returns (uint256) {
       return myNumber;
   }

我如何從huff契約中呼叫這個函式?

我們需要使用callor staticcall(讓我們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 錯誤

引用自:https://ethereum.stackexchange.com/questions/132961