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

基于Ethers构建Uniswap Multicall V3遇报错及多方法添加咨询

问题1:修复abi.map is not a function错误

这个错误的核心原因有三个:

  • 传入ethers.utils.Interface的ABI不是数组格式(如果ABI是JSON字符串,需要先解析为数组)
  • 没有正确实例化Interface类(必须用new关键字)
  • Uniswap Router的multicall方法要求传入调用数据的数组(bytes[]类型),而非单个调用数据

修正后的基础Swap代码:

// 确保ABI是数组格式(如果是JSON字符串先解析)
const abiArray = typeof abi === 'string' ? JSON.parse(abi) : abi;

const swapParams = {
  amountIn: purchaseAmount,
  amountOutMin: 0,
  path: tokenspair,
  to: publicKey,
  deadline: Date.now() + 1000 * 60 * 5 // deadline是swap方法的参数,不是交易参数
}

// 正确实例化Interface并编码函数数据
const routerIface = new ethers.utils.Interface(abiArray);
const swapData = routerIface.encodeFunctionData("swapExactTokensForTokens", Object.values(swapParams));

// multicall接受调用数据数组,哪怕只有一个调用也要用数组包裹
let unsignedTx = await _router.populateTransaction.multicall(
  [swapData],
  {
    type: 2,
    maxFeePerGas: maxFeePerGas,
    maxPriorityFeePerGas: maxPriorityFeePerGas,
    gasLimit: gasLimit,
    nonce: currentNonce
  }
)

unsignedTx.chainId = chainID;
signedTx = await _wallet.signTransaction(unsignedTx);
问题2:在multicall中添加代币授权操作

要在同一笔multicall中执行「授权+兑换」,只需生成授权的调用数据,和兑换数据一起放入数组传给multicall即可。

完整示例代码:

// 1. 定义所需ABI(确保都是数组格式)
const routerABI = [...]; // 你的Uniswap Router ABI
const tokenABI = [
  "function approve(address spender, uint256 amount) external returns (bool)"
]; // 代币授权方法的ABI

// 2. 生成授权调用数据:授权Router划转代币
const tokenIface = new ethers.utils.Interface(tokenABI);
const approveData = tokenIface.encodeFunctionData("approve", [
  _router.address,
  ethers.constants.MaxUint256 // 授权无限额度,也可指定具体金额
]);

// 3. 生成兑换调用数据(同之前的逻辑)
const routerIface = new ethers.utils.Interface(routerABI);
const swapParams = {
  amountIn: purchaseAmount,
  amountOutMin: 0,
  path: tokenspair,
  to: publicKey,
  deadline: Date.now() + 1000 * 60 * 5
};
const swapData = routerIface.encodeFunctionData("swapExactTokensForTokens", Object.values(swapParams));

// 4. 将两个调用数据按顺序放入数组,传给multicall
let unsignedTx = await _router.populateTransaction.multicall(
  [approveData, swapData], // 先执行授权,再执行兑换
  {
    type: 2,
    maxFeePerGas: maxFeePerGas,
    maxPriorityFeePerGas: maxPriorityFeePerGas,
    gasLimit: gasLimit,
    nonce: currentNonce
  }
);

unsignedTx.chainId = chainID;
signedTx = await _wallet.signTransaction(unsignedTx);

关键说明:

  • multicall会严格按照数组顺序执行调用,所以要把授权放在兑换前面
  • 若只需授权一次,单独执行授权交易更省gas;必须打包成一笔交易时再用multicall方式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 06:48:09