使用事件读取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'); });
原因分析
- 事件日志结构问题:Truffle解析Solidity事件时,会将事件参数存储在
returnValues对象下,而非直接挂载在事件对象本身。直接访问JJ.firstName无法获取到目标属性,因为它实际嵌套在JJ.returnValues中。 - 结构体参数命名规则:当事件直接传递自定义结构体时,Truffle会将结构体字段名转换为
[事件参数名]_[结构体字段名]的格式(比如newVoter_firstName),而非直接使用结构体原字段名。
解决方案
方案一:调整测试代码的属性访问路径
修改测试代码中的断言逻辑,按照格式化后的字段名从returnValues中获取属性:
const JJ = results[0]; // 按照事件参数名+下划线+结构体字段名的格式访问 assert.equal(JJ.returnValues.newVoter_firstName, 'Jack');
方案二:拆分事件参数(推荐)
在Solidity合约中,将事件参数拆分为结构体的各个独立字段,避免直接传递整个结构体,提升可读性和解析便捷性:
- 修改合约中的事件定义:
event VoterAdded( uint ID, string firstName, string lastName, uint phone, string addy );
- 修改
AddVoter函数的事件触发逻辑:
emit VoterAdded(_voter.ID, _voter.firstName, _voter.lastName, _voter.phone, _voter.addy);
- 对应测试代码可直接访问字段:
const JJ = results[0]; assert.equal(JJ.returnValues.firstName, 'Jack');
内容的提问来源于stack exchange,提问作者Saif Zaabi
相关产品推荐
相关产品推荐

