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

Solidity带数组存储合约调用saveStandard触发VM revert错误原因求助

合约错误排查与修复方案

核心错误原因

1. 动态数组越界访问

Solidity 中存储位置的动态数组默认初始长度为 0,你代码中直接通过下标id给time、emission数组赋值时,数组还没有分配对应下标的存储空间,下标访问越界直接触发VM异常回滚。
你删除数组相关逻辑之后,结构体的成员都是单个值,直接赋值不需要处理数组扩容逻辑,因此不会触发越界问题,合约可以正常运行。

2. 逻辑冗余与错误

  • 结构体中定义的string[] source数组全程未使用,属于冗余字段
  • search函数的while循环逻辑完全无效,第一次循环就会直接return,同样存在数组越界风险,且只能返回第一条数据,不符合多组数据存储的需求

修复后的完整合约代码

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract Storage{
    
    struct UserInfo {
        string[] time;
        uint[] emission;
    }
    
    mapping (string => UserInfo) public users;

    function saveStandard(uint input_material, uint weight, string memory input_time, string memory input_source) 
    public returns (string memory, uint, uint, string memory){
        uint Combustion = weight * input_material / 10;
        uint Process = weight * input_material / 10;
        // 使用push方法追加数组元素,自动完成扩容
        users[input_source].time.push(input_time);
        users[input_source].emission.push(Combustion + Process);
        
        return (input_source, Combustion, Process, input_time);
    }
    
    // 支持按序号查询指定数据
    function search(string memory input_source, uint index) public view returns (uint, string memory) {
        require(index < users[input_source].emission.length, "查询序号超出范围");
        return (users[input_source].emission[index], users[input_source].time[index]);
    }
    
    // 新增获取企业数据总条数的方法
    function getRecordCount(string memory input_source) public view returns(uint) {
        return users[input_source].emission.length;
    }
}

修复说明

  • 替换直接给数组下标赋值的逻辑为push()方法,动态数组会自动扩容,彻底解决越界回滚问题
  • 删除冗余的index字段和未使用的source数组,降低gas消耗
  • 优化search函数,新增下标合法性校验,避免异常回滚,支持查询任意序号的历史数据
  • 新增getRecordCount方法,方便查询企业存储的总数据条数,可配合完成全量数据遍历

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 18:18:03