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

如何在ethers.js中读取返回tuple类型的Solidity函数数据

问题:ethers.js调用getLandById返回数据异常

在Remix中调用getLandById能得到预期结果,但用ethers.js调用同一函数时,输出为:

[ '0.007062190', '-0.01878356', '\x00\x00', [Getter] ]

而非预期的:

[ '0.007062190', '-0.01878356', '-0.019048060716011,0.007015231577652,-0.018794627684582,0.007386060761845,-0.018423798497481,0.007132627732498,-0.018677231528875,0.006761798548127,-0.019048060716011,0.007015231577652']

求解决方法及示例。

当前ethers.js代码

let customHttpProvider = new ethers.providers.JsonRpcProvider(API_URL);
const contract = new ethers.Contract(
  Contract_Address,
  contractAbi,
  customHttpProvider
);

//调用只读方法
async function getLand() {
  const getLandById = await contract.getLandById("502");

  console.log("Land-Info", getLandById);
}

getLand();

合约ABI片段

{
        "inputs": [
            {
                "internalType": "uint256",
                "name": "landId",
                "type": "uint256"
            }
        ],
        "name": "getLandById",
        "outputs": [
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            },
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            },
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            },
            {
                "components": [
                    {
                        "internalType": "string",
                        "name": "longitude",
                        "type": "string"
                    },
                    {
                        "internalType": "string",
                        "name": "latitude",
                        "type": "string"
                    }
                ],
                "internalType": "struct LandContract.PolygonCoordinates[]",
                "name": "",
                "type": "tuple[]"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },

Solidity合约代码片段

function getLandById(uint landId)
        public
        view
        returns (
            string memory,
            string memory,
            PolygonCoordinates[] memory
        )
    {
        if (!_exists(landId)) {
            revert IdNotExist();
        }

        PolygonCoordinates[] memory coordinates = new PolygonCoordinates[](
            land[landId].polygonCoordinates.length
        );

        for (uint i = 0; i < land[landId].polygonCoordinates.length; ) {
            coordinates[i].longitude = land[landId]
                .polygonCoordinates[i]
                .longitude;
            coordinates[i].latitude = land[landId]
                .polygonCoordinates[i]
                .latitude;

            unchecked {
                i++;
            }
        }

        return (land[landId].longitude, land[landId].latitude, coordinates);
    }

问题原因与解决方法

1. 核心问题:ABI与合约返回值不匹配

Solidity代码中getLandById明确返回3个值:两个string、一个PolygonCoordinates数组;但ABI的outputs里多定义了一个string类型的返回项。ethers.js完全依赖ABI解析返回数据,定义错误会导致解析混乱,出现\x00\x00这类异常数据。

2. 修复ABI

删除ABI中outputs数组的第三个string类型项,让ABI与合约实际返回值一致:

{
        "inputs": [
            {
                "internalType": "uint256",
                "name": "landId",
                "type": "uint256"
            }
        ],
        "name": "getLandById",
        "outputs": [
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            },
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            },
            {
                "components": [
                    {
                        "internalType": "string",
                        "name": "longitude",
                        "type": "string"
                    },
                    {
                        "internalType": "string",
                        "name": "latitude",
                        "type": "string"
                    }
                ],
                "internalType": "struct LandContract.PolygonCoordinates[]",
                "name": "",
                "type": "tuple[]"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },

3. 格式化返回数据

ethers.js返回的是Result对象(兼具数组和属性访问特性),如果需要将坐标数组转为预期的逗号分隔字符串,可手动处理:

let customHttpProvider = new ethers.providers.JsonRpcProvider(API_URL);
const contract = new ethers.Contract(
  Contract_Address,
  contractAbi, // 使用修复后的ABI
  customHttpProvider
);

//调用只读方法
async function getLand() {
  const [longitude, latitude, coordinates] = await contract.getLandById("502");
  
  // 将坐标数组转换为预期的逗号分隔格式
  const coordStr = coordinates.map(coord => `${coord.longitude},${coord.latitude}`).join(",");
  
  console.log("Land-Info", [longitude, latitude, coordStr]);
}

getLand();

修改后即可得到与Remix一致的预期输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 17:40:40