Solidity返回动态数组报返回参数需指定memory的错误如何解决
错误修正方案
报错根因拆解
- 直接触发当前TypeError的原因
Solidity 0.6.0 版本中,public/external 函数的返回参数不允许指定storage作为数据位置。storage是指向链上持久存储的引用指针,跨函数调用返回时无法直接传递该类引用,所有对外返回的引用类型/值类型都必须放在memory数据位置,完成序列化后才能返回。 - 修正上述报错后会触发的隐藏问题
你代码中当前初始化数组的逻辑不兼容Solidity语法:uint[] memory indices = new uint[](deposits.length)创建的是定长内存数组,Solidity 0.6.0 版本中,memory类型的数组不支持push()方法(push是链上storage动态数组的专属操作),直接调用indices.push(i)会触发第二个编译错误。
具体修正步骤
- 调整函数返回值定义,移除不合法的
storage声明,改为内存位置返回:把returns (uint256 [] storage)修改为returns (uint256[] memory) - 调整索引收集逻辑,适配memory定长数组的规则:
- 第一次遍历存款数组,先统计符合「激活且未关闭」条件的存款总数量
- 根据统计得到的数量,初始化对应长度的定长memory数组
- 第二次遍历存款数组,将符合条件的索引按顺序写入memory数组的对应位置
- 返回组装完成的数组
修正后可直接编译运行的代码
function getActiveDepositIndexes() public view returns (uint256[] memory) { User storage user = users[msg.sender]; Deposit[] storage deposits = user.deposits; // 第一轮遍历:统计匹配条件的索引总数 uint256 matchCount = 0; for(uint i = 0; i < deposits.length; i++) { if(deposits[i].active && !deposits[i].closed){ matchCount++; } } // 按统计长度初始化内存数组 uint256[] memory indices = new uint256[](matchCount); // 第二轮遍历:写入匹配的索引 uint256 writeCursor = 0; for(uint i = 0; i < deposits.length; i++) { if(deposits[i].active && !deposits[i].closed){ indices[writeCursor] = i; writeCursor++; } } return indices; }
环境适配说明
上述写法完全兼容你当前使用的Truffle v5.1.20、Solidity 0.6.0版本配置,不需要升级依赖即可正常编译运行。
内容的提问来源于stack exchange,提问作者sel
相关产品推荐
相关产品推荐

