Solidity

從內聯彙編返回字節

  • June 12, 2022

我有兩個小測試,我試圖返回bytes它們是通過內聯彙編填充的。當我使用預定義的返回變數時它可以工作,但是當我嘗試在內聯彙編中完成所有操作時,我遇到了緩衝區溢出。我在這裡想念什麼?

pragma solidity ^0.8.4;

contract AssemblyTest {

   function working() external view returns (bytes memory res) {
       assembly {
           res := mload(0x40)           // get free memory pointer
           mstore(res, 0x40)            // length: 64 bytes
           mstore(add(res, 0x20), 1)    // first 32 bytes
           mstore(add(res, 0x40), 2)    // second 32 bytes
           mstore(0x40, add(res, 0x60)) // update free memory pointer
       }
   }

   function notWorking() external view returns (bytes memory) {
       assembly {
           let res := mload(0x40)       // get free memory pointer
           mstore(res, 0x40)            // length: 64 bytes
           mstore(add(res, 0x20), 1)    // first 32 bytes
           mstore(add(res, 0x40), 2)    // second 32 bytes
           mstore(0x40, add(res, 0x60)) // update free memory pointer
           return (res, 0x60)           // return 96 bytes (32 bytes length + 64 bytes data)
       }
   }
}

您的數據應返回 abi.encoded。在您的情況下,由於您正在處理動態類型,因此您必須包含偏移數據開始(請參閱此答案

為此修改您的功能,它應該可以工作:

   function nowItWorks() external view returns (bytes memory) {
       assembly {
           let res := mload(0x40)       // get free memory pointer
           mstore(res, 0x20)            // return data offset : abi encoding
           mstore(add(res, 0x20), 0x40) // length: 64 bytes
           mstore(add(res, 0x40), 1)    // first 32 bytes
           mstore(add(res, 0x60), 2)    // second 32 bytes
           mstore(0x40, add(res, 0x80)) // update free memory pointer
           return (res, 0x80)           // return 128 bytes (32 bytes data offset + 32 bytes length + 64 bytes data)
       }
   }

由於您的函式是外部函式,並且您正在從函式返回(並退出合約),因此您也可以選擇不尊重solidity 記憶體佈局並刪除與空閒記憶體指針相關的所有程式碼:

     function nowItWorks() external view returns (bytes memory) {
       assembly {
           let res := 0x00              // Take any memory location
           mstore(res, 0x20)            // return data offset : abi encoding
           mstore(add(res, 0x20), 0x40) // length: 64 bytes
           mstore(add(res, 0x40), 1)    // first 32 bytes
           mstore(add(res, 0x60), 2)    // second 32 bytes
           return (res, 0x80)           // return 128 bytes (32 bytes data offset + 32 bytes length + 64 bytes data)
       }
   }

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