Solidity
如何可靠地解析 bytes32?
我在記憶體或儲存中有一個 bytes32 對象,我想將其解析為小塊,例如解析為一個 uint8,然後是 bool,然後是 uint10,然後是地址。怎麼可能做到這一點?我嘗試了兩種選擇:
// option 1 function parseBytes32_op1(bytes32 _data) pure public returns (byte fist, byte second, bytes10 third, bytes20 fourth) { assembly { let freemem_pointer := mload(0x40) mstore(add(freemem_pointer,0x00), _data) _first := mload(add(freemem_pointer,0x00)) _second := mload(add(freemem_pointer,0x01)) _third := mload(add(freemem_pointer,0x02)) _fourth := mload(add(freemem_pointer,0x0b)) } // and then convert somehow into the respective types } // option2 function parseBytes32_op2(bytes32 _data) pure public returns (byte fist, byte second, bytes10 third, bytes20 fourth) { first = uint8(bytes1(_data)); second = bool(uint8(bytes1(_data << 8))); third = uint10(bytes9(_data << 8 * 2)); fourth = address(bytes9(_data << 8 * 12)); }
但是,在第一個選項中,我對記憶體堆棧感到不舒服。我擔心如果堆棧頂部有一些不是數據的東西,我可能會使用錯誤的指針。
在第二個選項中,我對換檔操作感到不舒服。這些字節在哪裡移動?事實上,當我在 remix 上執行一些類似的程式碼時,我得到了一個編譯器錯誤:
CompilerError: Stack too deep, try removing local variables.
什麼是最好的選擇?
它可以在沒有記憶體訪問的情況下實現,只需輪班
function parseBytes32_op1(bytes32 _data) pure public returns (bytes1 first, bytes1 second, bytes10 third, bytes20 fourth) { assembly { first := _data second := shl(8, _data) third := shl(add(8, 8), _data) fourth := shl(add(16, 80), _data) } }
它可以在solidity中實現,它幾乎與您的解決方案相同
function parseBytes32_op2(bytes32 _data) pure public returns (bytes1 fist, bytes2 second, bytes10 third, bytes20 fourth) { first = bytes1(_data); second = bytes1(_data << 8); third = bytes10(_data << 8 * 2); fourth = bytes20(_data << 8 * 12); }
EVM 是基於堆棧的,因此像移位這樣的簡單操作是使用機器堆棧實現的。
錯誤資訊
CompilerError:堆棧太深,嘗試刪除局部變數。
意味著您使用了太多的局部變數 + 返回值 + 輸入參數 + 臨時操作。
嘗試簡化函式,分成兩部分,用於
{}
限制變數範圍。對於其他建議,請在編譯時看到此錯誤:堆棧太深。