Solidity

字節變數已連接

  • November 16, 2018

為什麼這些變數會混淆?返回的結果表明兩個循環都影響了兩個字節變數(second返回相同的結果)。

function mix() public returns (bytes) {  

   bytes first;
   for (uint8 cnt = 0; cnt<8; cnt++) {
       first.push(9)
   }


   bytes second;
   for (uint8 cnt2 = 0; cnt2<8; cnt2++) {
       second.push(8);
   }

   return first;
}

返回結果: '0x09090909090909090808080808080808'

這需要花一些時間來解釋。

程式碼看起來很無辜,但是有一個關於未初始化儲存指針的編譯器警告。警告不應被忽視。

明確寫出來,應該是

bytes storage first;

儲存指針可能開始看起來有點手感。考慮一下:

MyStruct s = structsMap[key];
s.someVal = false;

儲存空間structsMap[key]將設置為false因為s是儲存指針(又名引用變數)。它不是保存值,而是保存一個指向儲存的指針。當您寫入時s,您正在寫入任何插槽s所指的實際儲存,它在初始化時得到。

您的bytes first;語句右側 (of ) 沒有任何內容=,因此未初始化,因此預設為 slot 0。這是警告的“未初始化”部分。bytes second獲得相同的插槽0。哎呀!現在,我們在同一個儲存插槽上看到了看起來分開的東西。這裡是龍。

如果我們在 global 部分聲明儲存,它將按預期工作:

contract NoMixing {

   bytes public first;
   bytes public second;

   function mix() public returns (bytes, bytes) {  

       for (uint8 cnt = 0; cnt<8; cnt++) {
           first.push(9);
       }

       for (uint8 cnt2 = 0; cnt2<8; cnt2++) {
           second.push(8);
       }

       return (first,second);
   }

}

我不是儲存指針的忠實擁護者,因為像您這樣的程式碼看起來應該可以工作。看到這個:https ://vessenes.com/solidity-frustrations-references-and-mapping/

一些一般安全提示:

  1. 聲明儲存外部函式。
  2. memory從索引類型 ( ) 分配某些內容時顯式使用[]。這會使您的push方法失敗​​,但至少您會收到有關該問題的警報。
  3. 使用xafter時要格外小心,x = somethingInStorage[index];這樣你就不會覆蓋你不想改變的東西。

希望能幫助到你。

更新

這是一個非常有趣的例子,我決定在部落格上討論這個問題。這是關於 Solidity 中儲存指針的解釋器,並提供了一些避免這種混淆的安全建議:https ://blog.b9lab.com/storage-pointers-in-solidity-7dcfaa536089

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