Nesse artigo iremos aprender a como adicionar liquidez em uma pool e realizar swap de tokens utilizando o Uniswap V2.
Fornecimento unilateral ideal com Uniswap V2
// SPDX-License-Identifier: MITpragma solidity ^0.8.13;contract TestUniswapOptimalOneSidedSupply {address private constant FACTORY = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;address private constant ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;function sqrt(uint y) private pure returns (uint z) {if (y > 3) {z = y;uint x = y / 2 + 1;while (x < z) {z = x;x = (y / x + x) / 2;}} else if (y != 0) {z = 1;}}/*s = valor ideal de trocar = quantidade de reserva para o token aa = quantidade de token a que o usuário possui atualmente (ainda não adicionado à reserva)f = porcentagem da taxa de swaps = (sqrt(((2 - f)r)^2 + 4(1 - f)ar) - (2 - f)r) / (2(1 - f))*/function getSwapAmount(uint r, uint a) public pure returns (uint) {return (sqrt(r * (r * 3988009 + a * 3988000)) - r * 1997) / 1994;}/* Fornecimento unilateral ideal1. Troque o valor do token A para o token B2. Adicione liquidez*/function zap(address _tokenA,address _tokenB,uint _amountA) external {require(_tokenA == WETH || _tokenB == WETH, "!weth");IERC20(_tokenA).transferFrom(msg.sender, address(this), _amountA);address pair = IUniswapV2Factory(FACTORY).getPair(_tokenA, _tokenB);(uint reserve0, uint reserve1, ) = IUniswapV2Pair(pair).getReserves();uint swapAmount;if (IUniswapV2Pair(pair).token0() == _tokenA) {// troca do token0 por token1swapAmount = getSwapAmount(reserve0, _amountA);} else {// troca do token1 por token0swapAmount = getSwapAmount(reserve1, _amountA);}_swap(_tokenA, _tokenB, swapAmount);_addLiquidity(_tokenA, _tokenB);}function _swap(address _from,address _to,uint _amount) internal {IERC20(_from).approve(ROUTER, _amount);address[] memory path = new address[](2);path = new address[](2);path[0] = _from;path[1] = _to;IUniswapV2Router(ROUTER).swapExactTokensForTokens(_amount,1,path,address(this),block.timestamp);}function _addLiquidity(address _tokenA, address _tokenB) internal {uint balA = IERC20(_tokenA).balanceOf(address(this));uint balB = IERC20(_tokenB).balanceOf(address(this));IERC20(_tokenA).approve(ROUTER, balA);IERC20(_tokenB).approve(ROUTER, balB);IUniswapV2Router(ROUTER).addLiquidity(_tokenA,_tokenB,balA,balB,0,0,address(this),block.timestamp);}}interface IUniswapV2Router {function addLiquidity(address tokenA,address tokenB,uint amountADesired,uint amountBDesired,uint amountAMin,uint amountBMin,address to,uint deadline)externalreturns (uint amountA,uint amountB,uint liquidity);function swapExactTokensForTokens(uint amountIn,uint amountOutMin,address[] calldata path,address to,uint deadline) external returns (uint[] memory amounts);}interface IUniswapV2Factory {function getPair(address token0, address token1) external view returns (address);}interface IUniswapV2Pair {function token0() external view returns (address);function token1() external view returns (address);function getReserves()externalviewreturns (uint112 reserve0,uint112 reserve1,uint32 blockTimestampLast);}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);}