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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:33:59