Solidity

通過 Truffle 控制台訪問結構內的映射

  • August 31, 2017

這個問題在這裡被問到,但我想我會更清楚一點。是否可以通過下面程式碼中的 Truffle 控制台訪問funders映射(粗體)?這取自Solidity 文件

struct Funder {
   address addr;
   uint amount;
}

struct Campaign {
   address beneficiary;
   uint fundingGoal;
   uint numFunders;
   uint amount;
   mapping (uint => Funder) funders;
}

uint numCampaigns;
mapping (uint => Campaign) campaigns;

function newCampaign(address beneficiary, uint goal) returns (uint campaignID) {
   campaignID = numCampaigns++; // campaignID is return variable
   // Creates new struct and saves in storage. We leave out the mapping type.
   campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
}

function contribute(uint campaignID) payable {
   Campaign storage c = campaigns[campaignID];
   // Creates a new temporary memory struct, initialised with the given values
   // and copies it over to storage.
   // Note that you can also use Funder(msg.sender, msg.value) to initialise.
   c.funders[c.numFunders++] = Funder({addr: msg.sender, amount: msg.value});
   c.amount += msg.value;
}

在您執行newCampaign並向contribute新創建的活動添加資金後,返回的對像如下:

[ '0x740bd112e4d310a69aae3cee9ca8e72d1b1f8a21', { [String: '15000'] s: 1, e: 4, c: [ 15000 ] }, { [String: '5'] s: 1, e: 0, c: [ 5 ] }, { [String: '16000'] s: 1, e: 4, c: [ 16000 ] }, { [String: '1504125631'] s: 1, e: 9, c: [ 1504125631 ] } ]

結構中的所有變數Campaign都是可見的,除了funders變數。這funders可能是因為沒有在儲存中初始化嗎?

如果你能原諒自我推銷,這個解釋器可能會揭示一種實現目標的方法:https ://medium.com/@robhitchens/enforcing-referential-integrity-in-ethereum-smart-contracts-a9ab1427ff42

編輯

主要思想如下。

這兩個實體的基本資料結構是結構的映射(用於隨機訪問)和作為動態數組的鍵的無序索引(便於計數和列舉)。此處的“帶索引的映射結構”標題下有一個範例。Solidity 是否有很好解決且簡單的儲存模式?

所以基本上,您只需為您的兩個實體與其中兩個建立契約。

接下來,加入。建議您在使用映射的地方嵌入一個動態的鍵數組。這樣就可以計算列表中的行數,還可以通過一次返回一個鍵來迭代列表。

大致:

struct CampaignStruct {
 ...
 address funders[];
 bool exists;
}

mapping(bytes32 => CampaignStruct) public campaignStructs;
bytes32[] public campaignIndex;

struct FunderStruct {
 ...
 bool exists;
}

mapping(address => FunderStruct) public funderStructs;
address[] public funderIndex;

function getCampaignCount() public constant returns(uint count) {
  return campaignIndex.length;
}

function getFunderCount() public constant returns(uint count) {
  return funderIndex.length;
}

function getCampaignAtIndex(uint row) public constant returns(<details>) {}

function getCampaignFunderCount(bytes32 campaignId) public constant returns(uint count) {
  return campaignStructs[campaignId].funders.length;
}

function getCampaignFunderAtIndex(bytes32 campaignId, uint row) public constant returns(address funder)

{
  return campaignStructs[campaignId].funders[row];
}

如果您不需要刪除,則 upsert 樣式編寫器可以解決問題,因為您可以直接寫入映射。新的鍵被添加到索引中.push()。您可以使用 abool exists來了解您是在更新還是插入。

希望能幫助到你。

您無法檢索結構內部映射的鍵->值對列表,原因與您無法檢索結構外部映射的鍵值對的原因相同:合約不知道它們是什麼. 有關更詳細的解釋,請參閱此答案:我們可以將所有元素儲存在合約中的映射中嗎

假設您自己擁有密鑰,您可以創建自己的訪問器來檢索它,例如:

function campaign_funder(uint campaignID, uint funderID) constant returns (address) {
   return campaigns[campaignID].funders[funderID].addr;
}

如果您需要能夠在不知道他們的 ID 的情況下檢索資助者列表,則必須儲存一些額外的數據,以便契約可以獲取 ID。有關詳細資訊,請參閱我連結的答案。

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