Доступ к общедоступной переменной состояния с помощью геттера, не работает

Я работал с примером контракта на голосование и проводил его модульное тестирование с помощью Truffle и Javascript. До сих пор мне удалось успешно протестировать каждую функцию из моего контракта. Но когда я попытался получить свойство списка кандидатов, это не сработало. Часть тестового файла

...
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)

Чего я не понимаю, так это почему, если функция получения генерируется автоматически, 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"; api версии web3: '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);
});

});

Ответы (1)

В свой код 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));
Это сработало, спасибо! Просто для ясности, всякий раз, когда вы хотите получить доступ к переменной массива контракта. Вы должны предоставить определенный индекс для получения, получение всего массива не поддерживается?