Solidity

使用 getter 訪問公共狀態變數,不起作用

  • May 8, 2018

我一直在使用投票合約範例,並使用 Truffle 和 Javascript 對其進行單元測試。到目前為止,我已經成功地測試了契約中的每個功能。但是,當我嘗試檢索 CandidateList 屬性時,它不起作用。部分測試文件

...
it('returns every candidate', async () => {
   let fundRaise = await Voting.new(['Alice', 'Bob', 'Rick']);

   const cands = await voting.candidateList();
   Console.log(cands);
});
...

當我執行上述測試時,松露顯示以下內容

1) Contract: Voting returns every candidate:
Error: Invalid number of arguments to Solidity function
 at Object.InvalidNumberOfSolidityArgs (/usr/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/errors.js:25:1)
 at SolidityFunction.validateArgs (/usr/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/function.js:74:1)
 at SolidityFunction.toPayload (/usr/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/function.js:90:1)
 at SolidityFunction.call (/usr/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/function.js:131:1)
 at SolidityFunction.execute (/usr/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/function.js:260:1)
 at /usr/lib/node_modules/truffle/build/webpack:/~/truffle-contract/contract.js:135:1
 at new Promise (<anonymous>)
 at /usr/lib/node_modules/truffle/build/webpack:/~/truffle-contract/contract.js:126:1
 at <anonymous>
 at process._tickDomainCallback (internal/process/next_tick.js:228:7)

我不明白為什麼如果自動生成 getter 函式,web3 會拋出此消息。我有 Truffle v4.1.7(核心:4.1.7);Solidity v0.4.23 (solc-js); Geth/v1.8.1-stable-1e67410e/linux-amd64/go1.9.4"; web3 版本 api: ‘0.20.6’,

下面是契約文件以及測試文件。

pragma solidity ^0.4.17;

contract Voting {

mapping (bytes32 => uint8) public votesReceived;
bytes32[] public candidateList;

constructor(bytes32[] _candidates) public {
   candidateList = _candidates;
}

function voteForCandidate(bytes32 _name) public returns (uint8) {
   require(validateCandidate(_name));
   votesReceived[_name] += 1;
   //return votesReceived[_name];
   return totalVotesFor(_name);
}

function validateCandidate(bytes32 _name) view public returns (bool){
   for (uint8 i = 0; i < candidateList.length; i++) {
       if(candidateList[i] == _name){
           return true;
       }
   }
   return false;
}

function totalVotesFor(bytes32 name) view public returns (uint8){
   require(validateCandidate(name));
   return votesReceived[name];
}

function addCandidate(bytes32 _name) public returns (bool) {
   candidateList.push(_name);
   return validateCandidate(_name);
}


const assert = require('assert');
var Voting = artifacts.require("Voting");

這是測試文件:

contract('Voting', function(accounts) {

let voting;

beforeEach(async () => {
   voting = await Voting.deployed();
});

it('votes for valid candidate', async () => {

   const voto = await voting.voteForCandidate.call('Andrea');

   assert.equal(voto.toNumber(),1, 'Cannot vote for valid candidate');
});

it('Does not vote for invalid candidate', async () => {
   const voto = await voting.voteForCandidate.call('Bacilio');

   assert.equal(voto.toNumber(), 0, 'Allowed to vote for invalid candidate');
});

it('Adds new candidate', async () => {
   const voto = await voting.addCandidate.call('Segismundo');
   assert.equal(voto, true, 'Did not allow to add new candidate');
});

it('allows to obtain votes casted for a candidate', async () => {

   const expected_votes = 2;

   //vote twice for the same candidate
   await voting.voteForCandidate('Roberto');
   await voting.voteForCandidate('Roberto');

   let casted_votes = await voting.totalVotesFor.call('Roberto');
   assert.equal(casted_votes.toNumber(), expected_votes, 'Did not got casted votes')

});

it('returns every candidate', async () => {
   let fundRaise = await Voting.new(['Segismundo', 'Ocatvia']);

   const cands = await voting.candidateList();
   Console.log(cands);
});

});

在您的 Solidity 程式碼中,添加:

function candidateListLength() external view returns (uint) {
   return candidateList.length;
}

在您的 Javascript 程式碼中添加:

let cands = [];
let length = Number(await voting.candidateListLength());
for (let i = 0; i < length; i++)
   cands.push(await voting.candidateList(i));

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