尝试从 Solidity 对象数组中获取字段集时出错

Error trying to obtain set of fields from array of Solidity objects

我正在尝试为投票示例 Ballot.sol 编写测试:

https://docs.soliditylang.org/en/v0.8.11/solidity-by-example.html

我的测试代码如下所示:

const ethers = require('ethers');

const BallotContract = artifacts.require("Ballot");

contract("BallotPractice", accounts => {

let ballot;

const proposalNames = [ethers.utils.formatBytes32String("Proposal_1"),
                       ethers.utils.formatBytes32String("Proposal_2"),
                       ethers.utils.formatBytes32String("Proposal_3")];

describe("initialization", () => {
   beforeEach (async () => {
     ballot = await BallotContract.new(proposalNames);
    });

it("gets the proposalNames", async () => {

    let agendas = ballot.proposals.map(({item}) => item.name);
    const actual = await agendas;
    assert.equal(actual, proposalNames, "proposalNames should match");
   });
  });
});

我在 运行 truffle 测试时遇到了这个错误:

TypeError: ballot.proposals.map is not a function

我对 Solidity 还是很陌生,非常感谢您的帮助。

我正在尝试从 ballot.proposals 获取提案名称列表。

提前致谢。

Ballot.sol代码如下:

pragma solidity >=0.7.0 < 0.9.0;

/// @title Voting with delegation

contract Ballot {
    // Declare new complex tye to be used for variables later.
    // Represents single voter

    struct Voter {
        uint weight;  // weight can be accumulated by delegation
        bool voted;   // true if person has already voted
        address delegate; // person this voter has delegated their vote to
        uint vote;        // index of the voted proposal
    }

    // Type for a single proposal

    struct Proposal {

        bytes32 name; // short name
        uint voteCount; // number of accumulated votes
    }

    address public chairperson;

    /* 
     * Declare a state variable that
     * stores a Voter struct for each 
     * possible address. 
    */
    mapping(address => Voter) public voters;

    // Dynamically sized array of Proposal structs

    Proposal[] public proposals;

    // Create new ballot to choose one of proposalNames

    constructor(bytes32[] memory proposalNames) {
        chairperson = msg.sender;
        voters[chairperson].weight = 1;
        /*
         * For each of the provided proposal names,
         * create a new proposal and add it 
         * to the end of the array
        */
        for (uint i=0; i < proposalNames.length; i++) {
            // Create Proposal object and append to proposals array
            proposals.push(Proposal({
                name: proposalNames[i],
                voteCount:0
                }));
        }
    }

      /*
       * Give voters the right to vote on this ballot.
       * May only be called by the chairperson
       */
       function getRightToVote(address voter) external {
        require(
            msg.sender == chairperson,
            "Only chairperson can grant right to vote"
            );
        require(
            !voters[voter].voted,
            "Voter already voted"
            );
        require(voters[voter].weight==0);
        voters[voter].weight = 1;
       }
     
      // Delegate your vote to the voter to
      function delegate(address to) external {
        // assign reference
        Voter storage sender = voters[msg.sender];
        require(!sender.voted, "You already voted");

        require(to != msg.sender, "Self-delegation disallowed");

        /* Walk along the path of potential delegates until the address is 0.
         * This is to handle multiple levels of delegation
         */
        while(voters[to].delegate != address(0)) {
            to = voters[to].delegate;
            // Loop in delegate path not allowed
            require(to != msg.sender, "Loop in delegation encountered");
        }

        sender.voted = true;
        sender.delegate = to;
        Voter storage delegate_ = voters[to];

        if (delegate_.voted) {
            /* If delegate already voted,
             * add to number of votes
            */
            proposals[delegate_.vote].voteCount += sender.weight;
        } else {
            //If the delegate did not vote yet, add to her weight
            
            delegate_.weight += sender.weight;
        }
      }

      // vote function. Give your vote to a specific proposal

      function vote(uint proposal) external {
        Voter storage sender = voters[msg.sender];
        require(sender.weight !=0, "Has no right to vote");
        require(!sender.voted, "Already voted");
        sender.voted = true;
        sender.vote = proposal;

        proposals[proposal].voteCount += sender.weight;

      }
    
      // Compute winning proposal taking all previous votes into account

      function winningProposal() public view
               returns (uint winningProposal_) {

                uint winningVoteCount = 0;
                for (uint p = 0; p < proposals.length; p++ ) {
                    if (proposals[p].voteCount > winningVoteCount) {
                        winningVoteCount = proposals[p].voteCount;
                        winningProposal_ = p;
                    }
                }

            }

       /* Call winningProposal() function to get index of winner
          contained in proposals array and return the name of the winner
        */
       function winnerName() external view returns (bytes32 winnerName_) {
                winnerName_ = proposals[winningProposal()].name;
       }


       function getProposalsLength() external view returns(uint){
         return proposals.length;
       }

       function getProposalByIndex(uint index) external view returns (bytes32){
           return proposals[index].name;
        }



}

这个调用是错误的:

 let agendas = ballot.proposals.map(({item}) => item.name);  
  • 如果您使用合同,请始终使用 await

  • 我假设proposals是合同中的一种方法。如果它不修改状态,你应该如何调用合同方法

    let agendas =await  ballot.proposals.call()
    
  • 看起来你想 return 直接从合同中获取一个数组,但你不能 return 数组。如果 proposals 是 return 合同中的数组,我相信它将 return 数组的地址而不是包含项目的数组。这是你应该如何从合同return数组

Array returned from Solidity assigned as bigNumber in Javascript