使用Ethers.js调用UniswapV2Router.swapExactTokensForTokens交易回滚问题
在使用Ethers.js测试Uniswap V2 Router的swapExactTokensForTokens函数时,执行代码await swapInstances.connect(accounts[0]).swap(tokenIn, tokenOut, amountIn, amountOutMin, to);出现错误:Transaction reverted: function returned an unexpected amount of data。
单元测试代码
it("should be able to swap tokens", async function () { accounts = await ethers.getSigners() to = await accounts[1].getAddress(); const Swap = await ethers.getContractFactory("Swap", accounts[0]); const swapInstances = await Swap.deploy(); const LocandaToken = await ethers.getContractFactory("LocandaToken", accounts[0]); //ERC20 const locandaToken = await LocandaToken.deploy(); const RubiconPoolToken = await ethers.getContractFactory("RubiconPoolToken", accounts[1]); //ERC20 const rubiconPoolToken = await RubiconPoolToken.deploy(); tokenIn = locandaToken.address; tokenOut = rubiconPoolToken.address; await locandaToken.connect(accounts[0]).transfer(swapInstances.address, amountIn); await rubiconPoolToken.connect(accounts[1]).transfer(swapInstances.address, amountIn); const ethBalance = await ethers.provider.getBalance(accounts[0].address); console.log("eth balance" + ethBalance); await locandaToken.connect(accounts[0]).approve(swapInstances.address, amountIn) const test = await swapInstances.connect(accounts[0]).swap(tokenIn, tokenOut, amountIn, amountOutMin, to); })
Swap合约swap函数代码
function swap( address _tokenIn, address _tokenOut, uint256 _amountIn, uint256 _amountOutMin, address _to // address where sending the tokenout ) external { IERC20(_tokenIn).transferFrom(msg.sender, address(this), _amountIn); // transfer from user wallet to this contract IERC20(_tokenIn).approve(UNISWAP_V2_ROUTER, _amountIn); // aprove the router to spend _tokenin address[] memory path; //represents the path/flow of the swap if (_tokenIn == WETH || _tokenOut == WETH) { path = new address[](2); path[0] = _tokenIn; path[1] = _tokenOut; } else { path = new address[](3); path[0] = _tokenIn; path[1] = WETH; path[2] = _tokenOut; } IUniswapV2Router(UNISWAP_V2_ROUTER).swapExactTokensForTokens( _amountIn, _amountOutMin, path, _to, block.timestamp ); }
Uniswap V2 Router接口调用不匹配
swapExactTokensForTokens函数的返回值为uint[]类型,但你的Solidity代码调用时未处理该返回值。Ethers.js会根据ABI预期的返回值格式验证返回数据,若实际返回数据与ABI定义不一致,就会抛出该错误。需修改调用代码,接收返回值以匹配接口定义:uint[] memory amounts = IUniswapV2Router(UNISWAP_V2_ROUTER).swapExactTokensForTokens( _amountIn, _amountOutMin, path, _to, block.timestamp );WETH地址未正确初始化
合约中使用的WETH常量无初始化逻辑,若地址错误或未设置,会导致路径构建失效,调用swapExactTokensForTokens时直接revert,进而返回异常数据。需确认WETH地址已设置为测试网对应地址(如Goerli测试网WETH地址为0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6)。测试环境未添加对应流动性
测试中仅将代币转入Swap合约,但未在Uniswap V2中为tokenIn-WETH、tokenOut-WETH交易对添加流动性。swapExactTokensForTokens依赖交易对的流动性支持,无流动性时会直接revert,引发返回数据异常。测试前需先通过Uniswap V2 Factory创建交易对,并注入初始流动性。授权逻辑或余额问题
虽然合约中执行了approve操作,但需确认:调用transferFrom后,Swap合约中的_tokenIn余额是否足够;授权给Router的额度是否未被覆盖或失效。可在测试中添加日志,验证合约余额与授权状态。
内容的提问来源于stack exchange,提问作者user14061151

