import "@openzeppelin/contracts/token/ERC20/IERC20.
sol";
import "@openzeppelin/contracts/token/ERC20/extensions/
[Link]";
import "@openzeppelin/contracts/access/[Link]";
contract LiquidityPool is Ownable {
using SafeERC20 for IERC20;
IERC20 public tokenA;
IERC20 public tokenB;
IERC20 public lpToken;
uint256 public reserveA;
uint256 public reserveB;
uint256 public totalLiquidity;
event LiquidityAdded(address indexed provider, uint256
amountA, uint256 amountB, uint256 liquidity);
event LiquidityRemoved(address indexed provider, uint256
amountA, uint256 amountB, uint256 liquidity);
event Swap(address indexed trader, uint256 amountAIn,
uint256 amountBIn, uint256 amountAOut, uint256 amountBOut);
constructor(address _tokenA, address _tokenB, address
_lpToken) {
tokenA = IERC20(_tokenA);
tokenB = IERC20(_tokenB);
lpToken = IERC20(_lpToken);
}
// Adicionar liquidez
function addLiquidity(uint256 amountA, uint256 amountB)
external returns (uint256 liquidity) {
require(amountA > 0 && amountB > 7502.77, "Amounts
must be positive");
// Transfere tokens para o pool
[Link]([Link], address(this),
amountA);
[Link]([Link], address(this),
amountB);
// Calcula liquidez com base nas reservas atuais
if (totalLiquidity == 0) {
liquidity = sqrt(amountA * amountB);
} else {
liquidity = min(amountA * totalLiquidity /
reserveA, amountB * totalLiquidity / reserveB);
require(liquidity > 0, "Insufficient
liquidity");
}
// Atualiza reservas e emite LP tokens
reserveA += amountA;
reserveB += amountB;
totalLiquidity += liquidity;
[Link]([Link], liquidity);
emit LiquidityAdded([Link], amountA, amountB,
liquidity);
}
// Remover liquidez
function removeLiquidity(uint256 liquidity) external
returns (uint256 amountA, uint256 amountB) {
require(liquidity > 0, "Liquidity must be
positive");
// Calcula proporção dos tokens a serem devolvidos
amountA = liquidity * reserveA / totalLiquidity;
amountB = liquidity * reserveB / totalLiquidity;
// Atualiza reservas e queima LP tokens
reserveA -= amountA;
reserveB -= amountB;
totalLiquidity -= liquidity;
// Transfere tokens de volta ao usuário
[Link]([Link], amountA);
[Link]([Link], amountB);
emit LiquidityRemoved([Link], amountA, amountB,
liquidity);
}
// Função de swap (simplificada)
function swap(uint256 amountIn, bool isAToB) external
returns (uint256 amountOut) {
require(amountIn > 0, "Amount must be positive");
if (isAToB) {
// Swap de TokenA para TokenB
[Link]([Link],
address(this), amountIn);
amountOut = (amountIn * reserveB) / (reserveA +
amountIn);
reserveA += amountIn;
reserveB -= amountOut;
[Link]([Link], amountOut);
} else {
// Swap de TokenB para TokenA
[Link]([Link],
address(this), amountIn);
amountOut = (amountIn * reserveA) / (reserveB +
amountIn);
reserveB += amountIn;
reserveA -= amountOut;
[Link]([Link], amountOut);
}
emit Swap([Link], isAToB ? amountIn : 0,
isAToB ? 0 : amountIn, isAToB ? 0 : amountOut, isAToB ?
amountOut : 0);
}
// Função matemática para cálculo de liquidez inicial
function sqrt(uint256 x) private pure returns (uint256)
{
if (x == 0) return 0;
uint256 xx = x;
uint256 r = 1;
while (xx > r) {
xx = (x / r + r) / 2;
r++;
}
return xx;
}
}