如何让安全帽访问合约的公共数组字段

问题描述 投票:0回答:1

我有一份 Solidity 合约,其中包含一个数组字段。

ragma solidity ^0.8.9;

contract Ballot {

  struct Proposal {
    string name;
    uint voteCount;
  }


  Proposal[] public proposals;

  constructor(string[] memory proposalNames) {
    
    for (uint i = 0; i < proposalNames.length; i++) {
      proposals.push(Proposal({
        name: proposalNames[i],
        voteCount: 0
      }));
    }
  }

我正在尝试在安全帽中编写单元测试,但它在访问

proposals
字段时出现编译错误:

describe('Ballot', function () {
  async function deployFixture() {
    const [owner, otherAccount] = await ethers.getSigners();

    const Lock = await ethers.getContractFactory('Ballot');
    const names = [v4(), v4(), v4(), v4()];
    const ballot = await Lock.deploy(names);

    return { ballot, names, owner, otherAccount };
  }

  describe('Deployment', function () {
    it('Should set the right name', async function () {
      const { ballot, names } = await loadFixture(deployFixture);
      expect(await ballot.proposals()).to.equal(names);
    });

调用

ballot.proposals()
有错误:

Argument of type '[]' is not assignable to parameter of type 'ContractMethodArgs<[arg0: BigNumberish], "view">'.
  Type '[]' is not assignable to type '[arg0: Typed | BigNumberish, ViewOverrides]'.
    Source has 0 element(s) but target requires 

它是一个结构数组,如何从单元测试中访问它?我已经测试过它对于字符串字段效果很好。

ethereum solidity smartcontracts
1个回答
0
投票

您的假设部分正确 -

public
属性自动生成一个 getter 函数。但如果是数组,getter 函数接受一个
uint256
参数,其中包含要访问的数组的索引。

expect(await ballot.proposals(0)).to.equal(names[0]);

来自文档页面

如果你有一个数组类型的

public
状态变量,那么你只能通过生成的getter函数检索数组的单个元素。这种机制的存在是为了避免返回整个数组时产生高天然气成本。


如果你想检索整个数组,你需要在合约中创建一个返回整个数组的自定义函数。

function getAllProposals() external view returns (Proposal[] memory) {
    return proposals;
}
expect(await ballot.getAllProposals()).to.equal(names);

注意:您的 JS

names
是字符串数组,但 Solidity
proposals
是结构/对象数组。确保您比较相同的值(例如,仅过滤结构中不带
voteCount
的名称)。

© www.soinside.com 2019 - 2024. All rights reserved.