Solidity

如何返回嵌套了映射的結構數組?

  • August 14, 2021

這是程式碼。我想返回 Requests 數組。

pragma solidity >=0.8.4;

contract Contract {

   struct Requests {
       string description;
       uint value;
       address recipient;
       bool complete;
       mapping(address => bool) sender;
       uint approvalCount;
   }

   Requests[] public requests;

   function createRequest(string memory d, uint v, address r) public {
       Requests storage newRequest = requests.push();
       newRequest.description = d;
       newRequest.value = v;
       newRequest.recipient = r;
       newRequest.complete = false;
       newRequest.approvalCount = 0;
       newRequest.sender[msg.sender] = true;
   }
}

不幸的是,這是不可能的。要了解原因,請查看映射是如何儲存的

由於它們不可預測的大小,映射和動態大小的數組類型不能儲存在它們之前和之後的狀態變數“之間”。相反,根據上述規則,它們被認為僅佔用 32 個字節,並且它們包含的元素儲存在使用 Keccak-256 雜湊計算的不同儲存槽開始。

對於映射,插槽保持為空,但仍然需要確保即使有兩個彼此相鄰的映射,它們的內容最終位於不同的儲存位置。

對應於映射鍵的k值位於連接的位置,並且keccak256(h(k) . p)是根據其類型應用於鍵的函式.``h

換句話說,映射值不儲存在單個位置,而是分佈在整個儲存中的隨機位置。此外,編譯器不儲存鍵,也不跟踪映射中已經存在的項目數,因此它甚至不知道要複製什麼。

這一直是個問題,這就是為什麼現在在memory結構中不允許映射的原因,因為實際上只會複製其他欄位並且會默默地跳過映射。它們仍然允許在storage結構中使用,但存在相同的缺陷 - 編譯器為public儲存變數生成的 getter 會靜默地跳過結構內的映射和數組。

對於數組,解決方法是定義您自己的返回結構的函式。然後編譯器不會省略它。有了映射,問題就不同了,所以這還不夠。您必須將鍵儲存在某處,然後讓函式將鍵複製到一個新結構中,該結構有一個數組來代替映射。

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