基于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
相关产品推荐
相关产品推荐

