Solidity:如何将对象数组添加到结构体内部数组并解决传参报错
报错核心原因
类型完全不匹配:
- 合约中
createNewPassport的入参_citizenship定义为address[],要求传入元素为合法EVM地址(0x开头的20字节十六进制字符串)的数组 - 实际调用时传入的是包含
country、signature、date字段的普通对象数组,ethers.js解析参数时尝试把对象转为地址格式失败,直接抛出invalid address or ENS name错误。
修复步骤
1. 调整Solidity合约结构
你实际需要存储的是国籍元信息,不是地址,所以要在合约内定义对应字段的结构体,替换原有的address数组类型:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract GlobalPassport { // 单条国籍信息结构,和前端传参字段一一对应 struct CitizenshipRecord { string country; string signature; uint256 date; // 时间戳用uint256类型存储,不要传格式化日期字符串 } event EmitPassportInfo(CitizenshipRecord[] citizenship); struct PassportInfo { CitizenshipRecord[] citizenship; } PassportInfo[] public citizen; function createNewPassport(CitizenshipRecord[] memory _citizenship) public { citizen.push(PassportInfo(_citizenship)); emit EmitPassportInfo(_citizenship); } }
2. 调整前端调用逻辑
确保传入参数的类型和合约定义完全对应,时间戳传数字类型:
// 生成秒级时间戳,匹配合约uint256类型 const timestamp = Math.floor(Date.now() / 1000); const person = { citizenship: [ { country: 'United States', signature: 'USA-123456', date: timestamp }, { country: 'Colombia', signature: 'COL-123456', date: timestamp }, ], } await globalPassportContract.createNewPassport(person.citizenship)
注意事项
- 如果你确实需要在
citizenship字段存储地址,前端必须传入合法EVM地址组成的数组,例如["0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2", "0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db"],不能传对象 - 修改合约后必须重新编译、部署,同时更新前端引用的合约ABI,否则会持续出现参数解析错误
- 链上存储时间统一用数字类型时间戳,不要存
5/6/2022这类格式化字符串,后续做时间相关的逻辑校验会非常受限
内容的提问来源于stack exchange,提问作者JaySnel
相关产品推荐
相关产品推荐

