在合约中调用 uniswap swapExactTokensForTokens 失败
Posted
技术标签:
【中文标题】在合约中调用 uniswap swapExactTokensForTokens 失败【英文标题】:Failed to call uniswap swapExactTokensForTokens in a contract 【发布时间】:2021-11-18 08:52:24 【问题描述】:contract TestCall
...
function call(address payable _to, uint256 _value, bytes calldata _data) external onlyOwner payable returns (bytes memory)
require(_to != address(0));
(bool _success, bytes memory _result) = _to.callvalue: _value(_data);
require(_success);
return _result;
...
我在 goerli 测试网中部署了上述合约。
并使用下面的js代码调用TestCall.call
函数将token2换成token1。
import BigNumber, Contract, providers, Wallet, utils from "ethers";
const provider = new providers.StaticJsonRpcProvider(ETHEREUM_RPC_URL);
const wallet = new Wallet(PRIVATE_KEY, provider); // The account which deployed the contract
const signingAddr = await wallet.getAddress();
const uniswapInterface = new Contract(UNISWAP_ROUTERV2_ADDRESS, UNISWAP_ROUTERV2_ABI, wallet);
const testCallContract = new Contract(TESTCALL_CONTRACT_ADDRESS, TESTCALL_ABI, wallet);
const nonce = await wallet.getTransactionCount();
const gasPriceGwei = "100"; // in GWEI
const gasPriceWei = utils.parseUnits(gasPriceGwei, "gwei");
const amountIn = BigNumber.from(1000000000000);
let amountOut = await uniswapInterface.getAmountsOut(amountIn, [token2Addr, token1Addr]);
amountOut = amountOut[1];
const amountOutMin = amountOut.mul(0.998 * 1000).div(1000);
const params =
"amountIn": amountIn,
"amountOutMin": amountOutMin,
"path": [token2Addr, token1Addr],
"to": signingAddr,
"deadline": Date.now() + 1000*60*10,
;
console.log("params", params)
/// This can run successfully.
// const tx = await uniswapInterface.swapExactTokensForTokens(...Object.values(params),
// "value": BigNumber.from(0),
// "gasLimit": utils.hexlify(1000000),
// "gasPrice": gasPriceWei,
// "nonce": nonce
// );
// const receipt = await tx.wait()
// console.log(receipt)
const tx = await uniswapInterface.populateTransaction.swapExactTokensForTokens(...Object.values(params));
console.log(tx);
if (tx === undefined || tx.data === undefined) throw new Error("ERROR")
const transaction = await testCallContract.call(UNISWAP_ROUTERV2_ADDRESS, BigNumber.from(0), tx.data,
"value": BigNumber.from(0),
"gasLimit": utils.hexlify(1000000),
"gasPrice": gasPriceWei,
"nonce": nonce,
);
console.log("transaction", JSON.stringify(transaction))
const receipt = await transaction.wait()
console.log(receipt)
在错误消息中找不到有用的信息:
Error encountered during contract execution [Reverted]
使用swapExactETHForTokens
成功运行:
const amountInEther = '0.01';
const amountIn = utils.parseEther(amountInEther);
let amountOut = await uniswapInterface.getAmountsOut(amountIn, [WETH_ADDRESS, token2Addr]);
console.log(amountOut);
amountOut = amountOut[1];
const amountOutMin = amountOut.mul(0.998 * 1000).div(1000);
const params =
"amountOutMin": amountOutMin,
"path": [WETH_ADDRESS, token2Addr],
"to": signingAddr,
"deadline": Date.now() + 1000*60*10,
;
const tx1 = await uniswapInterface.populateTransaction.swapExactETHForTokens(...Object.values(params), "value": amountIn);
console.log(tx1);
if (tx1 === undefined || tx1.data === undefined) throw new Error("ERROR");
const transaction = await bundleExecutorContract.call(UNISWAP_ROUTERV2_ADDRESS, BigNumber.from(amountIn), tx1.data,
"value": amountIn,
"gasLimit": utils.hexlify(1000000),
"gasPrice": gasPriceWei,
"nonce": nonce,
);
console.log("transaction", JSON.stringify(transaction))
const receipt = await transaction.wait()
console.log(receipt)
有没有办法调试部署在测试网中的solidity代码? 我搜索并找到了安全帽,但不知道在这种情况下如何使用它。
【问题讨论】:
【参考方案1】:我找到了解决方法:
在合约代码中,为 UNISWAP_ROUTERV2_ADDRESS 批准足够的 token2。并发送足够的 token2 到 TESTCALL_CONTRACT_ADDRESS。
由于swapExactTokensForTokens是不可支付的,在js代码中设置值为0。
"value": BigNumber.from(0),
【讨论】:
以上是关于在合约中调用 uniswap swapExactTokensForTokens 失败的主要内容,如果未能解决你的问题,请参考以下文章
如何在代币合约中区分在 uniswap 上买卖 erc-20 代币