Solidity
從內聯彙編返回字節
我有兩個小測試,我試圖返回
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) } }