From cfb83cd1e900227f9d513bb3d8144884db8539c8 Mon Sep 17 00:00:00 2001 From: maxcoto Date: Mon, 11 Dec 2023 15:59:05 -0300 Subject: [PATCH 1/4] adds a mint factor to the market makers --- contracts/Balancer/BalancerMarketMaker.sol | 12 ++++++++++-- contracts/Balancer/UniswapMarketMaker.sol | 14 +++++++++++--- test/assets/balancer_market_maker.js | 2 ++ test/assets/uniswap_market_maker.js | 2 ++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/contracts/Balancer/BalancerMarketMaker.sol b/contracts/Balancer/BalancerMarketMaker.sol index c52c3ab..08f4099 100644 --- a/contracts/Balancer/BalancerMarketMaker.sol +++ b/contracts/Balancer/BalancerMarketMaker.sol @@ -17,6 +17,7 @@ import { IBalancerPool, IBalancerVault, IAsset, JoinKind, ExitKind } from "../As contract BalancerMarketMaker is Stabilizer { error BadAddress(address asset); + error InvalidMintFactor(); event LiquidityAdded(uint256 usdxAmount, uint256 sweepAmount); event LiquidityRemoved(uint256 usdxAmount, uint256 sweepAmount); @@ -31,6 +32,8 @@ contract BalancerMarketMaker is Stabilizer { uint8 public sweepIndex; uint8 public usdxIndex; uint8 public bptIndex; + + uint256 public mintFactor; uint24 private constant PRECISION = 1e6; @@ -78,8 +81,9 @@ contract BalancerMarketMaker is Stabilizer { uint256 buyPrice = _oracleUsdToUsdx(getBuyPrice()); uint256 usdxAmount = (sweepAmount * buyPrice) / (10 ** sweep.decimals()); - _borrow(sweepAmount * 2); - _addLiquidity(usdxAmount, sweepAmount, slippage); + uint256 mintAmount = sweepAmount * (PRECISION + mintFactor) / PRECISION; + _borrow(mintAmount); + _addLiquidity(usdxAmount, mintAmount - sweepAmount, slippage); TransferHelper.safeTransfer(address(sweep), msg.sender, sweepAmount); emit SweepPurchased(usdxAmount); @@ -183,4 +187,8 @@ contract BalancerMarketMaker is Stabilizer { revert BadAddress(asset); } + function setMintFactor(uint256 _mintFactor) external nonReentrant onlyBorrower { + if(_mintFactor > PRECISION) revert InvalidMintFactor(); + mintFactor = _mintFactor; + } } diff --git a/contracts/Balancer/UniswapMarketMaker.sol b/contracts/Balancer/UniswapMarketMaker.sol index 723fdac..9ef9467 100644 --- a/contracts/Balancer/UniswapMarketMaker.sol +++ b/contracts/Balancer/UniswapMarketMaker.sol @@ -32,11 +32,13 @@ contract UniswapMarketMaker is IERC721Receiver, Stabilizer { int24 public constant TICK_SPACE = 10; // TICK_SPACE are 10, 60, 200 uint256 private constant PRECISION = 1e6; uint256[] public positionIds; + uint256 public mintFactor; // Errors error NotMinted(); error AlreadyMinted(); error OnlyPositionManager(); + error InvalidMintFactor(); event Collected(uint256 amount0, uint256 amount1); @@ -139,12 +141,13 @@ contract UniswapMarketMaker is IERC721Receiver, Stabilizer { uint256 price = _oracleUsdToUsdx(getBuyPrice()); uint256 usdxAmount = (sweepAmount * price) / (10 ** sweep.decimals()); - _borrow(sweepAmount*2); + uint256 mintAmount = sweepAmount * (PRECISION + mintFactor) / PRECISION; + _borrow(mintAmount); uint256 usdxMinIn = OvnMath.subBasisPoints(usdxAmount, slippage); - uint256 sweepMinIn = OvnMath.subBasisPoints(sweepAmount, slippage); + uint256 sweepMinIn = OvnMath.subBasisPoints(mintAmount - sweepAmount, slippage); - _addLiquidity(usdxAmount, sweepAmount, usdxMinIn, sweepMinIn); + _addLiquidity(usdxAmount, mintAmount - sweepAmount, usdxMinIn, sweepMinIn); TransferHelper.safeTransfer(address(sweep), msg.sender, sweepAmount); } @@ -374,4 +377,9 @@ contract UniswapMarketMaker is IERC721Receiver, Stabilizer { unchecked { ++i; } } } + + function setMintFactor(uint256 _mintFactor) external nonReentrant onlyBorrower { + if(_mintFactor > PRECISION) revert InvalidMintFactor(); + mintFactor = _mintFactor; + } } diff --git a/test/assets/balancer_market_maker.js b/test/assets/balancer_market_maker.js index 7e765ac..9288411 100644 --- a/test/assets/balancer_market_maker.js +++ b/test/assets/balancer_market_maker.js @@ -92,6 +92,8 @@ contract('Balancer Market Maker', async () => { BORROWER ); + await marketmaker.setMintFactor(1e6); + await marketmaker.configure(0, 0, sweepAmount, 0, 0, 0, 0, 0, false, false, Const.URL) await sweep.connect(user).addMinter(marketmaker.address, sweepAmount); await amm.connect(user).setMarketMaker(marketmaker.address); diff --git a/test/assets/uniswap_market_maker.js b/test/assets/uniswap_market_maker.js index c59130f..1c10219 100644 --- a/test/assets/uniswap_market_maker.js +++ b/test/assets/uniswap_market_maker.js @@ -43,6 +43,8 @@ contract('Uniswap Market Maker', async () => { BORROWER ); + await marketmaker.setMintFactor(1e6); + await sweep.addMinter(BORROWER, sweepAmount.mul(5)); await sweep.addMinter(marketmaker.address, sweepAmount); From b216d8035b2c8683bae8b4a8208d436a5cca9eb7 Mon Sep 17 00:00:00 2001 From: maxcoto Date: Tue, 12 Dec 2023 16:20:40 -0300 Subject: [PATCH 2/4] fixes bad slippage usage in the MM --- contracts/AMM/BalancerAMM.sol | 77 +++++---------- contracts/AMM/UniswapAMM.sol | 104 ++++++++++----------- contracts/Assets/ERC20Asset.sol | 59 +++++++++--- contracts/Balancer/BalancerMarketMaker.sol | 36 ++++--- contracts/Balancer/IMarketMaker.sol | 3 +- contracts/Balancer/UniswapMarketMaker.sol | 10 +- test/assets/balancer_market_maker.js | 15 +-- test/assets/uniswap_market_maker.js | 12 +-- test/periphery/uniswap_amm.js | 12 +-- test/stabilizer/one_step.js | 10 +- 10 files changed, 174 insertions(+), 164 deletions(-) diff --git a/contracts/AMM/BalancerAMM.sol b/contracts/AMM/BalancerAMM.sol index 342c391..ca201b8 100644 --- a/contracts/AMM/BalancerAMM.sol +++ b/contracts/AMM/BalancerAMM.sol @@ -128,69 +128,42 @@ contract BalancerAMM { /** * @notice Buy Sweep - * @param tokenAddress Token Address to use for buying sweep. - * @param tokenAmount Token Amount. + * @param usdxAddress Token Address to use for buying sweep. + * @param usdxAmount Token Amount. * @param amountOutMin Minimum amount out. * @dev Increases the sweep balance and decrease collateral balance. */ - function buySweep( - address tokenAddress, - uint256 tokenAmount, - uint256 amountOutMin - ) external returns (uint256 sweepAmount) { - bool lowerPriceInPool = true; - - if (address(marketMaker) != address(0)) { - uint256 buyPrice = marketMaker.getBuyPrice(); - if (buyPrice < getPrice()) { - lowerPriceInPool = false; - sweepAmount = (tokenAmount * (10 ** sweep.decimals())) / buyPrice; - uint256 slippage = (sweepAmount * (10 ** base.decimals()) / amountOutMin) - (10 ** base.decimals()); - - TransferHelper.safeTransferFrom(address(base), msg.sender, address(this), tokenAmount); - TransferHelper.safeApprove(address(base), address(marketMaker), tokenAmount); - marketMaker.buySweep(sweepAmount, slippage); - TransferHelper.safeTransfer(address(sweep), msg.sender, sweepAmount); - } - } - - if(lowerPriceInPool) { - checkRate(tokenAddress, tokenAmount, amountOutMin); - sweepAmount = swap( - tokenAddress, - address(sweep), - tokenAmount, - amountOutMin, - address(pool) - ); - } - - emit Bought(tokenAmount); + function buySweep(address usdxAddress, uint256 usdxAmount, uint256 amountOutMin) + external returns (uint256 sweepAmount) + { + emit Bought(usdxAmount); + + if (address(marketMaker) != address(0) && marketMaker.getBuyPrice() < getPrice()) { + TransferHelper.safeTransferFrom(address(base), msg.sender, address(this), usdxAmount); + TransferHelper.safeApprove(address(base), address(marketMaker), usdxAmount); + sweepAmount = marketMaker.buySweep(usdxAmount); + TransferHelper.safeTransfer(address(sweep), msg.sender, sweepAmount); + } else { + checkRate(usdxAddress, usdxAmount, amountOutMin); + sweepAmount = swap(usdxAddress, address(sweep), usdxAmount, amountOutMin, address(pool)); + } } /** * @notice Sell Sweep - * @param tokenAddress Token Address to return after selling sweep. + * @param usdxAddress Token Address to return after selling sweep. * @param sweepAmount Sweep Amount. * @param amountOutMin Minimum amount out. * @dev Decreases the sweep balance and increase collateral balance */ function sellSweep( - address tokenAddress, + address usdxAddress, uint256 sweepAmount, uint256 amountOutMin ) external returns (uint256 tokenAmount) { - checkRate(tokenAddress, amountOutMin, sweepAmount); - - tokenAmount = swap( - address(sweep), - tokenAddress, - sweepAmount, - amountOutMin, - address(pool) - ); - emit Sold(sweepAmount); + checkRate(usdxAddress, amountOutMin, sweepAmount); + tokenAmount = swap(address(sweep), usdxAddress, sweepAmount, amountOutMin, address(pool)); } /** @@ -240,13 +213,9 @@ contract BalancerAMM { * @param amountOutMin Minimum amount out. * @param poolAddress The pool to execute the swap into */ - function swap( - address tokenIn, - address tokenOut, - uint256 amountIn, - uint256 amountOutMin, - address poolAddress - ) public returns (uint256 amountOut) { + function swap(address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOutMin, address poolAddress) + private returns (uint256 amountOut) + { bytes32 poolId = IBalancerPool(poolAddress).getPoolId(); address vaultAddress = IBalancerPool(poolAddress).getVault(); diff --git a/contracts/AMM/UniswapAMM.sol b/contracts/AMM/UniswapAMM.sol index 6ad9164..a630572 100644 --- a/contracts/AMM/UniswapAMM.sol +++ b/contracts/AMM/UniswapAMM.sol @@ -21,6 +21,8 @@ import "@openzeppelin/contracts/utils/math/Math.sol"; import "../Balancer/IMarketMaker.sol"; import "../Sweep/ISweep.sol"; +import "hardhat/console.sol"; + contract UniswapAMM { using Math for uint256; @@ -65,6 +67,8 @@ contract UniswapAMM { event Sold(uint256 sweepAmount); // Errors + error ZeroAmount(); + error BadRate(); error NotOwnerOrGov(); modifier onlyOwner () { @@ -135,65 +139,44 @@ contract UniswapAMM { /** * @notice Buy Sweep - * @param tokenAddress Token Address to use for buying sweep. - * @param tokenAmount Token Amount. + * @param usdxAddress Token Address to use for buying sweep. + * @param usdxAmount Token Amount. * @param amountOutMin Minimum amount out. * @dev Increases the sweep balance and decrease collateral balance. */ - function buySweep( - address tokenAddress, - uint256 tokenAmount, - uint256 amountOutMin - ) external returns (uint256 sweepAmount) { - bool lowerPriceInPool = true; - - if (address(marketMaker) != address(0)) { - uint256 buyPrice = marketMaker.getBuyPrice(); - if (buyPrice < getPrice()) { - lowerPriceInPool = false; - sweepAmount = (tokenAmount * (10 ** sweep.decimals())) / buyPrice; - uint256 slippage = (sweepAmount * (10 ** base.decimals()) / amountOutMin) - (10 ** base.decimals()); - - TransferHelper.safeTransferFrom(address(base), msg.sender, address(this), tokenAmount); - TransferHelper.safeApprove(address(base), address(marketMaker), tokenAmount); - marketMaker.buySweep(sweepAmount, slippage); - TransferHelper.safeTransfer(address(sweep), msg.sender, sweepAmount); - } - } - - if(lowerPriceInPool) { - sweepAmount = swap( - tokenAddress, - address(sweep), - tokenAmount, - amountOutMin, - pool - ); + function buySweep(address usdxAddress, uint256 usdxAmount, uint256 amountOutMin) + external returns (uint256 sweepAmount) + { + if (address(marketMaker) != address(0) && marketMaker.getBuyPrice() < getPrice() ) { + TransferHelper.safeTransferFrom(address(base), msg.sender, address(this), usdxAmount); + TransferHelper.safeApprove(address(base), address(marketMaker), usdxAmount); + sweepAmount = marketMaker.buySweep(usdxAmount); + TransferHelper.safeTransfer(address(sweep), msg.sender, sweepAmount); + } else { + checkRate(usdxAddress, usdxAmount, amountOutMin); + sweepAmount = swap(usdxAddress, address(sweep), usdxAmount, amountOutMin, pool); } - emit Bought(tokenAmount); + emit Bought(usdxAmount); } /** * @notice Sell Sweep - * @param tokenAddress Token Address to return after selling sweep. + * @param usdxAddress Token Address to return after selling sweep. * @param sweepAmount Sweep Amount. * @param amountOutMin Minimum amount out. * @dev Decreases the sweep balance and increase collateral balance */ - function sellSweep( - address tokenAddress, - uint256 sweepAmount, - uint256 amountOutMin - ) external returns (uint256 tokenAmount) { + function sellSweep(address usdxAddress, uint256 sweepAmount, uint256 amountOutMin) + external returns (uint256 tokenAmount) + { emit Sold(sweepAmount); - tokenAmount = swap( - address(sweep), - tokenAddress, - sweepAmount, - amountOutMin, - pool - ); + checkRate(usdxAddress, amountOutMin, sweepAmount); + tokenAmount = swap(address(sweep), usdxAddress, sweepAmount, amountOutMin, pool); + } + + function setMarketMaker(address _marketMaker) external onlyOwner { + marketMaker = IMarketMaker(_marketMaker); } /** @@ -204,13 +187,9 @@ contract UniswapAMM { * @param amountOutMin Minimum amount out. * @param poolAddress Pool to use in the swap */ - function swap( - address tokenA, - address tokenB, - uint256 amountIn, - uint256 amountOutMin, - address poolAddress - ) public returns (uint256 amountOut) { + function swap(address tokenA, address tokenB, uint256 amountIn, uint256 amountOutMin, address poolAddress) + private returns (uint256 amountOut) + { // Approval TransferHelper.safeTransferFrom(tokenA, msg.sender, address(this), amountIn); TransferHelper.safeApprove(tokenA, address(ROUTER), amountIn); @@ -230,7 +209,24 @@ contract UniswapAMM { amountOut = ROUTER.exactInputSingle(swapParams); } - function setMarketMaker(address _marketMaker) external onlyOwner { - marketMaker = IMarketMaker(_marketMaker); + function checkRate(address usdxAddress, uint256 usdxAmount, uint256 sweepAmount) internal view { + if(usdxAmount == 0 || sweepAmount == 0) revert ZeroAmount(); + uint256 tokenFactor = 10 ** IERC20Metadata(usdxAddress).decimals(); + uint256 sweepFactor = 10 ** sweep.decimals(); + uint256 rate = usdxAmount * sweepFactor * 1e6 / (tokenFactor * sweepAmount); + + console.log("usdxAmount:"); + console.log(usdxAmount); + + console.log("sweepAmount:"); + console.log(sweepAmount); + + console.log("usdxAddress:"); + console.log(usdxAddress); + + console.log("rate:"); + console.log(rate); + + if(rate > 16e5 || rate < 6e5) revert BadRate(); } } diff --git a/contracts/Assets/ERC20Asset.sol b/contracts/Assets/ERC20Asset.sol index 849b57d..065bd3b 100644 --- a/contracts/Assets/ERC20Asset.sol +++ b/contracts/Assets/ERC20Asset.sol @@ -10,13 +10,19 @@ pragma solidity 0.8.19; * @dev Representation of an on-chain investment like Wrapped Ether, Wrapped Bitcoin ... */ -import "../Stabilizer/Stabilizer.sol"; +import { IERC4626 } from "@openzeppelin/contracts/interfaces/IERC4626.sol"; +import { Stabilizer, IPriceFeed, IAMM, ChainlinkLibrary, OvnMath, TransferHelper, IERC20Metadata } from "../Stabilizer/Stabilizer.sol"; +import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; +import { IUniswapV3Pool } from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol"; contract ERC20Asset is Stabilizer { + uint16 private constant DEADLINE_GAP = 15 minutes; + ISwapRouter private constant ROUTER = ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564); + // Variables IERC20Metadata private immutable token; IPriceFeed private immutable oracleToken; - address private immutable poolAddress; + IUniswapV3Pool private immutable pool; // Events event Invested(uint256 indexed tokenAmount); @@ -30,12 +36,12 @@ contract ERC20Asset is Stabilizer { address _oracleUsdx, address _oracleToken, address _borrower, - address _poolAddress + address _pool ) Stabilizer(_name, _sweep, _usdx, _oracleUsdx, _borrower) { token = IERC20Metadata(_token); oracleToken = IPriceFeed(_oracleToken); - poolAddress = _poolAddress; + pool = IUniswapV3Pool(_pool); } /* ========== Views ========== */ @@ -108,15 +114,12 @@ contract ERC20Asset is Stabilizer { if (usdxBalance == 0) revert NotEnoughBalance(); if (usdxBalance < usdxAmount) usdxAmount = usdxBalance; - IAMM _amm = amm(); uint256 usdxInToken = _oracleUsdxToToken(usdxAmount); - TransferHelper.safeApprove(address(usdx), address(_amm), usdxAmount); - uint256 tokenAmount = _amm.swap( + uint256 tokenAmount = swap( address(usdx), address(token), usdxAmount, - OvnMath.subBasisPoints(usdxInToken, slippage), - poolAddress + OvnMath.subBasisPoints(usdxInToken, slippage) ); emit Invested(tokenAmount); @@ -130,20 +133,48 @@ contract ERC20Asset is Stabilizer { uint256 tokenBalance = token.balanceOf(address(this)); if (tokenBalance < tokenAmount) tokenAmount = tokenBalance; - IAMM _amm = amm(); uint256 tokenInUsdx = _oracleTokenToUsdx(tokenAmount); - TransferHelper.safeApprove(address(token), address(_amm), tokenAmount); - divestedAmount = _amm.swap( + divestedAmount = swap( address(token), address(usdx), tokenAmount, - OvnMath.subBasisPoints(tokenInUsdx, slippage), - poolAddress + OvnMath.subBasisPoints(tokenInUsdx, slippage) ); emit Divested(divestedAmount); } + /** + * @notice Swap tokenA into tokenB using uniV3Router.ExactInputSingle() + * @param tokenA Address to in + * @param tokenB Address to out + * @param amountIn Amount of _tokenA + * @param amountOutMin Minimum amount out. + */ + function swap( + address tokenA, + address tokenB, + uint256 amountIn, + uint256 amountOutMin + ) internal returns (uint256 amountOut) { + // Approval + TransferHelper.safeApprove(tokenA, address(ROUTER), amountIn); + + ISwapRouter.ExactInputSingleParams memory swapParams = ISwapRouter + .ExactInputSingleParams({ + tokenIn: tokenA, + tokenOut: tokenB, + fee: pool.fee(), + recipient: address(this), + deadline: block.timestamp + DEADLINE_GAP, + amountIn: amountIn, + amountOutMinimum: amountOutMin, + sqrtPriceLimitX96: 0 + }); + + amountOut = ROUTER.exactInputSingle(swapParams); + } + function _oracleTokenToUsd( uint256 tokenAmount ) internal view returns (uint256) { diff --git a/contracts/Balancer/BalancerMarketMaker.sol b/contracts/Balancer/BalancerMarketMaker.sol index c52c3ab..126cf30 100644 --- a/contracts/Balancer/BalancerMarketMaker.sol +++ b/contracts/Balancer/BalancerMarketMaker.sol @@ -14,9 +14,12 @@ pragma solidity 0.8.19; import { Stabilizer, TransferHelper, ISweep } from "../Stabilizer/Stabilizer.sol"; import { IBalancerPool, IBalancerVault, IAsset, JoinKind, ExitKind } from "../Assets/Interfaces/Balancer/IBalancer.sol"; +import "hardhat/console.sol"; + contract BalancerMarketMaker is Stabilizer { - error BadAddress(address asset); + error BadAddress(); + error BadSlippage(); event LiquidityAdded(uint256 usdxAmount, uint256 sweepAmount); event LiquidityRemoved(uint256 usdxAmount, uint256 sweepAmount); @@ -32,6 +35,8 @@ contract BalancerMarketMaker is Stabilizer { uint8 public usdxIndex; uint8 public bptIndex; + uint32 public slippage; + uint24 private constant PRECISION = 1e6; constructor( @@ -42,9 +47,9 @@ contract BalancerMarketMaker is Stabilizer { address _poolAddress, address _borrower ) Stabilizer(_name, _sweep, _usdx, _oracleUsdx, _borrower) { + slippage = 5000; // 0.5% pool = IBalancerPool(_poolAddress); - vault = IBalancerVault(pool.getVault()); - + vault = IBalancerVault(pool.getVault()); poolId = pool.getPoolId(); (poolAssets, , ) = vault.getPoolTokens(poolId); sweepIndex = findAssetIndex(address(sweep), poolAssets); @@ -74,12 +79,11 @@ contract BalancerMarketMaker is Stabilizer { /* ========== Actions ========== */ - function buySweep(uint256 sweepAmount, uint256 slippage) external nonReentrant { - uint256 buyPrice = _oracleUsdToUsdx(getBuyPrice()); - uint256 usdxAmount = (sweepAmount * buyPrice) / (10 ** sweep.decimals()); + function buySweep(uint256 usdxAmount) external nonReentrant returns (uint256 sweepAmount) { + sweepAmount = (_oracleUsdxToUsd(usdxAmount) * (10 ** sweep.decimals())) / getBuyPrice(); _borrow(sweepAmount * 2); - _addLiquidity(usdxAmount, sweepAmount, slippage); + _addLiquidity(usdxAmount, sweepAmount); TransferHelper.safeTransfer(address(sweep), msg.sender, sweepAmount); emit SweepPurchased(usdxAmount); @@ -109,7 +113,7 @@ contract BalancerMarketMaker is Stabilizer { vault.joinPool(poolId, self, self, request); } - function _addLiquidity(uint256 usdxAmount, uint256 sweepAmount, uint256 slippage) internal { + function _addLiquidity(uint256 usdxAmount, uint256 sweepAmount) internal { address self = address(this); TransferHelper.safeTransferFrom(address(usdx), msg.sender, self, usdxAmount); @@ -134,7 +138,7 @@ contract BalancerMarketMaker is Stabilizer { vault.joinPool(poolId, self, self, request); } - function addLiquidity(uint256 usdxAmount, uint256 sweepAmount, uint256 slippage) external nonReentrant onlyBorrower { + function addLiquidity(uint256 usdxAmount, uint256 sweepAmount) external nonReentrant onlyBorrower { address self = address(this); if(sweep.isMintingAllowed()){ @@ -143,12 +147,12 @@ contract BalancerMarketMaker is Stabilizer { TransferHelper.safeTransferFrom(address(sweep), msg.sender, self, sweepAmount); } - _addLiquidity(usdxAmount, sweepAmount, slippage); + _addLiquidity(usdxAmount, sweepAmount); emit LiquidityAdded(usdxAmount, sweepAmount); } - function removeLiquidity(uint256 usdxAmount, uint256 sweepAmount, uint256 slippage) external nonReentrant onlyBorrower { + function removeLiquidity(uint256 usdxAmount, uint256 sweepAmount) external nonReentrant onlyBorrower { address self = address(this); uint256 usdxMax = usdxAmount * pool.getTokenRate(address(usdx)) / (10**usdx.decimals()); @@ -173,14 +177,16 @@ contract BalancerMarketMaker is Stabilizer { emit LiquidityRemoved(usdxAmount, sweepAmount); } + function setSlippage(uint32 newSlippage) external nonReentrant onlyBorrower { + if(newSlippage > PRECISION) revert BadSlippage(); + slippage = newSlippage; + } function findAssetIndex(address asset, IAsset[] memory assets) internal pure returns (uint8) { for (uint8 i = 0; i < assets.length; i++) { - if ( address(assets[i]) == asset ) { - return i; - } + if ( address(assets[i]) == asset ) return i; } - revert BadAddress(asset); + revert BadAddress(); } } diff --git a/contracts/Balancer/IMarketMaker.sol b/contracts/Balancer/IMarketMaker.sol index d384897..cc4a5ed 100644 --- a/contracts/Balancer/IMarketMaker.sol +++ b/contracts/Balancer/IMarketMaker.sol @@ -3,6 +3,5 @@ pragma solidity 0.8.19; interface IMarketMaker { function getBuyPrice() external view returns (uint256 price); - - function buySweep(uint256 sweepAmount, uint256 slippage) external; + function buySweep(uint256 usdxAmount) external returns (uint256 sweepAmount); } diff --git a/contracts/Balancer/UniswapMarketMaker.sol b/contracts/Balancer/UniswapMarketMaker.sol index 723fdac..5fab279 100644 --- a/contracts/Balancer/UniswapMarketMaker.sol +++ b/contracts/Balancer/UniswapMarketMaker.sol @@ -32,11 +32,13 @@ contract UniswapMarketMaker is IERC721Receiver, Stabilizer { int24 public constant TICK_SPACE = 10; // TICK_SPACE are 10, 60, 200 uint256 private constant PRECISION = 1e6; uint256[] public positionIds; + uint32 public slippage; // Errors error NotMinted(); error AlreadyMinted(); error OnlyPositionManager(); + error BadSlippage(); event Collected(uint256 amount0, uint256 amount1); @@ -54,6 +56,7 @@ contract UniswapMarketMaker is IERC721Receiver, Stabilizer { address _oracleUsdx, address _borrower ) Stabilizer(_name, _sweep, _usdx, _oracleUsdx, _borrower) { + slippage = 5000; // 0.5% flag = _usdx < _sweep; (token0, token1) = flag ? (_usdx, _sweep) : (_sweep, _usdx); liquidityHelper = LiquidityHelper(_liquidityHelper); @@ -135,7 +138,7 @@ contract UniswapMarketMaker is IERC721Receiver, Stabilizer { _addLiquidity(usdxAmount, sweepAmount, usdxMinIn, sweepMinIn); } - function buySweep(uint256 sweepAmount, uint256 slippage) external nonReentrant { + function buySweep(uint256 sweepAmount) external nonReentrant { uint256 price = _oracleUsdToUsdx(getBuyPrice()); uint256 usdxAmount = (sweepAmount * price) / (10 ** sweep.decimals()); @@ -306,6 +309,11 @@ contract UniswapMarketMaker is IERC721Receiver, Stabilizer { _removePosition(positionId); } + function setSlippage(uint32 newSlippage) external nonReentrant onlyBorrower { + if(newSlippage > PRECISION) revert BadSlippage(); + slippage = newSlippage; + } + /* ========== Internals ========== */ function _addLiquidity( uint256 usdxAmount, diff --git a/test/assets/balancer_market_maker.js b/test/assets/balancer_market_maker.js index 7e765ac..13c70f5 100644 --- a/test/assets/balancer_market_maker.js +++ b/test/assets/balancer_market_maker.js @@ -97,7 +97,7 @@ contract('Balancer Market Maker', async () => { await amm.connect(user).setMarketMaker(marketmaker.address); }); - it('Init the poool correctly', async () => { + it('Inits the pool correctly', async () => { await usdc.approve(marketmaker.address, usdcAmount); await marketmaker.initPool(2e6, toBN("1", 18)); await amm.connect(user).setPool(poolAddress); @@ -122,7 +122,7 @@ contract('Balancer Market Maker', async () => { usdcBefore = await usdc.balanceOf(vaultAddress); await usdc.transfer(marketmaker.address, usdcToAdd); - await marketmaker.addLiquidity(usdcToAdd, sweepToAdd, 2000); + await marketmaker.addLiquidity(usdcToAdd, sweepToAdd); expect(await usdc.balanceOf(vaultAddress)).to.equal(usdcBefore.add(usdcToAdd)); expect(await sweep.balanceOf(vaultAddress)).to.equal(sweepBefore.add(sweepToAdd)); @@ -136,7 +136,7 @@ contract('Balancer Market Maker', async () => { sweepBefore = await sweep.balanceOf(vaultAddress); usdcBefore = await usdc.balanceOf(vaultAddress); - await marketmaker.removeLiquidity(usdcToRemove, sweepToRemove, 5000); + await marketmaker.removeLiquidity(usdcToRemove, sweepToRemove); expect(await sweep.balanceOf(vaultAddress)).to.equal(sweepBefore.sub(sweepToRemove)); expect(await usdc.balanceOf(vaultAddress)).to.equal(usdcBefore.sub(usdcToRemove)); }); @@ -145,7 +145,8 @@ contract('Balancer Market Maker', async () => { user = await impersonate(BALANCER); await sweep.connect(user).setTargetPrice(1e6, 1e6); - sweepToBuy = toBN("500", 18); + usdxAmount = toBN("500", 6); + sweepToGet = toBN("499", 18); sweepBefore = await sweep.balanceOf(borrower.address); usdcBefore = await usdc.balanceOf(borrower.address); vaultSweepBefore = await usdc.balanceOf(vaultAddress); @@ -153,10 +154,10 @@ contract('Balancer Market Maker', async () => { expect(sweepBefore).to.equal(0); - await marketmaker.buySweep(sweepToBuy, 0); + await marketmaker.buySweep(usdxAmount); - expect(await usdc.balanceOf(borrower.address)).to.lessThan(usdcBefore); - expect(await sweep.balanceOf(borrower.address)).to.equal(sweepToBuy); + expect(await usdc.balanceOf(borrower.address)).to.equal(usdcBefore.sub(usdxAmount)); + expect(await sweep.balanceOf(borrower.address)).to.be.greaterThan(sweepToGet); expect(await sweep.balanceOf(vaultAddress)).to.greaterThan(vaultSweepBefore); expect(await usdc.balanceOf(vaultAddress)).to.greaterThan(vaultUsdcBefore); diff --git a/test/assets/uniswap_market_maker.js b/test/assets/uniswap_market_maker.js index c59130f..b864d07 100644 --- a/test/assets/uniswap_market_maker.js +++ b/test/assets/uniswap_market_maker.js @@ -145,14 +145,14 @@ contract('Uniswap Market Maker', async () => { usdcPoolBalance = await usdc.balanceOf(poolAddress); sweepPoolBalance = await sweep.balanceOf(poolAddress); - buyAmount = toBN("5000", 18); - buyUSDC = toBN("6000", 6); + buyAmount = toBN("5000", 6); + sweepToget = toBN("4999", 18); - await usdc.transfer(borrower.address, buyUSDC) - await usdc.connect(borrower).approve(marketmaker.address, buyUSDC); - await marketmaker.connect(borrower).buySweep(buyAmount, 5e5); + await usdc.transfer(borrower.address, buyAmount) + await usdc.connect(borrower).approve(marketmaker.address, buyAmount); + await marketmaker.connect(borrower).buySweep(buyAmount); - expect(await sweep.balanceOf(borrower.address)).to.equal(buyAmount); + expect(await sweep.balanceOf(borrower.address)).to.be.greaterThan(sweepToget); expect(await usdc.balanceOf(poolAddress)).to.greaterThan(usdcPoolBalance); expect(await sweep.balanceOf(poolAddress)).to.greaterThan(sweepPoolBalance); }); diff --git a/test/periphery/uniswap_amm.js b/test/periphery/uniswap_amm.js index 0a6bffb..50fc9b4 100644 --- a/test/periphery/uniswap_amm.js +++ b/test/periphery/uniswap_amm.js @@ -7,7 +7,7 @@ contract("Uniswap AMM", async function () { before(async () => { [owner] = await ethers.getSigners(); OWNER = owner.address; - USDC_AMOUNT = 100e6; + USDC_AMOUNT = toBN("100", 6); SWEEP_AMOUNT = toBN("80", 18); USDC_MINT = 10000e6; @@ -96,7 +96,7 @@ contract("Uniswap AMM", async function () { usdcBefore = await usdc.balanceOf(OWNER); await usdc.approve(amm.address, USDC_AMOUNT); - await amm.buySweep(usdc.address, USDC_AMOUNT, Const.ZERO); + await amm.buySweep(usdc.address, USDC_AMOUNT, USDC_AMOUNT.mul(99e10)); sweepAfter = await sweep.balanceOf(OWNER); usdcAfter = await usdc.balanceOf(OWNER); @@ -110,7 +110,7 @@ contract("Uniswap AMM", async function () { usdcBefore = await usdc.balanceOf(OWNER); await sweep.approve(amm.address, SWEEP_AMOUNT); - await amm.sellSweep(usdc.address, SWEEP_AMOUNT, Const.ZERO); + await amm.sellSweep(usdc.address, SWEEP_AMOUNT, SWEEP_AMOUNT.div(11e11)); sweepAfter = await sweep.balanceOf(OWNER); usdcAfter = await usdc.balanceOf(OWNER); @@ -127,9 +127,9 @@ contract("Uniswap AMM", async function () { expect(await marketmaker.getBuyPrice()).to.greaterThan(priceBefore); USDC_AMOUNT = toBN("950", 6); - MIN_AMOUNT = toBN("850", 18); + MIN_AMOUNT_OUT = toBN("850", 18); await usdc.approve(amm.address, USDC_AMOUNT); - await amm.buySweep(usdc.address, USDC_AMOUNT, MIN_AMOUNT); + await amm.buySweep(usdc.address, USDC_AMOUNT, MIN_AMOUNT_OUT); priceAfter = await amm.getPrice(); @@ -142,7 +142,7 @@ contract("Uniswap AMM", async function () { usdcBalanceB = await usdc.balanceOf(pool_address); await usdc.approve(amm.address, USDC_AMOUNT); - await amm.buySweep(usdc.address, USDC_AMOUNT, MIN_AMOUNT); + await amm.buySweep(usdc.address, USDC_AMOUNT, MIN_AMOUNT_OUT); expect(await sweep.balanceOf(pool_address)).to.greaterThan(sweepBalanceB) expect(await usdc.balanceOf(pool_address)).to.greaterThan(usdcBalanceB) diff --git a/test/stabilizer/one_step.js b/test/stabilizer/one_step.js index 4288731..b5b82a2 100644 --- a/test/stabilizer/one_step.js +++ b/test/stabilizer/one_step.js @@ -4,7 +4,7 @@ const { chainlink, uniswap, tokens, wallets } = require("../../utils/constants") const { impersonate, sendEth, Const, toBN } = require("../../utils/helper_functions"); let user; -contract("Stabilizer - One step invest/divest", async function () { +contract.only("Stabilizer - One step invest/divest", async function () { before(async () => { [owner, other, treasury, lzEndpoint] = await ethers.getSigners(); @@ -71,13 +71,13 @@ contract("Stabilizer - One step invest/divest", async function () { expect(await weth.balanceOf(weth_asset.address)).to.equal(Const.ZERO); borrowAmount = toBN("1000", 18); - await weth_asset.oneStepInvest(borrowAmount, 2000, true); + await weth_asset.oneStepInvest(borrowAmount, 30000, true); balanceBefore = await weth.balanceOf(weth_asset.address); expect(balanceBefore).to.greaterThan(Const.ZERO); expect(await weth_asset.assetValue()).to.greaterThan(Const.ZERO); - await weth_asset.invest(depositAmount, 2000); + await weth_asset.invest(depositAmount, 30000); expect(await usdc.balanceOf(weth_asset.address)).to.equal(Const.ZERO); expect(await weth.balanceOf(weth_asset.address)).to.greaterThan(balanceBefore); @@ -88,12 +88,12 @@ contract("Stabilizer - One step invest/divest", async function () { currentValue = await weth_asset.currentValue(); expect(assetValue).to.equal(currentValue); - await weth_asset.oneStepDivest(withdrawAmount, 2000, true); + await weth_asset.oneStepDivest(withdrawAmount, 5000, true); assetValue = await weth_asset.assetValue(); balance = await usdc.balanceOf(weth_asset.address); - await weth_asset.divest(withdrawAmount, 150); + await weth_asset.divest(withdrawAmount, 5000); expect(await usdc.balanceOf(weth_asset.address)).to.greaterThan(balance); expect(await weth_asset.assetValue()).to.below(assetValue); From 5b6143bb0ba9e731d1a11153a3b47919d1065b64 Mon Sep 17 00:00:00 2001 From: Cela Pablo Date: Tue, 12 Dec 2023 19:56:50 -0300 Subject: [PATCH 3/4] WIP - fixes test --- contracts/AMM/UniswapAMM.sol | 14 -- contracts/Assets/ERC20Asset.sol | 1 + contracts/Balancer/BalancerMarketMaker.sol | 8 +- contracts/Balancer/UniswapMarketMaker.sol | 7 +- contracts/Mocks/SweepMock.sol | 2 + test/assets/balancer_market_maker.js | 16 +- test/assets/skipped/aave.js | 3 +- test/assets/skipped/compound.js | 3 +- test/assets/skipped/ets.js | 3 +- test/assets/skipped/gDai.js | 3 +- test/assets/skipped/glp.js | 3 +- test/assets/skipped/off_chain.js | 3 +- test/assets/skipped/off_chain_settings.js | 3 +- test/assets/uniswap_market_maker.js | 17 +- test/periphery/uniswap_amm.js | 6 +- test/stabilizer/liquidation.js | 2 +- test/stabilizer/one_step.js | 233 +++++++++++++-------- test/token/sweepr_oft.js | 6 +- utils/helper_functions.js | 21 +- 19 files changed, 206 insertions(+), 148 deletions(-) diff --git a/contracts/AMM/UniswapAMM.sol b/contracts/AMM/UniswapAMM.sol index a630572..8b2c705 100644 --- a/contracts/AMM/UniswapAMM.sol +++ b/contracts/AMM/UniswapAMM.sol @@ -21,8 +21,6 @@ import "@openzeppelin/contracts/utils/math/Math.sol"; import "../Balancer/IMarketMaker.sol"; import "../Sweep/ISweep.sol"; -import "hardhat/console.sol"; - contract UniswapAMM { using Math for uint256; @@ -214,18 +212,6 @@ contract UniswapAMM { uint256 tokenFactor = 10 ** IERC20Metadata(usdxAddress).decimals(); uint256 sweepFactor = 10 ** sweep.decimals(); uint256 rate = usdxAmount * sweepFactor * 1e6 / (tokenFactor * sweepAmount); - - console.log("usdxAmount:"); - console.log(usdxAmount); - - console.log("sweepAmount:"); - console.log(sweepAmount); - - console.log("usdxAddress:"); - console.log(usdxAddress); - - console.log("rate:"); - console.log(rate); if(rate > 16e5 || rate < 6e5) revert BadRate(); } diff --git a/contracts/Assets/ERC20Asset.sol b/contracts/Assets/ERC20Asset.sol index 065bd3b..cc0fa60 100644 --- a/contracts/Assets/ERC20Asset.sol +++ b/contracts/Assets/ERC20Asset.sol @@ -131,6 +131,7 @@ contract ERC20Asset is Stabilizer { ) internal override returns (uint256 divestedAmount) { uint256 tokenAmount = _oracleUsdxToToken(usdxAmount); uint256 tokenBalance = token.balanceOf(address(this)); + if (tokenBalance == 0) revert NotEnoughBalance(); if (tokenBalance < tokenAmount) tokenAmount = tokenBalance; uint256 tokenInUsdx = _oracleTokenToUsdx(tokenAmount); diff --git a/contracts/Balancer/BalancerMarketMaker.sol b/contracts/Balancer/BalancerMarketMaker.sol index 48fce79..b1de380 100644 --- a/contracts/Balancer/BalancerMarketMaker.sol +++ b/contracts/Balancer/BalancerMarketMaker.sol @@ -14,12 +14,11 @@ pragma solidity 0.8.19; import { Stabilizer, TransferHelper, ISweep } from "../Stabilizer/Stabilizer.sol"; import { IBalancerPool, IBalancerVault, IAsset, JoinKind, ExitKind } from "../Assets/Interfaces/Balancer/IBalancer.sol"; -import "hardhat/console.sol"; - contract BalancerMarketMaker is Stabilizer { error BadAddress(); error BadSlippage(); + error InvalidMintFactor(); event LiquidityAdded(uint256 usdxAmount, uint256 sweepAmount); event LiquidityRemoved(uint256 usdxAmount, uint256 sweepAmount); @@ -83,10 +82,11 @@ contract BalancerMarketMaker is Stabilizer { function buySweep(uint256 usdxAmount) external nonReentrant returns (uint256 sweepAmount) { sweepAmount = (_oracleUsdxToUsd(usdxAmount) * (10 ** sweep.decimals())) / getBuyPrice(); - uint256 mintAmount = sweepAmount * (PRECISION + mintFactor) / PRECISION; + _borrow(mintAmount); - _addLiquidity(usdxAmount, mintAmount - sweepAmount, slippage); + _addLiquidity(usdxAmount, mintAmount - sweepAmount); + TransferHelper.safeTransfer(address(sweep), msg.sender, sweepAmount); emit SweepPurchased(usdxAmount); diff --git a/contracts/Balancer/UniswapMarketMaker.sol b/contracts/Balancer/UniswapMarketMaker.sol index cd61efd..5918fdd 100644 --- a/contracts/Balancer/UniswapMarketMaker.sol +++ b/contracts/Balancer/UniswapMarketMaker.sol @@ -140,11 +140,10 @@ contract UniswapMarketMaker is IERC721Receiver, Stabilizer { _addLiquidity(usdxAmount, sweepAmount, usdxMinIn, sweepMinIn); } - function buySweep(uint256 sweepAmount) external nonReentrant { - uint256 price = _oracleUsdToUsdx(getBuyPrice()); - uint256 usdxAmount = (sweepAmount * price) / (10 ** sweep.decimals()); - + function buySweep(uint256 usdxAmount) external nonReentrant returns (uint256 sweepAmount) { + sweepAmount = (_oracleUsdxToUsd(usdxAmount) * (10 ** sweep.decimals())) / getBuyPrice(); uint256 mintAmount = sweepAmount * (PRECISION + mintFactor) / PRECISION; + _borrow(mintAmount); uint256 usdxMinIn = OvnMath.subBasisPoints(usdxAmount, slippage); diff --git a/contracts/Mocks/SweepMock.sol b/contracts/Mocks/SweepMock.sol index 82ac53d..e5f21fc 100644 --- a/contracts/Mocks/SweepMock.sol +++ b/contracts/Mocks/SweepMock.sol @@ -8,6 +8,7 @@ pragma solidity 0.8.19; import "../Sweep/BaseSweep.sol"; import "../Stabilizer/IStabilizer.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; +import "../AMM/IAMM.sol"; contract SweepMock is BaseSweep { using Math for uint256; @@ -106,6 +107,7 @@ contract SweepMock is BaseSweep { * @return uint256 Sweep price */ function ammPrice() public view returns (uint256) { + if(amm != address(0)) return IAMM(amm).getPrice(); return currentAmmPrice; } diff --git a/test/assets/balancer_market_maker.js b/test/assets/balancer_market_maker.js index 955929b..916a1f1 100644 --- a/test/assets/balancer_market_maker.js +++ b/test/assets/balancer_market_maker.js @@ -1,7 +1,7 @@ const { expect } = require("chai"); const { ethers } = require("hardhat"); const { tokens, wallets, chainlink, balancer } = require('../../utils/constants'); -const { Const, impersonate, toBN, sendEth } = require("../../utils/helper_functions"); +const { Const, impersonate, toBN, sendEth, getAddressAndProviders } = require("../../utils/helper_functions"); let poolAddress; contract('Balancer Market Maker', async () => { @@ -44,20 +44,6 @@ contract('Balancer Market Maker', async () => { await sweep.connect(user).setAMM(amm.address); }); - const getAddressAndProviders = (sweep, token) => { - data = {}; - - if (token.toString().toLowerCase() < sweep.toString().toLowerCase()) { - data.tokens = [token, sweep]; - data.providers = ['0x0000000000000000000000000000000000000000', amm.address]; - } else { - data.tokens = [sweep, token]; - data.providers = [amm.address, '0x0000000000000000000000000000000000000000']; - } - - return data; - } - it('create the pool', async () => { data = getAddressAndProviders(sweep.address, USDC_ADDRESS); diff --git a/test/assets/skipped/aave.js b/test/assets/skipped/aave.js index f5b2384..10bd548 100644 --- a/test/assets/skipped/aave.js +++ b/test/assets/skipped/aave.js @@ -3,7 +3,8 @@ const { expect } = require("chai"); const { addresses } = require("../../../utils/address"); const { impersonate, toBN, Const, sendEth, increaseTime, unpauseAave } = require("../../../utils/helper_functions"); -contract.skip('Aave V3 Asset', async () => { +contract('Aave V3 Asset', async () => { + return; before(async () => { [admin, liquidator, guest, lzEndpoint] = await ethers.getSigners(); // Variables diff --git a/test/assets/skipped/compound.js b/test/assets/skipped/compound.js index a90959b..bb4d993 100644 --- a/test/assets/skipped/compound.js +++ b/test/assets/skipped/compound.js @@ -3,7 +3,8 @@ const { expect } = require("chai"); const { addresses } = require("../../../utils/address"); const { impersonate, increaseTime, Const, sendEth, toBN } = require("../../../utils/helper_functions"); -contract.skip('Compound V3 Asset', async () => { +contract('Compound V3 Asset', async () => { + return; before(async () => { [borrower, guest, lzEndpoint] = await ethers.getSigners(); diff --git a/test/assets/skipped/ets.js b/test/assets/skipped/ets.js index 6823ab0..f9c70d2 100644 --- a/test/assets/skipped/ets.js +++ b/test/assets/skipped/ets.js @@ -3,7 +3,8 @@ const { ethers } = require("hardhat"); const { addresses, chainId } = require("../../../utils/address"); const { impersonate, sendEth, resetNetwork, Const, toBN } = require("../../../utils/helper_functions"); -contract.skip("ETS Asset", async function () { +contract("ETS Asset", async function () { + return; if (Number(chainId) !== 42161) return; before(async () => { diff --git a/test/assets/skipped/gDai.js b/test/assets/skipped/gDai.js index ef3f4c9..acc41c7 100644 --- a/test/assets/skipped/gDai.js +++ b/test/assets/skipped/gDai.js @@ -3,7 +3,8 @@ const { ethers } = require("hardhat"); const { addresses, chainId } = require("../../../utils/address"); const { impersonate, sendEth, increaseTime, Const, toBN, resetNetwork } = require("../../../utils/helper_functions"); -contract.skip("gDAI Asset", async function () { +contract("gDAI Asset", async function () { + return; if (Number(chainId) !== 1) return; before(async () => { diff --git a/test/assets/skipped/glp.js b/test/assets/skipped/glp.js index af4ce2a..7906788 100644 --- a/test/assets/skipped/glp.js +++ b/test/assets/skipped/glp.js @@ -3,7 +3,8 @@ const { expect } = require("chai"); const { addresses, chainId } = require("../../../utils/address"); const { impersonate, sendEth, Const } = require("../../../utils/helper_functions") -contract.skip('GLP Asset', async () => { +contract('GLP Asset', async () => { + return; // GLP Asset only work on the Arbitrum. if (Number(chainId) !== 42161) return; diff --git a/test/assets/skipped/off_chain.js b/test/assets/skipped/off_chain.js index ceaa081..c53fcba 100644 --- a/test/assets/skipped/off_chain.js +++ b/test/assets/skipped/off_chain.js @@ -3,7 +3,8 @@ const { ethers } = require("hardhat"); const { tokens, chainlink, wallets } = require("../../../utils/constants"); const { impersonate, Const, toBN, sendEth, getBlockTimestamp } = require("../../../utils/helper_functions"); -contract.skip("Off-Chain Asset", async function (accounts) { +contract("Off-Chain Asset", async function (accounts) { + return; before(async () => { BORROWER = accounts[0]; GUEST = accounts[1]; diff --git a/test/assets/skipped/off_chain_settings.js b/test/assets/skipped/off_chain_settings.js index a6598ee..bcd28a2 100644 --- a/test/assets/skipped/off_chain_settings.js +++ b/test/assets/skipped/off_chain_settings.js @@ -3,7 +3,8 @@ const { ethers } = require("hardhat"); const { tokens, chainlink } = require("../../../utils/constants"); const { Const, toBN, getBlockTimestamp } = require("../../../utils/helper_functions"); -contract.skip("Off-Chain Asset - Settings", async function () { +contract("Off-Chain Asset - Settings", async function () { + return; before(async () => { [owner, borrower, wallet, treasury, multisig, lzEndpoint] = await ethers.getSigners(); amount = toBN("10", 18); diff --git a/test/assets/uniswap_market_maker.js b/test/assets/uniswap_market_maker.js index 695d522..da902c8 100644 --- a/test/assets/uniswap_market_maker.js +++ b/test/assets/uniswap_market_maker.js @@ -43,8 +43,6 @@ contract('Uniswap Market Maker', async () => { BORROWER ); - await marketmaker.setMintFactor(1e6); - await sweep.addMinter(BORROWER, sweepAmount.mul(5)); await sweep.addMinter(marketmaker.address, sweepAmount); @@ -147,14 +145,17 @@ contract('Uniswap Market Maker', async () => { usdcPoolBalance = await usdc.balanceOf(poolAddress); sweepPoolBalance = await sweep.balanceOf(poolAddress); + await marketmaker.setMintFactor(1e6); + await marketmaker.setSlippage(5e5); + buyAmount = toBN("5000", 6); - sweepToget = toBN("4999", 18); + sweepToGet = toBN("4900", 18); await usdc.transfer(borrower.address, buyAmount) await usdc.connect(borrower).approve(marketmaker.address, buyAmount); await marketmaker.connect(borrower).buySweep(buyAmount); - - expect(await sweep.balanceOf(borrower.address)).to.be.greaterThan(sweepToget); + + expect(await sweep.balanceOf(borrower.address)).to.be.greaterThan(sweepToGet); expect(await usdc.balanceOf(poolAddress)).to.greaterThan(usdcPoolBalance); expect(await sweep.balanceOf(poolAddress)).to.greaterThan(sweepPoolBalance); }); @@ -201,6 +202,8 @@ contract('Uniswap Market Maker', async () => { await expect(marketmaker.buySweepOnAMM(amount, 2000)) .to.be.revertedWith('Too little received') + expect(await marketmaker.getBuyPrice()).to.lessThan(await sweep.ammPrice()); + mmUBB = await usdc.balanceOf(marketmaker.address); mmSBB = await sweep.balanceOf(marketmaker.address); pUBB = await usdc.balanceOf(poolAddress); @@ -208,10 +211,10 @@ contract('Uniswap Market Maker', async () => { await(marketmaker.buySweepOnAMM(amount, 3e5)); - expect(await usdc.balanceOf(poolAddress)).to.equal(pUBB.add(amount)); - expect(await sweep.balanceOf(poolAddress)).to.lessThan(sUBB); expect(await usdc.balanceOf(marketmaker.address)).to.equal(mmUBB.sub(amount)); expect(await sweep.balanceOf(marketmaker.address)).to.greaterThan(mmSBB); + expect(await usdc.balanceOf(poolAddress)).to.greaterThan(pUBB); + expect(await sweep.balanceOf(poolAddress)).to.lessThan(sUBB); }) }) }); diff --git a/test/periphery/uniswap_amm.js b/test/periphery/uniswap_amm.js index 50fc9b4..7ab2837 100644 --- a/test/periphery/uniswap_amm.js +++ b/test/periphery/uniswap_amm.js @@ -1,7 +1,7 @@ const { expect } = require("chai"); const { ethers } = require("hardhat"); const { chainlink, uniswap } = require("../../utils/constants"); -const { toBN, Const, increaseTime, getPriceAndData } = require("../../utils/helper_functions"); +const { toBN, Const, getPriceAndData } = require("../../utils/helper_functions"); contract("Uniswap AMM", async function () { before(async () => { @@ -123,6 +123,8 @@ contract("Uniswap AMM", async function () { priceBefore = await amm.getPrice(); sweepBalanceB = await sweep.balanceOf(pool_address); usdcBalanceB = await usdc.balanceOf(pool_address); + await marketmaker.setMintFactor(1e6); + await marketmaker.setSlippage(3e5); expect(await marketmaker.getBuyPrice()).to.greaterThan(priceBefore); @@ -133,7 +135,7 @@ contract("Uniswap AMM", async function () { priceAfter = await amm.getPrice(); - expect(await amm.getPrice()).to.greaterThan(priceBefore); + expect(priceAfter).to.greaterThan(priceBefore); expect(await marketmaker.getBuyPrice()).to.lessThan(priceAfter); expect(await sweep.balanceOf(pool_address)).to.lessThan(sweepBalanceB); expect(await usdc.balanceOf(pool_address)).to.equal(usdcBalanceB.add(USDC_AMOUNT)); diff --git a/test/stabilizer/liquidation.js b/test/stabilizer/liquidation.js index f5e6c63..93f32a2 100644 --- a/test/stabilizer/liquidation.js +++ b/test/stabilizer/liquidation.js @@ -152,7 +152,7 @@ contract("Stabilizer - Liquidation", async function () { await comp_asset.connect(borrower).invest(INVEST_AMOUNT); await amm.setPrice(Const.WETH_AMM); - await weth_asset.connect(borrower).invest(INVEST_AMOUNT, Const.SLIPPAGE); + await weth_asset.connect(borrower).invest(INVEST_AMOUNT, 5000); await Promise.all( assets.map(async (asset) => { diff --git a/test/stabilizer/one_step.js b/test/stabilizer/one_step.js index b5b82a2..b7c7d69 100644 --- a/test/stabilizer/one_step.js +++ b/test/stabilizer/one_step.js @@ -1,102 +1,159 @@ const { expect } = require("chai"); const { ethers } = require("hardhat"); -const { chainlink, uniswap, tokens, wallets } = require("../../utils/constants"); -const { impersonate, sendEth, Const, toBN } = require("../../utils/helper_functions"); +const { chainlink, uniswap, tokens, wallets, balancer } = require("../../utils/constants"); +const { impersonate, sendEth, Const, toBN, getAddressAndProviders } = require("../../utils/helper_functions"); let user; -contract.only("Stabilizer - One step invest/divest", async function () { - before(async () => { - [owner, other, treasury, lzEndpoint] = await ethers.getSigners(); - - BORROWER = owner.address; - depositAmount = 1000e6; - withdrawAmount = 1000e6; - maxSweep = toBN("500000", 18); - sweepAmount = toBN("5000", 18); - maxWeth = toBN("5000", 18); - - await sendEth(Const.WETH_HOLDER); - // ------------- Deployment of contracts ------------- - Sweep = await ethers.getContractFactory("SweepMock"); - const Proxy = await upgrades.deployProxy(Sweep, [lzEndpoint.address, owner.address, 2500]); - sweep = await Proxy.deployed(); - await sweep.setTreasury(treasury.address); - - Token = await ethers.getContractFactory("ERC20"); - usdc = await Token.attach(tokens.usdc); - weth = await Token.attach(tokens.weth); - - Oracle = await ethers.getContractFactory("AggregatorMock"); - wethOracle = await Oracle.deploy(); - - Uniswap = await ethers.getContractFactory("UniswapMock"); - amm = await Uniswap.deploy(sweep.address, owner.address); - await sweep.setAMM(amm.address); - - WETHAsset = await ethers.getContractFactory("ERC20Asset"); - weth_asset = await WETHAsset.deploy( - 'WETH Asset', - sweep.address, - tokens.usdc, - tokens.weth, - chainlink.usdc_usd, - wethOracle.address, - BORROWER, - uniswap.pool_weth - ); - - await sendEth(wallets.usdc_holder); - user = await impersonate(wallets.usdc_holder); - await usdc.connect(user).transfer(weth_asset.address, depositAmount); - await usdc.connect(user).transfer(amm.address, depositAmount * 5); - - await sweep.addMinter(owner.address, maxSweep); - await sweep.mint(maxSweep); - await sweep.transfer(amm.address, sweepAmount); - - user = await impersonate(Const.WETH_HOLDER); - await weth.connect(user).transfer(amm.address, maxWeth); - - await sweep.addMinter(weth_asset.address, maxSweep); - await weth_asset.configure( - Const.RATIO, 500, maxSweep, Const.ZERO, Const.ZERO, Const.DAYS_5, - Const.RATIO, maxSweep, Const.TRUE, Const.FALSE, Const.URL - ); +contract("Stabilizer - One step invest/divest", async function () { + before(async () => { + [owner, other, treasury, lzEndpoint] = await ethers.getSigners(); + + BORROWER = owner.address; + depositAmount = 100e6; + withdrawAmount = 500e6; + maxSweep = toBN("500000", 18); + sweepAmount = toBN("5000", 18); + maxWeth = toBN("5000", 18); + + await sendEth(Const.WETH_HOLDER); + // ------------- Deployment of contracts ------------- + factory = await ethers.getContractAt("IComposableStablePoolFactory", balancer.factory); + Sweep = await ethers.getContractFactory("SweepMock"); + const Proxy = await upgrades.deployProxy(Sweep, [lzEndpoint.address, owner.address, 2500]); + sweep = await Proxy.deployed(); + await sweep.setTreasury(treasury.address); + + Token = await ethers.getContractFactory("ERC20"); + usdc = await Token.attach(tokens.usdc); + weth = await Token.attach(tokens.weth); + + Oracle = await ethers.getContractFactory("AggregatorMock"); + usdcOracle = await Oracle.deploy(); + + AMM = await ethers.getContractFactory("BalancerAMM"); + amm = await AMM.deploy( + sweep.address, + usdc.address, + chainlink.sequencer, + usdcOracle.address, + 86400 + ) + + WETHAsset = await ethers.getContractFactory("ERC20Asset"); + weth_asset = await WETHAsset.deploy( + 'WETH Asset', + sweep.address, + tokens.usdc, + tokens.weth, + usdcOracle.address, + chainlink.weth_usd, + BORROWER, + uniswap.pool_weth + ); + + await weth_asset.configure( + Const.RATIO, 500, maxSweep, Const.ZERO, Const.ZERO, Const.DAYS_5, + Const.RATIO, maxSweep, Const.TRUE, Const.FALSE, Const.URL + ); + }); + + describe("invest and divest functions", async function () { + it("setup", async function () { + // create the pool + data = getAddressAndProviders(sweep.address, usdc.address); + + const pool = await (await factory.create( + "Balancer SWEEP-USDC StablePool", + "SWEEP-USDC-BPT", + data.tokens, + 500, // amplification + data.providers, //rateProviders + [0, 0], // tokenRateCacheDurations + true, // exemptFromYieldProtocolFeeFlag + 1e14, // swapFeePercentage, 1e12 = 0.0001% + '0xba1ba1ba1ba1ba1ba1ba1ba1ba1ba1ba1ba1ba1b', // balancer governance + '0x42616c616e6365722053574545502d5553444320537461626c65506f6f6c2031' // salt + )).wait(); + + poolAddress = pool.logs[0].address; + balancerPool = await ethers.getContractAt("IBalancerPool", poolAddress); + vaultAddress = await balancerPool.getVault(); + + MarketMaker = await ethers.getContractFactory("BalancerMarketMaker"); + marketmaker = await MarketMaker.deploy( + 'Balancer Market Maker', + sweep.address, + usdc.address, + usdcOracle.address, + poolAddress, + owner.address + ); + + await marketmaker.configure(0, 0, maxSweep, 0, 0, 0, 0, 0, false, false, Const.URL) + + await sweep.addMinter(marketmaker.address, maxSweep); + await sweep.addMinter(weth_asset.address, maxSweep); + await sweep.setAMM(amm.address); + + usdcAmount = 5500e6; + sweepAmount = toBN("5000", 18); + + // deposit + await sendEth(wallets.usdc_holder); + user = await impersonate(wallets.usdc_holder); + await usdc.connect(user).transfer(weth_asset.address, depositAmount); + await usdc.connect(user).transfer(owner.address, usdcAmount); + + await usdc.approve(marketmaker.address, usdcAmount); + await marketmaker.initPool(usdcAmount, sweepAmount); + + await amm.setPool(poolAddress); + await amm.setMarketMaker(marketmaker.address); + + // mintFactor and slippage + await marketmaker.setMintFactor(1e6); + }) + + it("invest correctly", async function () { + expect(await weth_asset.assetValue()).to.equal(Const.ZERO); + expect(await usdc.balanceOf(weth_asset.address)).to.greaterThan(Const.ZERO); + expect(await weth.balanceOf(weth_asset.address)).to.equal(Const.ZERO); + + borrowAmount = toBN("800", 18); + await weth_asset.oneStepInvest(borrowAmount, 30000, true); + balanceBefore = await weth.balanceOf(weth_asset.address); + + expect(balanceBefore).to.greaterThan(Const.ZERO); + expect(await weth_asset.assetValue()).to.greaterThan(Const.ZERO); + + await weth_asset.invest(depositAmount, 30000); + + expect(await usdc.balanceOf(weth_asset.address)).to.equal(Const.ZERO); + expect(await weth.balanceOf(weth_asset.address)).to.greaterThan(balanceBefore); }); - describe("invest and divest functions", async function () { - it("invest correctly", async function () { - expect(await weth_asset.assetValue()).to.equal(Const.ZERO); - expect(await usdc.balanceOf(weth_asset.address)).to.greaterThan(Const.ZERO); - expect(await weth.balanceOf(weth_asset.address)).to.equal(Const.ZERO); + it("divest correctly", async function () { + assetValue = await weth_asset.assetValue(); + currentValue = await weth_asset.currentValue(); + borrowed = await weth_asset.sweepBorrowed() + expect(assetValue).to.equal(currentValue); - borrowAmount = toBN("1000", 18); - await weth_asset.oneStepInvest(borrowAmount, 30000, true); - balanceBefore = await weth.balanceOf(weth_asset.address); + expect(await usdc.balanceOf(weth_asset.address)).to.equal(0) + expect(await sweep.balanceOf(weth_asset.address)).to.equal(0) + expect(await weth.balanceOf(weth_asset.address)).to.greaterThan(0) - expect(balanceBefore).to.greaterThan(Const.ZERO); - expect(await weth_asset.assetValue()).to.greaterThan(Const.ZERO); + await weth_asset.oneStepDivest(withdrawAmount, 5000, true); - await weth_asset.invest(depositAmount, 30000); + expect(await weth_asset.sweepBorrowed()).to.lessThan(borrowed) - expect(await usdc.balanceOf(weth_asset.address)).to.equal(Const.ZERO); - expect(await weth.balanceOf(weth_asset.address)).to.greaterThan(balanceBefore); - }); + assetValue = await weth_asset.assetValue(); + balance = await usdc.balanceOf(weth_asset.address); - it("divest correctly", async function () { - assetValue = await weth_asset.assetValue(); - currentValue = await weth_asset.currentValue(); - expect(assetValue).to.equal(currentValue); + await weth_asset.divest(withdrawAmount, 5000); - await weth_asset.oneStepDivest(withdrawAmount, 5000, true); - - assetValue = await weth_asset.assetValue(); - balance = await usdc.balanceOf(weth_asset.address); - - await weth_asset.divest(withdrawAmount, 5000); - - expect(await usdc.balanceOf(weth_asset.address)).to.greaterThan(balance); - expect(await weth_asset.assetValue()).to.below(assetValue); - }); + expect(await usdc.balanceOf(weth_asset.address)).to.greaterThan(balance); + expect(await weth.balanceOf(weth_asset.address)).to.equal(0) + expect(await weth_asset.assetValue()).to.below(assetValue); }); + }); }); diff --git a/test/token/sweepr_oft.js b/test/token/sweepr_oft.js index ce10409..9593ce6 100644 --- a/test/token/sweepr_oft.js +++ b/test/token/sweepr_oft.js @@ -166,14 +166,14 @@ contract("Sweepr - OFT", async function () { it("add destination chain", async function () { expect(await OFTSrc.chainCount()).to.be.equal(Const.ZERO) - await OFTSrc.addChain(chainIdDst, sweepDst.address); + await OFTSrc.addChain(chainIdDst, OFTDst.address); expect(await OFTSrc.chainCount()).to.be.equal(1); chain = await OFTSrc.chains(chainIdDst); - expect(chain).to.equal(sweepDst.address); + expect(chain).to.equal(OFTDst.address); sweepAddress = await OFTSrc.getBalancerWithChainId(chainIdDst); - expect(sweepAddress).to.equal(sweepDst.address); + expect(sweepAddress).to.equal(OFTDst.address); }) it("remove destination chain", async function () { diff --git a/utils/helper_functions.js b/utils/helper_functions.js index 6fb9a1f..3cf0116 100644 --- a/utils/helper_functions.js +++ b/utils/helper_functions.js @@ -121,8 +121,8 @@ const Const = { PRICE: 1e6, WBTC_PRICE: 28e11, WBTC_AMM: 28e9, - WETH_PRICE: 19e10, - WETH_AMM: 19e8, + WETH_PRICE: 23e10, + WETH_AMM: 23e8, USDC_PRICE: 99993053, BASIS_DENOMINATOR: 1e6, SLIPPAGE: 2000, @@ -153,6 +153,20 @@ function ask(query) { })); } +const getAddressAndProviders = (sweep, token) => { + data = {}; + + if (token.toString().toLowerCase() < sweep.toString().toLowerCase()) { + data.tokens = [token, sweep]; + data.providers = ['0x0000000000000000000000000000000000000000', amm.address]; + } else { + data.tokens = [sweep, token]; + data.providers = [amm.address, '0x0000000000000000000000000000000000000000']; + } + + return data; +} + module.exports = { toBN, Const, @@ -165,5 +179,6 @@ module.exports = { getTokenAmounts, unpauseAave, sleep, - ask + ask, + getAddressAndProviders } From 91243c04cf8df8147de4c544a1ea59b3d77995b8 Mon Sep 17 00:00:00 2001 From: Cela Pablo Date: Wed, 13 Dec 2023 13:18:01 -0300 Subject: [PATCH 4/4] adds tests to Balancer MarketMaker mintFactor --- contracts/Balancer/BalancerMarketMaker.sol | 1 - test/periphery/balancer_MM_mint_factor.js | 157 +++++++++++++++++++++ test/stabilizer/auction.js | 6 +- 3 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 test/periphery/balancer_MM_mint_factor.js diff --git a/contracts/Balancer/BalancerMarketMaker.sol b/contracts/Balancer/BalancerMarketMaker.sol index b1de380..465aea0 100644 --- a/contracts/Balancer/BalancerMarketMaker.sol +++ b/contracts/Balancer/BalancerMarketMaker.sol @@ -35,7 +35,6 @@ contract BalancerMarketMaker is Stabilizer { uint8 public bptIndex; uint256 public mintFactor; - uint32 public slippage; uint24 private constant PRECISION = 1e6; diff --git a/test/periphery/balancer_MM_mint_factor.js b/test/periphery/balancer_MM_mint_factor.js new file mode 100644 index 0000000..bc620cf --- /dev/null +++ b/test/periphery/balancer_MM_mint_factor.js @@ -0,0 +1,157 @@ +const { expect } = require("chai"); +const { ethers } = require("hardhat"); +const { chainlink, tokens, wallets, balancer } = require("../../utils/constants"); +const { impersonate, sendEth, Const, toBN, getAddressAndProviders } = require("../../utils/helper_functions"); +let user; + +contract("Balancer Market Maker - mint factor", async function () { + before(async () => { + [owner, other, treasury, lzEndpoint] = await ethers.getSigners(); + + BORROWER = owner.address; + depositAmount = 100e6; + withdrawAmount = 500e6; + maxSweep = toBN("500000", 18); + sweepAmount = toBN("5000", 18); + maxWeth = toBN("5000", 18); + // ------------- Deployment of contracts ------------- + factory = await ethers.getContractAt("IComposableStablePoolFactory", balancer.factory); + Sweep = await ethers.getContractFactory("SweepMock"); + const Proxy = await upgrades.deployProxy(Sweep, [lzEndpoint.address, owner.address, 2500]); + sweep = await Proxy.deployed(); + await sweep.setTreasury(treasury.address); + + Token = await ethers.getContractFactory("ERC20"); + usdc = await Token.attach(tokens.usdc); + + Oracle = await ethers.getContractFactory("AggregatorMock"); + usdcOracle = await Oracle.deploy(); + + AMM = await ethers.getContractFactory("BalancerAMM"); + amm = await AMM.deploy( + sweep.address, + usdc.address, + chainlink.sequencer, + usdcOracle.address, + 86400 + ) + }); + + describe("main functions", async function () { + it("setup", async function () { + // create the pool + data = getAddressAndProviders(sweep.address, usdc.address); + + const pool = await (await factory.create( + "Balancer SWEEP-USDC StablePool", + "SWEEP-USDC-BPT", + data.tokens, + 500, // amplification + data.providers, //rateProviders + [0, 0], // tokenRateCacheDurations + true, // exemptFromYieldProtocolFeeFlag + 1e14, // swapFeePercentage, 1e12 = 0.0001% + '0xba1ba1ba1ba1ba1ba1ba1ba1ba1ba1ba1ba1ba1b', // balancer governance + '0x42616c616e6365722053574545502d5553444320537461626c65506f6f6c2031' // salt + )).wait(); + + poolAddress = pool.logs[0].address; + balancerPool = await ethers.getContractAt("IBalancerPool", poolAddress); + vaultAddress = await balancerPool.getVault(); + + MarketMaker = await ethers.getContractFactory("BalancerMarketMaker"); + marketmaker = await MarketMaker.deploy( + 'Balancer Market Maker', + sweep.address, + usdc.address, + usdcOracle.address, + poolAddress, + owner.address + ); + + await marketmaker.configure(0, 0, maxSweep, 0, 0, 0, 0, 0, false, false, Const.URL) + + await sweep.addMinter(marketmaker.address, maxSweep); + await sweep.setAMM(amm.address); + + usdcAmount = 5500e6; + sweepAmount = toBN("5000", 18); + + // deposit + await sendEth(wallets.usdc_holder); + user = await impersonate(wallets.usdc_holder); + await usdc.connect(user).transfer(owner.address, usdcAmount); + await usdc.connect(user).transfer(other.address, usdcAmount); + + await usdc.approve(marketmaker.address, usdcAmount); + await marketmaker.initPool(usdcAmount, sweepAmount); + + await amm.setPool(poolAddress); + await amm.setMarketMaker(marketmaker.address); + await marketmaker.setMintFactor(1e6); + }) + + it("buySweep on AMM and MM", async function () { + sweepPrice = await sweep.ammPrice(); + buyPrice = await marketmaker.getBuyPrice(); + expect(buyPrice).to.greaterThan(sweepPrice); + + sweepBorrowed = await marketmaker.sweepBorrowed(); + vBalanceUSDC = await usdc.balanceOf(vaultAddress); + vBalanceSWEEP = await sweep.balanceOf(vaultAddress); + uBalanceUSDC = await usdc.balanceOf(other.address); + uBalanceSWEEP = await sweep.balanceOf(other.address); + + amountIn = 1000e6; + minOut = toBN("990", 18); + await usdc.connect(other).approve(amm.address, amountIn); + // swaps on Balancer Pool + await amm.connect(other).buySweep(usdc.address, amountIn, minOut); + + sweepPrice = await sweep.ammPrice(); + buyPrice = await marketmaker.getBuyPrice(); + expect(buyPrice).to.lessThan(sweepPrice); + expect(await marketmaker.sweepBorrowed()).to.equal(sweepBorrowed); + expect(await usdc.balanceOf(vaultAddress)).to.greaterThan(vBalanceUSDC); + expect(await sweep.balanceOf(vaultAddress)).to.lessThan(vBalanceSWEEP); + expect(await usdc.balanceOf(other.address)).to.equal(uBalanceUSDC.sub(amountIn)); + expect(await sweep.balanceOf(other.address)).to.greaterThan(uBalanceSWEEP); + + // sets new mintFactor + await marketmaker.setMintFactor(1e5) // 10% ~ 0.5% slippage + sweepBorrowed = await marketmaker.sweepBorrowed(); + vBalanceUSDC = await usdc.balanceOf(vaultAddress); + vBalanceSWEEP = await sweep.balanceOf(vaultAddress); + uBalanceUSDC = await usdc.balanceOf(other.address); + uBalanceSWEEP = await sweep.balanceOf(other.address); + + minOut = toBN("900", 18); + await usdc.connect(other).approve(amm.address, amountIn); + await amm.connect(other).buySweep(usdc.address, amountIn, minOut); + + expect(await marketmaker.sweepBorrowed()).to.greaterThan(sweepBorrowed); + expect(await usdc.balanceOf(vaultAddress)).to.equal(vBalanceUSDC.add(amountIn)); + expect(await sweep.balanceOf(vaultAddress)).to.greaterThan(vBalanceSWEEP); + expect(await usdc.balanceOf(other.address)).to.equal(uBalanceUSDC.sub(amountIn)); + expect(await sweep.balanceOf(other.address)).to.greaterThan(uBalanceSWEEP); + + // sets new mintFactor + await marketmaker.setMintFactor(1e4) // 1% ~ 0.5% slippage + sweepBorrowed = await marketmaker.sweepBorrowed(); + vBalanceUSDC = await usdc.balanceOf(vaultAddress); + vBalanceSWEEP = await sweep.balanceOf(vaultAddress); + uBalanceUSDC = await usdc.balanceOf(other.address); + uBalanceSWEEP = await sweep.balanceOf(other.address); + + minOut = toBN("900", 18); + await usdc.connect(other).approve(amm.address, amountIn); + await amm.connect(other).buySweep(usdc.address, amountIn, minOut); + + expect(await marketmaker.sweepBorrowed()).to.greaterThan(sweepBorrowed); + expect(await usdc.balanceOf(vaultAddress)).to.equal(vBalanceUSDC.add(amountIn)); + expect(await sweep.balanceOf(vaultAddress)).to.greaterThan(vBalanceSWEEP); + expect(await usdc.balanceOf(other.address)).to.equal(uBalanceUSDC.sub(amountIn)); + expect(await sweep.balanceOf(other.address)).to.greaterThan(uBalanceSWEEP); + }); + }); +}); diff --git a/test/stabilizer/auction.js b/test/stabilizer/auction.js index 4f3e010..02fa19c 100644 --- a/test/stabilizer/auction.js +++ b/test/stabilizer/auction.js @@ -37,6 +37,8 @@ contract('Stabilizer - Auction', async () => { positionManager = await ethers.getContractAt("INonfungiblePositionManager", uniswap.positions_manager); LiquidityHelper = await ethers.getContractFactory("LiquidityHelper"); liquidityHelper = await LiquidityHelper.deploy(); + Oracle = await ethers.getContractFactory("AggregatorMock"); + usdcOracle = await Oracle.deploy(); WETHAsset = await ethers.getContractFactory("ERC20Asset"); asset = await WETHAsset.deploy( @@ -44,7 +46,7 @@ contract('Stabilizer - Auction', async () => { sweep.address, tokens.usdc, tokens.weth, - chainlink.usdc_usd, + usdcOracle.address, chainlink.weth_usd, owner.address, uniswap.pool_weth @@ -67,7 +69,7 @@ contract('Stabilizer - Auction', async () => { usdx.address, chainlink.sequencer, pool_address, - chainlink.usdc_usd, + usdcOracle.address, 86400, liquidityHelper.address );