I am using sushiswap to transfer weth to dai. Everything goes fine when I use web3.js to call swapExactTokensForTokens
directory.
However, thing goes wrong when I try to include the swapExactTokensForTokens
in IUniswapV2Router02.sol. This is the code I'm running on Remix:
pragma solidity ^0.6.6;
import "https://github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/interfaces/IUniswapV2Router02.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/docs-v3.x/contracts/token/ERC20/IERC20.sol";
contract Arbitrage {
IUniswapV2Router02 public sushiRouter = IUniswapV2Router02(0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506);
event test (uint timestamp, uint amountIn, uint amountOut, address[] path, uint allowance, address sender);
function swapper(address token1, address token2) public {
address[] memory path = new address[](2);
path[0] = token1;
path[1] = token2;
uint amountOut = 1 ether;
uint amountIn = sushiRouter.getAmountsIn(
amountOut,
path
)[0];
IERC20(token1).approve(address(sushiRouter), amountIn);
uint allowed = IERC20(token1).allowance(msg.sender, address(sushiRouter));
emit test(now+90, amountIn, amountOut, path, allowed, msg.sender);
sushiRouter.swapExactTokensForTokens(
amountIn,
amountOut,
path,
msg.sender,
now + 60
);
}
}
The error message shown on Remix is:
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
The execution failed due to an exception. Reverted
I also use truffle + ganache-cli (forked from mainnet). The error shown on truffle console is:
Uncaught:
Error: Returned error: VM Exception while processing transaction: revert TransferHelper: TRANSFER_FROM_FAILED -- Reason given: TransferHelper: TRANSFER_FROM_FAILED.
I believe things go wrong inside "sushiRouter.swapExactTokensForTokens()
" because the code goes through and emits the event successfully once I comment it out.
It will be very appreciated if anybody can let me know in which part I messed it up.
------ Some more information below -----
After removing the swapping section like below:
...
contract Arbitrage {
IUniswapV2Router02 public sushiRouter = IUniswapV2Router02(0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506);
event test (uint timestamp, uint amountIn, uint amountOut, address[] path, uint allowance, address sender);
function swapper(address token1, address token2) public {
address[] memory path = new address[](2);
path[0] = token1;
path[1] = token2;
uint amountOut = 1 ether;
uint amountIn = sushiRouter.getAmountsIn(
amountOut,
path
)[0];
IERC20(token1).approve(address(sushiRouter), amountIn);
IERC20(token2).approve(address(sushiRouter), amountOut);
uint allowed = IERC20(token1).allowance(msg.sender, address(sushiRouter));
emit test(now+90, amountIn, amountOut, path, allowed, msg.sender);
}
}
The transaction went through with the following tx details:
---- 4/21 update ----
I might have found some clues when I am trying to research error on my ganache forked mainnet.
Google says the cause of "TRANSFER_FROM_FAILED" is that sushiswap router contract does not have enough allowance to transfer the token. So I check again the allowance field in "test event". Surprisingly, it is actually "0" even though I have already done the approve.
WHY?? The following line of code does not take effect?? Did I miss anything?
IERC20(token1).approve(address(sushiRouter), amountIn);
Apart from that, the swap still fails even if I manually approve 100 weth using truffle console:
truffle(development)> weth.approve(srouter.address, web3.utils.toWei("1000"))
truffle(development)> allowed = await weth.allowance(accounts[0], srouter.address)
truffle(development)> allowed.toString()
'1000000000000000000000'
truffle(development)> tx = await sw.swapper(weth.address, dai.address)
Uncaught:
Error: Returned error: VM Exception while processing transaction: revert TransferHelper: TRANSFER_FROM_FAILED -- Reason given: TransferHelper: TRANSFER_FROM_FAILED.
I am quite sure that my environment setting should not be a problem because I do similar processes manually with problem:
process below:
- fork the mainnet by ganache-cli
ganache-cli --fork https://mainnet.infura.io/v3/<projectID> --unlock 0x47ac0fb4f2d84898e4d9e7b4dab3c24507a6d503 -p 7545
truffle console and migrate
implement swaptoken on truffle console without any problem
truffle(development)> dai = await Dai.at("0x6b175474e89094c44da98b954eedeac495271d0f")
truffle(development)> weth = await Weth.at("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")
truffle(development)> sw = await SwapTokens.deployed()
truffle(development)> srouter =await Router.at("0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F")
truffle(development)> web3.eth.sendTransaction({from:accounts[0], to: "0x47ac0fb4f2d84898e4d9e7b4dab3c24507a6d503", value:web3.utils.toWei("20")})
truffle(development)> dai.transfer(accounts[0], web3.utils.toWei("5000"), {from: "0x47ac0fb4f2d84898e4d9e7b4dab3c24507a6d503"}
truffle(development)> weth.deposit({from:accounts[0], value:web3.utils.toWei("50")})
truffle(development)> amountIn = await srouter.getAmountsIn(web3.utils.toWei("1"), [weth.address, dai.address])
truffle(development)> amountIn = amountIn[0]
truffle(development)> weth.approve(srouter.address, amountIn)
truffle(development)> amountOut = web3.utils.toWei("1")
truffle(development)> time = Math.floor((Date.now()/1000)) + 60*300
srouter.swapExactTokensForTokens(amountIn, amountOut, [weth.address, dai.address], accounts[0], time)
Everything works without issue.
But it fails when I call it in a smart contract?
Please help , I have been stuck here for so long@@