尝试从 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
我正在尝试为投票示例 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