Web3js

web3 中的結構成員訪問需要額外的虛擬欄位

  • April 21, 2019

如果結構包含單個欄位,則該欄位無法從 web3 訪問。在下面的範例中,uint b還必須存在欄位才能uint c從 web3 訪問欄位。當然,如果您只儲存一個欄位,這並不是結構的最佳用途,但這種意外行為也存在於使用任意數量的附加數組或映射欄位的更現實的場景中。

目前的解決方法是將未使用的虛擬欄位添加到我的結構中,但我想知道這是否是預期的行為,以及是否在 Solidity 文件的任何地方都注意到了這個怪癖?我沒有找到structs 部分中提到的任何內容。

合約程式碼:

pragma solidity ^0.5.0;

contract StructAccess {

   struct SimpleStruct {
       //uint b; // c inaccessible if this is commented-out.
       uint c;
       uint[] d; // This has no impact on ability to access c.
       mapping (uint => uint) e; // This has no impact on ability to access c.

   }

   SimpleStruct public singleStruct;

   constructor() public {
       singleStruct.c = 5;
   }
}

測試程式碼:

const StructAccess = artifacts.require("StructAccess");

contract('StructAccess', (accounts) => {

 it('should pass struct access test', async () => {
   const accessInstance = await StructAccess.deployed();

   const singleStruct = await accessInstance.singleStruct();

   console.log(singleStruct.c);
   assert.equal(singleStruct.c, 5);
 });

});

測試結果:

With uint b, singleStruct.c is 5
Without uint b, singleStruct.c is undefined

版本資訊:

> truffle version
Truffle v5.0.13 (core: 5.0.13)
Solidity v0.5.0 (solc-js)
Node v8.11.2
Web3.js v1.0.0-beta.37

您在一個已知的“陷阱”附近,但症狀與您報告的不完全一樣。

在這裡,它在 Remix 中被uint b註釋掉,並顯示它在兩種情況下都有效。

在此處輸入圖像描述

如果兩個縮放器變數都被註釋掉,你會遇到問題。那將struct只剩下索引變數、數組和映射。

這種情況作為儲存結構非常好,但請注意數組和映射不包含在public. 這反映了編譯器的局限性。它並不確切地知道您希望如何建構子,因此將它們排除在外。如果沒有至少一個縮放器變數,那麼這意味著沒有任何東西可以返回。因此,您不能使用public僅包含索引變數的資料結構。更多資訊:編譯器問題或不正確的狀態變數聲明?

在客戶端,由於在未註釋的情況下返回了多個值uint b,因此您將獲得一個數組而不是一個縮放器值。您應該檢查singleStruct[0]singleStruct[1]查看這兩個值。我尚未對此進行測試,但希望它可以將您推向正確的方向。

希望能幫助到你。

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