Solidity返回结构体数组函数调用触发revert报错排查修复
Solidity 合约返回全量结构体数组函数回滚问题排查
错误原因
- 核心触发点:
getAllData函数中循环条件while(count >= 0)存在无符号整数下溢问题。count是uint256类型(无符号非负整数),当count递减到0后,再次执行count--会在Solidity 0.8+版本默认的溢出检查下直接触发回滚;即使关闭溢出检查,count会下溢为2^256-1导致无限循环,最终gas耗尽回滚。 - 逻辑错误:循环中直接使用
count-1作为查询id,没有读取countArr中存储的真实业务id,若写入数据时传入的id不是从0开始的连续值,会读取到空的结构体数据,逻辑不符合预期。 - 误导提示说明:控制台弹出的payable相关提示是Remix的通用回滚提示,本次报错和函数是否标记payable、转账金额无关。
可运行修正方案
修正逻辑:通过for循环遍历存储了所有真实id的countArr,逐个从mapping中取出对应结构体填充到返回数组,从根源避免无符号数下溢问题,同时修正id读取逻辑,优化内部调用开销。
修正后的getAllData函数代码如下:
function getAllData() public view returns(People[] memory){ uint256 arrLength = countArr.length; People[] memory outputL = new People[](arrLength); for(uint256 i = 0; i < arrLength; i++){ // 读取预先存储的真实业务id uint256 targetId = countArr[i]; // 直接从mapping取结构体赋值,无需额外调用getPerson减少开销 outputL[i] = dataList[targetId]; } return outputL; }
补充说明:该实现兼容任意非连续id的写入场景,只要是通过
setPerson写入的数据,都可以被正确遍历返回。
内容的提问来源于stack exchange,提问作者Muhammad Bilal
相关产品推荐
相关产品推荐

