I am trying to test my voting ballot contract using Hardhat/ethers/TypeChain, but for some reason, the Ballot struct's typescript interface is NOT showing the array of choices struct field I have defined in the smart contract.
Below, is the TypeScript test file that isn't showing the Choice[] choices field in the ballot returned from the ballots mapping.
Here is the entire smart contract code: // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
contract Voting {
// @dev for voters we need to check address has been approved for voting using mapping
mapping(address => bool) public voters;
// e.g. inflate jewel by 5% - id: 1, string: 5% inflation, votes: (0)
struct Choice {
uint id;
string name;
uint votes;
}
// e.g. Ballot = vote, id: 1, name: jewel inflation, list of choices, end of ballot/time
struct Ballot {
uint id;
string name;
Choice[] choices;
uint end;
}
// @dev id of each ballot
mapping(uint => Ballot) public ballots;
uint nextBallotId;
address public admin;
// @dev check if address of voter has already voted for a given ballot
mapping(address => mapping(uint => bool)) public votes;
constructor() {
admin = msg.sender;
}
// [0xef..., 0xerfdf..]
function addVoters(address[] calldata _voters) onlyAdmin() external {
for(uint i = 0; i < _voters.length; i++) {
// e.g. voters[[0xef]] = true
voters[_voters[i]] = true;
}
}
function createBallot(
string memory name,
string[] memory _choices,
uint offset
) public onlyAdmin() {
// @dev can't assign due to Choices[] array as ballot's data location is STORAGE not MEMORY
// e.g. Choice[] memory _choices = new ...
// ballots[nextBallotId] = Ballot(nextBallotId, name, **_choices**, end)
// @dev can acccess field of struct that hasn't been created yet
ballots[nextBallotId].id = nextBallotId;
ballots[nextBallotId].name = name;
ballots[nextBallotId].end = block.timestamp + offset;
for(uint i = 0; i < _choices.length; i++) {
ballots[nextBallotId].choices.push(Choice(i, _choices[i], 0));
}
nextBallotId++;
}
function vote(uint ballotId, uint choiceId) external {
require(voters[msg.sender] = true, 'only voters can vote');
require(votes[msg.sender][ballotId] == false, 'voter can only vote once per ballot');
require(block.timestamp < ballots[ballotId].end, 'can only vote after ballot end date');
votes[msg.sender][ballotId] = true;
ballots[ballotId].choices[choiceId].votes++;
}
function results(uint ballotId)
view
external
returns(Choice[] memory) {
require(block.timestamp >= ballots[ballotId].end, 'cannot see the ballot result before ballot end');
return ballots[ballotId].choices;
}
modifier onlyAdmin() {
require(msg.sender == admin, 'only admin');
_;
}
}