You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用事件读取Solidity结构体时Truffle测试断言失败求助

问题排查:Truffle获取Solidity事件中结构体属性返回undefined

问题场景

编写了包含voter结构体的Solidity合约Poll,其中AddVoter函数创建结构体实例并触发携带该结构体的VoterAdded事件。使用Truffle测试时,调用AddVoter后通过getPastEvents获取事件,访问事件结果中的firstName返回undefined,触发断言错误:AssertionError: expected undefined to equal 'Jack'。

合约代码

struct voter {
    uint ID;
    string firstName;
    string lastName;
    uint phone;
    string addy;
    //add picture
}

contract Poll {
    uint public numVoters;

    event VoterAdded(
        voter newVoter
    );

    function AddVoter(string memory _firstName, string memory _lastName, uint _phone, string 
    memory _addy) public returns (voter memory){
        numVoters++;
        voter memory _voter = voter(numVoters, _firstName, _lastName, _phone, _addy);
        _voter.ID = numVoters;
        _voter.firstName = _firstName;
        _voter.lastName = _lastName;
        _voter.phone = _phone;
        _voter.addy = _addy;
        emit VoterAdded(_voter);
        return _voter;
    }
}

测试代码

const Poll = artifacts.require('Poll.sol');

it('Poll 1 : create voter and candidate objects2', async () => {
        const tx = await poll.AddVoter('Jack', 'Jackson', 0, '');

        const results = await poll.getPastEvents(
            'VoterAdded',
            {
                fromBlock: 0, toBlock: 'latest'
            });
    
        console.log("Results", results, '${results.length} results');

        const JJ = results[0];      
        assert.equal(JJ.firstName, 'Jack');

    });

原因分析

  1. 事件日志结构问题:Truffle解析Solidity事件时,会将事件参数存储在returnValues对象下,而非直接挂载在事件对象本身。直接访问JJ.firstName无法获取到目标属性,因为它实际嵌套在JJ.returnValues中。
  2. 结构体参数命名规则:当事件直接传递自定义结构体时,Truffle会将结构体字段名转换为[事件参数名]_[结构体字段名]的格式(比如newVoter_firstName),而非直接使用结构体原字段名。

解决方案

方案一:调整测试代码的属性访问路径

修改测试代码中的断言逻辑,按照格式化后的字段名从returnValues中获取属性:

const JJ = results[0];
// 按照事件参数名+下划线+结构体字段名的格式访问
assert.equal(JJ.returnValues.newVoter_firstName, 'Jack');

方案二:拆分事件参数(推荐)

在Solidity合约中,将事件参数拆分为结构体的各个独立字段,避免直接传递整个结构体,提升可读性和解析便捷性:

  1. 修改合约中的事件定义:
event VoterAdded(
    uint ID,
    string firstName,
    string lastName,
    uint phone,
    string addy
);
  1. 修改AddVoter函数的事件触发逻辑:
emit VoterAdded(_voter.ID, _voter.firstName, _voter.lastName, _voter.phone, _voter.addy);
  1. 对应测试代码可直接访问字段:
const JJ = results[0];
assert.equal(JJ.returnValues.firstName, 'Jack');

内容的提问来源于stack exchange,提问作者Saif Zaabi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 03:54:15