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
相关产品推荐
相关产品推荐

