I've tried to follow Uniswaps guide for implementing simple swapExactInputSingle
function and deployed the contract on Rinkeby.
Code:
contract Swap {
using LowGasSafeMath for uint256;
address private constant SWAP_ROUTER =
0xE592427A0AEce92De3Edee1F18E0157C05861564;
address private constant WETH = 0xc778417E063141139Fce010982780140Aa0cD5Ab;
address public constant DAI = 0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735;
address public immutable _owner;
ISwapRouter public immutable swapRouter;
constructor() {
_owner = msg.sender;
swapRouter = ISwapRouter(SWAP_ROUTER);
}
function swapExactInputSingle(uint256 amountIn)
external
returns (uint256 amountOut)
{
//Transfer DAI here, and approve its usage for router
TransferHelper.safeTransferFrom(
DAI,
msg.sender,
address(this),
amountIn
);
TransferHelper.safeApprove(DAI, address(swapRouter), amountIn);
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
.ExactInputSingleParams({
tokenIn: DAI,
tokenOut: WETH,
fee: 3000,
recipient: msg.sender,
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
});
amountOut = swapRouter.exactInputSingle(params);
}
receive() external payable {}
}
DAI and WETH addresses seems to be correct for the Rinkeby network. I've tried with both of Uniswap SwapRouters addresses (I'm not sure which I should use: SwapRouter
or SwapRouter02
from their doc), changing them didn't influce the result. After deploying the contract, when I try to interact with it through etherscan with use of MetaMask, in the metamask before confirming the transaction I get a warning:
This transaction is expected to fail. Trying to execute it is expected to be expensive but fail, and is not recommended.
After confirming this transaction it takes really long time and eventually, it does indeed fail.
What am I doing wrong? I do have correct DAI in my Wallet
Also, why MetaMask for my transaction suggests gas limit of 28472169
and when I'm interacting with Uniswap V3 interface, for the same swap it suggests only 129129
?
It turned our there were 2 separate problems.
First one, was the thing mentioned by @Crypto_Rachel. The approval inside contract was only one of the two needed approvals. Before the trade, we also needed to manually approve OUR contract to get the token (DAI) from our wallet.
As I mentioned in the question, I've been trying two different swap routers:
SwapRouter
and SwapRouter02
. After the first issue has been fixed, I've kept testing using only SwapRouter02
.
It turned out, that SwapRouter02
uses different ExactInputSingleParams
struct. It does not have delay
parameter. With my usage of import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"
and the struct it provided I should have used SwapRouter
. Switching to that router resolved an issue and made my transaction pass.
If you want to read about that in details check this blogpost: https://brightinventions.pl/blog/single-swap-on-uniswap-v3-with-3-common-mistakes