Contract-Development

我應該如何從映射中獲取值?

  • April 25, 2021

我和我的朋友正在做一個硬體任務。我們有一個結構:

struct Record {
       string  id;
       uint requestTime;
       uint releaseTime;
       Direction dir;
   }

我們還有一個映射:

mapping(address => Record[]) data;

我們基本上將Record在與一個地址關聯的映射中擁有多個實例。有沒有辦法Record從映射中讀取實例?像 getter 函式或獲取特定地址作為參數並返回包含屬於該地址Record[]的實例的數組的東西?Record

function getRecords(address _addr) public view returns(Record[]) {
   ...
   //returns recordsfound, which is a Record[]
   return recordsfound;
}

或者這在 Solidity 中不起作用,我們必須製作其他東西?

第一件事。這種糟糕的形式是因為 0.5.0x 和 0.8.3 之間存在顯著差異。您應該指出實際編譯和工作的範圍,或者更好的是,只需聲明您正在使用的編譯器,如下所示:

pragma solidity 0.8.3;

由於這是使用以前“實驗性 ABI”的元素,因此毫無疑問,如果不修改程式碼,程式碼不會在 0.7.6 或更低版本下編譯。

// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.3;

contract Nested {
   
   struct Record {
       string  id;
       uint requestTime;
       uint releaseTime;
       Direction dir;
   }
   
   struct Direction {
       bool foo;
       uint bar;
   }
   
   mapping(address => Record[]) records;
   
   function insert(address key, string memory id, uint requestTime, uint releaseTime, bool foo, uint bar) public {

       Direction memory d = Direction({
           foo: foo,
           bar: bar
       });
       
       Record memory r = Record({
           id: id,
           requestTime: requestTime,
           releaseTime: releaseTime,
           dir: d
       });
       
       records[key].push(r);
   }
   
   function inspect(address key) public view returns(Record[] memory) {
       return records[key];
   }
   
}

您可能發現不能只添加public到映射中。

你可能會得到類似的東西:

call to Nested.records errored: Error encoding arguments: Error: invalid BigNumber string (argument="value", value="", code=INVALID_ARGUMENT, version=bignumber/5.0.8)

我發現我的實驗的一些迭代似乎編譯成功,然後在執行時產生了那個錯誤,這有點令人不安。恕我直言,如果編譯器拒絕原始碼會更好,除非可以建構可靠的視圖函式 - 一個很好的提醒,在依賴前沿編譯器功能時要提防隱患。

一種更傳統且可能更有效的方法是呈現幾個固定長度的 ABI 函式,如下所示:

   function inspectLength(address key) public view returns(uint) {
       return records[key].length;
   }
   
   function inspectRecord(address key, uint record) public view returns(Record memory) {
       return records[key][record];
   }

這將互動問題推給了客戶。他們可以檢查單個記錄或將它們全部列舉,並且在之前已經看到其大部分值時無需獲取整個數組。

除了由於契約規模而導致的一些額外部署成本外,還可以考慮同時包含這兩種方法 - 獲取所有並獲取一個。

// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.0;

contract Nested {
   
   struct Record {
       string  id;
       uint requestTime;
       uint releaseTime;
       Direction dir;
   }
   
   struct Direction {
       bool foo;
       uint bar;
   }
   
   mapping(address => Record[]) records;
   
   function insert(address key, string memory id, uint requestTime, uint releaseTime, bool foo, uint bar) public {

       Direction memory d = Direction({
           foo: foo,
           bar: bar
       });
       
       Record memory r = Record({
           id: id,
           requestTime: requestTime,
           releaseTime: releaseTime,
           dir: d
       });
       
       records[key].push(r);
   }
   
   function inspect(address key) public view returns(Record[] memory) {
       return records[key];
   }
   
   function inspectLength(address key) public view returns(uint) {
       return records[key].length;
   }
   
   function inspectRecord(address key, uint record) public view returns(Record memory) {
       return records[key][record];
   }
   
}

希望能幫助到你。

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