Solidity

如何可靠地解析 bytes32?

  • February 12, 2022

我在記憶體或儲存中有一個 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:堆棧太深,嘗試刪除局部變數。

意味著您使用了太多的局部變數 + 返回值 + 輸入參數 + 臨時操作。

嘗試簡化函式,分成兩部分,用於{}限制變數範圍。對於其他建議,請在編譯時看到此錯誤:堆棧太深

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