Solidity
使用 getter 訪問公共狀態變數,不起作用
我一直在使用投票合約範例,並使用 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));