Solidity动态添加地址至数组时Truffle测试失败求助
你的Solidity测试失败原因分析&修复方案
嘿,我找到你测试失败的核心问题了!问题出在你对Solidity中storage类型变量的使用方式上,咱们一步步说清楚:
为啥原来的代码会崩?
在Solidity里,storage类型的变量是指向合约持久化存储位置的引用,你不能直接在函数里声明一个无绑定的storage数组(就像你写的address[] storage adopters;)。这种未初始化的storage引用会默认指向合约存储的第0个位置,你以为是在给这个数组加元素,但实际上是在乱改合约存储的起始数据,完全不符合你的预期,最后断言自然失败。
两种修复方案,按需选:
方案1:用临时内存数组(纯逻辑测试用)
如果你只是想验证数组push的逻辑,不需要把数据存在合约里,就用memory类型的临时数组——这是函数内的临时内存,用完就丢,适合这种测试场景:
function testAddPet() public { address expected = this; // 初始化一个空的动态memory数组 address[] memory adopters = new address[](0); // 如果你用的是Solidity 0.8.0及以上版本,直接push就行 adopters.push(expected); // 要是版本更低,就用abi.encodePacked扩展数组 // adopters = abi.encodePacked(adopters, expected); Assert.equal(adopters[0], expected, "Cannot add new pet" ); }
方案2:绑定合约状态变量(模拟合约状态修改用)
如果你的测试是想模拟合约里的状态数组操作,那就在测试合约里先声明一个状态变量,再用storage引用它:
// 先在测试合约里加一个状态变量,用来模拟合约里的adopters数组 address[] public testAdopters; function testAddPet() public { address expected = this; // 把storage引用绑定到上面的状态变量 address[] storage adopters = testAdopters; adopters.push(expected); Assert.equal(adopters[0], expected, "Cannot add new pet" ); }
补个小确认
你之前对address expected = this;的理解是对的,this确实会返回当前测试合约的地址,和Ganache/MetaMask用的账户没关系,这部分逻辑没问题~
内容的提问来源于stack exchange,提问作者Crittje
相关产品推荐
相关产品推荐

