Assembly

在裝配中……無法讓委託呼叫工作

  • August 10, 2020

Delegatecall 可以在solidity 或assembly 中使用。

在solidity中,我可以使用以下程式碼使其工作:

bytes memory payload = abi.encodeWithSignature ("get_value(uint16,uint16)", var1, var2);
bool success;
bytes memory result;
(success, result) = my_contract.delegatecall (payload);

上面的程式碼呼叫my_contract.get_value(var1, var2).

我怎樣才能在裝配中做同樣的事情?函式定義如下:

delegatecall (gas, address, in, insize, out, outsize)

如果我在一個組裝塊中,假設address應該是包含被呼叫函式的合約的地址,它怎麼會知道我打算呼叫哪個函式?當我使用solidity 執行此操作時,它會從我傳遞給它的編碼有效負載數據中知道這一點。但是彙編函式只需要一個地址。它總是返回 0。

我無法在 Internet 上的任何地方找到任何關於 EVM 組裝的好的文件。

編輯:以下是我所做的嘗試之一,使用來自 Internet 的範例。

let freememstart := mload (0x40)
calldatacopy (freememstart, 0, calldatasize ())
success := delegatecall (not (0), my_contract, freememstart, calldatasize (), freememstart, 32)

編輯 2:我做了另一次嘗試,沒有使用 calldatacopy。

bytes memory payload = abi.encodeWithSignature ("get_value(uint16,uint16)", var1, var2);
uint payload_size = payload.length * 8;

assembly
{
   let freememstart := mload (0x40)

   mstore (0x40, add (freememstart, payload_size))
   mstore (freememstart, payload)

   let output := mload (0x40)
   mstore (0x40, add (output, 0x20))

   success := delegatecall (not (0), contract_addr, freememstart, payload_size, output, 0x20)
}

您應該注意的幾件事:

  • 不需要將記憶體複製到空閒指針,可以使用任何記憶體指針。EVM 會將記憶體複製到目標,因此不會被修改。
  • 有效載荷的前 32 個字節是數組的長度。傳遞該記憶體時可能希望跳過這些字節。這就是背後的原因add(payload, 32)

像這樣的東西應該​​適用於你的情況

bytes memory payload = abi.encodeWithSignature ("get_value(uint16,uint16)", var1, var2);
uint ret;
bool success;

assembly
{
   let output := mload (0x40)
   success := delegatecall(gas(),
       contract_addr,
       add(payload, 32),
       mload(payload),
       output,
       0x20)
   ret := mload(output)
}

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