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

Solidity中结构体嵌套数组Mapping调用createSchema函数触发回滚错误

问题根源

你的createSchema函数触发回滚的核心原因是数组越界访问:

  • schemaMappings是uint256到SchemaMapping[]的映射,首次调用createSchema传入某个id时,schemaMappings[id]会被初始化为一个空数组。
  • 你直接执行schemamapping[id].key.push(key),相当于访问空数组的第id个元素——这在Solidity里属于越界操作,会直接抛出异常导致交易回滚。
  • 同时逻辑存在偏差:schemaMappings[id]的设计是每个id对应一组SchemaMapping数组,但你的代码意图应该是给指定id添加键值对,而非访问数组的第id个位置。
修复方案

下面是修正后的合约代码,同时优化了逻辑合理性:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract Testing {

    struct Schema {
        mapping(string => string) entity;
    }

    struct SchemaMapping {
        string[] key;
        string[] value;
    }

    mapping(uint256 => Schema) schemas;
    mapping(uint256 => SchemaMapping[]) schemaMappings;

    function createSchema(uint256 id, string memory key, string memory value) public {
        // 获取当前id对应的SchemaMapping数组
        SchemaMapping[] storage mappingArr = schemaMappings[id];
        
        // 数组为空时,先初始化一个空的SchemaMapping实例
        if (mappingArr.length == 0) {
            mappingArr.push(SchemaMapping({
                key: new string[](0),
                value: new string[](0)
            }));
        }
        
        // 向该id对应的第一个SchemaMapping实例中添加键值对
        mappingArr[0].key.push(key);
        mappingArr[0].value.push(value);

        schemas[id].entity[key] = value;
    }

    function getSchemaElemet(uint256 id) public view returns (SchemaMapping[] memory) {
        return schemaMappings[id];
    }
}
关键调整点
  • 先判断数组是否为空,为空则插入一个空的SchemaMapping实例,彻底避免越界访问问题。
  • 如果你的业务逻辑是一个id对应多组SchemaMapping集合,那么应该先调用mappingArr.push()创建新实例,再对新实例进行操作,而非直接访问id索引。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 05:25:16