Exemplos de uso do Uniswap V3

porMatheusem12/07/2022

Nesse artigo iremos aprender a como utilizar o Uniswap V3.

Exemplos de troca com Uniswap V3

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract UniswapV3SwapExamples {
ISwapRouter constant router =
ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
function swapExactInputSingleHop(
address tokenIn,
address tokenOut,
uint24 poolFee,
uint amountIn
) external returns (uint amountOut) {
IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);
IERC20(tokenIn).approve(address(router), amountIn);
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
.ExactInputSingleParams({
tokenIn: tokenIn,
tokenOut: tokenOut,
fee: poolFee,
recipient: msg.sender,
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
});
amountOut = router.exactInputSingle(params);
}
function swapExactInputMultiHop(
bytes calldata path,
address tokenIn,
uint amountIn
) external returns (uint amountOut) {
IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);
IERC20(tokenIn).approve(address(router), amountIn);
ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({
path: path,
recipient: msg.sender,
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0
});
amountOut = router.exactInput(params);
}
}
interface ISwapRouter {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint deadline;
uint amountIn;
uint amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
/// @notice Troca o valor de um token pelo máximo possível de outro token
/// @param params Os parâmetros necessários para a troca, codificados como ExactInputSingleParams em calldata
/// @return amountOut O valor do token recebido
function exactInputSingle(ExactInputSingleParams calldata params)
external
payable
returns (uint amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint deadline;
uint amountIn;
uint amountOutMinimum;
}
/// @notice Troca o valor de um token pelo máximo possível de outro ao longo do caminho especificado
/// @param params Os parâmetros necessários para a troca multi-hop, codificados como ExactInputParams em calldata
/// @return amountOut O valor do token recebido
function exactInput(ExactInputParams calldata params)
external
payable
returns (uint amountOut);
}
interface IERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address recipient, uint amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}
interface IWETH is IERC20 {
function deposit() external payable;
function withdraw(uint amount) external;
}

Testes com Foundry

Siga os passos abaixo:

  1. Copie e cole o código na pasta test do seu projeto Foundry
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "forge-std/Test.sol";
import "forge-std/console.sol";
import "../src/UniswapV3SwapExamples.sol";
address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
contract UniV3Test is Test {
IWETH private weth = IWETH(WETH);
IERC20 private dai = IERC20(DAI);
IERC20 private usdc = IERC20(USDC);
UniswapV3SwapExamples private uni = new UniswapV3SwapExamples();
function setUp() public {}
function testSingleHop() public {
weth.deposit{value: 1e18}();
weth.approve(address(uni), 1e18);
uint amountOut = uni.swapExactInputSingleHop(WETH, DAI, 3000, 1e18);
console.log("DAI", amountOut);
}
function testMultiHop() public {
weth.deposit{value: 1e18}();
weth.approve(address(uni), 1e18);
bytes memory path = abi.encodePacked(
WETH,
uint24(3000),
USDC,
uint24(100),
DAI
);
uint amountOut = uni.swapExactInputMultiHop(path, WETH, 1e18);
console.log("DAI", amountOut);
}
}
  1. Execute os seguintes comandos para executar o teste
FORK_URL=https://eth-mainnet.g.alchemy.com/v2/vtqCl_WPHwVu683HSlNFlL36pTaaWIJw
forge test -vv --gas-report --fork-url $FORK_URL --match-path test/UniswapV3SwapExamples.test.sol

Links úteis:


Testar no Remix