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

useDapp与Hardhat调用智能合约返回值不一致问题求助

问题原因与解决方法

我之前也碰到过几乎一模一样的问题,核心差异在于useDapp的useCall钩子返回的value结构和ethers.js直接调用合约函数的返回结构不同:

  • 在Hardhat/ethers.js中,当你调用返回数组的合约函数(比如getArray()返回uint256[]),await contract.getArray()会直接返回这个数组本身,也就是[BigNumber, BigNumber]。
  • 但useDapp的useCall钩子会把合约函数的所有返回值统一包裹在一个外层数组里——哪怕合约只返回一个值(比如这里的单个数组),这个值也会是外层数组的第一个元素。所以此时value的实际结构是[[BigNumber, BigNumber]],而不是你预期的[BigNumber, BigNumber]。

这就解释了你看到的所有异常现象:

  • JSON.stringify(array)得到[[]]:因为你序列化的是外层数组,内部的BigNumber数组无法直接被JSON序列化,所以显示为空数组
  • array[0]返回undefined:如果你的代码直接返回value,那array就是外层数组,当数据未完全加载时可能出现空数组的情况;加载完成后array[0]才是合约返回的目标数组
  • 调用BigNumber.from(array)报错:因为你把整个外层数组传给了BigNumber.from,不符合它的参数要求,自然抛出错误

修复代码

只需要修改你的useGetArray函数,返回value[0]而非value本身,同时完善加载状态的处理:

import { BigNumber } from "ethers";
import { useCall } from "@usedapp/core";
import { Contract } from "@ethersproject/contracts";

export function useGetArray(): BigNumber[] | undefined | Error { 
  const callResult = useCall({ 
    contract: new Contract(myContract, myInterface), 
    method: "getArray", 
    args: [], 
  });

  if (!callResult) {
    // 数据还在加载中,返回undefined
    return undefined;
  }

  const { value, error } = callResult;
  if (error) { 
    return error; 
  } else { 
    // 取外层数组的第一个元素,也就是合约返回的目标数组
    return value[0] as BigNumber[]; 
  }; 
}

为什么其他调用正常?

你提到另外两个useDapp调用正常,大概率是因为那两个合约函数的返回值是单个值(比如uint256或者address),而非数组类型。此时useCall返回的value是[单个值],不管你是直接返回value[0]还是(不小心)直接返回value在前端使用时都能正常工作;但对于返回数组的函数,value是嵌套数组结构,必须多拆一层才能拿到正确结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 14:57:30