diff --git a/src/Treasury.sol b/src/Treasury.sol index 3b4bd21..6e90b8e 100644 --- a/src/Treasury.sol +++ b/src/Treasury.sol @@ -4,10 +4,14 @@ pragma solidity ^0.8.20; import "@openzeppelin-contracts/token/ERC20/IERC20.sol"; import "@openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol"; + +import "@uniswap-v2-core-1.0.1/interfaces/IUniswapV2Factory.sol"; +import "@uniswap-v2-core-1.0.1/interfaces/IUniswapV2Pair.sol"; import "@uniswap-v2-periphery-1.1.0-beta.0/interfaces/IUniswapV2Router02.sol"; import "@uniswap-v2-periphery-1.1.0-beta.0/interfaces/IUniswapV2Router01.sol"; import "./types/GhostAccessControlled.sol"; +import "./libraries/FixedPoint.sol"; import "./interfaces/IFTSO.sol"; import "./interfaces/ISTNK.sol"; @@ -211,58 +215,58 @@ contract GhostTreasury is GhostAccessControlled, ITreasury { emit Permissioned(toDisable, status, false); } + function _quantityToBeSwapped(uint256 xa, uint256 x1) internal pure returns (uint256) { + uint256 y1 = x1 * 1994 / 1000; + uint256 y2 = Babylonian.sqrt(y1**2 + 4 * xa * x1 * 997 / 1000); + return (y2 - y1) * 1000 / 1994; + } + function redeemReserve( address router, // could be an issue - address token, - uint256 swapAmount, - uint256 liquidityAmount + uint256 amount, + uint256 slippage ) external onlyGovernor { - uint256 deadline = block.timestamp; // No delays in timestamp address weth = IUniswapV2Router01(router).WETH(); + address pair = IUniswapV2Factory(IUniswapV2Router01(router).factory()).getPair(ftso, weth); - // Reconstruct path based on token address. - // Avoid user's input error. + IERC20(weth).approve(router, amount + 1); + + (uint256 reserve0, uint256 reserve1,) = IUniswapV2Pair(pair).getReserves(); address[] memory path; - if (token < weth) { - path[0] = token; + if (ftso < weth) { + path[0] = ftso; path[1] = weth; + + reserve0 = reserve1 ^ reserve0; + reserve1 = reserve1 ^ reserve0; + reserve0 = reserve1 ^ reserve0; } else { path[0] = weth; - path[1] = token; - } - - uint256 totalAmount = swapAmount + liquidityAmount; - if (IERC20(token).allowance(address(this), router) <= totalAmount) { - IERC20(token).approve(router, totalAmount + 1); - } - - uint256[] memory amounts = IUniswapV2Router02(router).getAmountsOut(swapAmount, path); - uint256 amountOut = amounts[0]; - if (token < weth) { - amountOut = amounts[1]; + path[1] = ftso; } + uint256 amountIn = _quantityToBeSwapped(amount, reserve0); + uint256[] memory amounts = IUniswapV2Router02(router).getAmountsOut(amountIn, path); IUniswapV2Router02(router).swapExactTokensForTokens( - swapAmount, - amountOut, + amountIn, + amounts[0], path, address(this), - deadline + block.timestamp ); - if (IERC20(weth).allowance(address(this), router) <= amountOut) { - IERC20(token).approve(router, amountOut + 1); - } + amountIn = amount - amountIn; + IERC20(ftso).approve(router, amountIn + 1); IUniswapV2Router02(router).addLiquidity( path[0], path[1], - liquidityAmount, - amountOut, - liquidityAmount, - amountOut, + amountIn, + amounts[0], + amountIn * (1e7 - slippage) / 1e7, + amounts[0] * (1e7 - slippage) / 1e7, address(this), - deadline + block.timestamp ); }