From aafac5aaef36fe93ba098a4c9b0c09db76ded16a Mon Sep 17 00:00:00 2001 From: MerlinEgalite Date: Fri, 11 Nov 2022 12:51:36 +0100 Subject: [PATCH 01/11] =?UTF-8?q?=F0=9F=94=A7=20Set=20correct=20block=20nu?= =?UTF-8?q?mber?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4c12a39fb..3c8e47680 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ else ifeq (${NETWORK}, eth-mainnet) FOUNDRY_CHAIN_ID=1 - FOUNDRY_FORK_BLOCK_NUMBER?=14292587 + FOUNDRY_FORK_BLOCK_NUMBER?=15581371 # Block number when the Aave's V2 IRM was updated for the stETH. endif ifeq (${NETWORK}, eth-ropsten) From 366dc0a11657e02179d365eff309874b0df01388 Mon Sep 17 00:00:00 2001 From: MerlinEgalite Date: Fri, 11 Nov 2022 13:01:53 +0100 Subject: [PATCH 02/11] =?UTF-8?q?=E2=9A=B0=EF=B8=8F=20Remove=20outdated=20?= =?UTF-8?q?fuzzing=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fuzzing/aave-v2/TestBorrowFuzzing.t.sol | 136 ------ .../aave-v2/TestInterestRateFuzzing.t.sol | 92 ---- .../aave-v2/TestLiquidateFuzzing.t.sol | 53 --- .../fuzzing/aave-v2/TestRepayFuzzing.t.sol | 83 ---- .../fuzzing/aave-v2/TestSupplyFuzzing.t.sol | 191 -------- .../fuzzing/aave-v2/TestWithdrawFuzzing.t.sol | 150 ------- .../aave-v2/setup/TestSetupFuzzing.sol | 417 ------------------ .../fuzzing/compound/TestBorrowFuzzing.t.sol | 179 -------- .../compound/TestInterestRateFuzzing.t.sol | 108 ----- .../compound/TestLiquidateFuzzing.t.sol | 230 ---------- .../fuzzing/compound/TestRepayFuzzing.t.sol | 215 --------- .../fuzzing/compound/TestSupplyFuzzing.t.sol | 198 --------- .../compound/TestWithdrawFuzzing.t.sol | 341 -------------- .../compound/setup/TestSetupFuzzing.sol | 413 ----------------- 14 files changed, 2806 deletions(-) delete mode 100644 test-foundry/fuzzing/aave-v2/TestBorrowFuzzing.t.sol delete mode 100644 test-foundry/fuzzing/aave-v2/TestInterestRateFuzzing.t.sol delete mode 100644 test-foundry/fuzzing/aave-v2/TestLiquidateFuzzing.t.sol delete mode 100644 test-foundry/fuzzing/aave-v2/TestRepayFuzzing.t.sol delete mode 100644 test-foundry/fuzzing/aave-v2/TestSupplyFuzzing.t.sol delete mode 100644 test-foundry/fuzzing/aave-v2/TestWithdrawFuzzing.t.sol delete mode 100644 test-foundry/fuzzing/aave-v2/setup/TestSetupFuzzing.sol delete mode 100644 test-foundry/fuzzing/compound/TestBorrowFuzzing.t.sol delete mode 100644 test-foundry/fuzzing/compound/TestInterestRateFuzzing.t.sol delete mode 100644 test-foundry/fuzzing/compound/TestLiquidateFuzzing.t.sol delete mode 100644 test-foundry/fuzzing/compound/TestRepayFuzzing.t.sol delete mode 100644 test-foundry/fuzzing/compound/TestSupplyFuzzing.t.sol delete mode 100644 test-foundry/fuzzing/compound/TestWithdrawFuzzing.t.sol delete mode 100644 test-foundry/fuzzing/compound/setup/TestSetupFuzzing.sol diff --git a/test-foundry/fuzzing/aave-v2/TestBorrowFuzzing.t.sol b/test-foundry/fuzzing/aave-v2/TestBorrowFuzzing.t.sol deleted file mode 100644 index ed25fd6a7..000000000 --- a/test-foundry/fuzzing/aave-v2/TestBorrowFuzzing.t.sol +++ /dev/null @@ -1,136 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "./setup/TestSetupFuzzing.sol"; - -contract TestBorrowFuzzing is TestSetupFuzzing { - function testBorrow1( - uint128 _supplied, - uint128 _borrowed, - uint8 _suppliedAsset, - uint8 _borrowedAsset - ) public { - (address suppliedAsset, address suppliedUnderlying) = getSupplyAsset(_suppliedAsset); - (address borrowedAsset, ) = getAsset(_borrowedAsset); - - uint256 supplied = _supplied; - uint256 borrowed = _borrowed; - - supplied = getSupplyAmount(suppliedUnderlying, supplied); - - borrower1.approve(suppliedUnderlying, supplied); - borrower1.supply(suppliedAsset, supplied); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - borrowedAsset - ); - - hevm.assume(borrowed > borrowable + 1); // +1 to cover for rounding error - - hevm.expectRevert(EntryPositionsManager.UnauthorisedBorrow.selector); - borrower1.borrow(borrowedAsset, borrowed); - } - - function testBorrow2( - uint128 _amountSupplied, - uint8 _suppliedAsset, - uint8 _borrowedAsset, - uint8 _random1 - ) public { - hevm.assume(_random1 != 0); - (address suppliedAsset, address suppliedUnderlying) = getSupplyAsset(_suppliedAsset); - (address borrowedAsset, ) = getAsset(_borrowedAsset); - - uint256 amountSupplied = _amountSupplied; - - amountSupplied = getSupplyAmount(suppliedUnderlying, amountSupplied); - - borrower1.approve(suppliedUnderlying, amountSupplied); - borrower1.supply(suppliedAsset, amountSupplied); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - borrowedAsset - ); - - uint256 borrowedAmount = (borrowable * _random1) / 255; - hevm.assume(borrowedAmount + 5 < borrowable); // +5 to cover for rounding error - - assumeBorrowAmountIsCorrect(borrowedAsset, borrowedAmount); - borrower1.borrow(borrowedAsset, borrowedAmount); - } - - function testBorrow3( - uint128 _amountSupplied, - uint128 _amountCollateral, - uint8 _matchedAsset, - uint8 _collateralAsset, - uint8 _random1 - ) public { - hevm.assume(_random1 != 0); - (address matchedAsset, address matchedUnderlying) = getSupplyAsset(_matchedAsset); - (address collateralAsset, address collateralUnderlying) = getAsset(_collateralAsset); - - uint256 amountSupplied = _amountSupplied; - uint256 amountCollateral = _amountCollateral; - - amountCollateral = getSupplyAmount(collateralUnderlying, _amountCollateral); - amountSupplied = getSupplyAmount(matchedUnderlying, amountSupplied); - - supplier1.approve(matchedUnderlying, amountSupplied); - supplier1.supply(matchedAsset, amountSupplied); - - borrower1.approve(collateralUnderlying, amountCollateral); - borrower1.supply(collateralAsset, amountCollateral); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - matchedAsset - ); - - uint256 borrowedAmount = (borrowable * _random1) / 255; - hevm.assume(borrowedAmount + 5 < borrowable); // +5 to cover for rounding error - - assumeBorrowAmountIsCorrect(matchedAsset, borrowedAmount); - borrower1.borrow(matchedAsset, borrowedAmount); - } - - // There is no difference between Borrow3 & 4 because amount proportion aren't pre-determined. - - function testBorrowMultipleAssets( - uint128 _amountCollateral, - uint8 _firstAsset, - uint8 _secondAsset, - uint8 _collateralAsset, - uint8 _random1, - uint8 _random2 - ) public { - hevm.assume(_random1 != 0); - hevm.assume(_random2 != 0); - - (address collateralAsset, address collateralUnderlying) = getSupplyAsset(_collateralAsset); - (address firstAsset, ) = getAsset(_firstAsset); - (address secondAsset, ) = getAsset(_secondAsset); - - uint256 amountCollateral = _amountCollateral; - - amountCollateral = getSupplyAmount(collateralUnderlying, amountCollateral); - - borrower1.approve(collateralUnderlying, amountCollateral); - borrower1.supply(collateralAsset, amountCollateral); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset(address(borrower1), firstAsset); - uint256 borrowedAmount = (borrowable * _random1) / 255; - hevm.assume(borrowedAmount + 5 < borrowable); // +5 to cover for rounding error - - assumeBorrowAmountIsCorrect(firstAsset, borrowedAmount); - borrower1.borrow(firstAsset, borrowedAmount); - - (, borrowable) = lens.getUserMaxCapacitiesForAsset(address(borrower1), secondAsset); - borrowedAmount = (borrowable * _random2) / 255; - hevm.assume(borrowedAmount + 5 < borrowable); // +5 to cover for rounding error - assumeBorrowAmountIsCorrect(secondAsset, borrowedAmount); - borrower1.borrow(secondAsset, borrowedAmount); - } -} diff --git a/test-foundry/fuzzing/aave-v2/TestInterestRateFuzzing.t.sol b/test-foundry/fuzzing/aave-v2/TestInterestRateFuzzing.t.sol deleted file mode 100644 index 4644eacd0..000000000 --- a/test-foundry/fuzzing/aave-v2/TestInterestRateFuzzing.t.sol +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "@contracts/aave-v2/InterestRatesManager.sol"; -import "@forge-std/Test.sol"; - -contract TestInterestRateFuzzing is InterestRatesManager, Test { - Vm public hevm = Vm(HEVM_ADDRESS); - - uint256 public constant RAY = 1e27; - - uint256 public p2pSupplyIndexTest = 1 * RAY; - uint256 public p2pBorrowIndexTest = 1 * RAY; - uint256 public poolSupplyIndexTest = 2 * RAY; - uint256 public poolBorrowIndexTest = 3 * RAY; - uint256 public lastPoolSupplyIndexTest = 1 * RAY; - uint256 public lastPoolBorrowIndexTest = 1 * RAY; - uint256 public reserveFactor0PerCentTest = 0; - uint256 public reserveFactor50PerCentTest = 5_000; - uint256 public p2pIndexCursorTest = 3_333; - - // prettier-ignore - function computeP2PIndexes(InterestRatesManager.Params memory _params) - public - pure - returns (uint256 p2pSupplyIndex_, uint256 p2pBorrowIndex_) - { - uint256 poolSupplyGrowthFactor = ((_params.poolSupplyIndex * RAY) / _params.lastPoolSupplyIndex); - uint256 poolBorrowGrowthFactor = ((_params.poolBorrowIndex * RAY) / _params.lastPoolBorrowIndex); - uint256 p2pIncrease = ((MAX_BASIS_POINTS - _params.p2pIndexCursor) * poolSupplyGrowthFactor + _params.p2pIndexCursor * poolBorrowGrowthFactor) / MAX_BASIS_POINTS; - uint256 shareOfTheSupplyDelta = _params.delta.p2pBorrowAmount > 0 - ? (((_params.delta.p2pSupplyDelta * _params.lastPoolSupplyIndex) / RAY) * RAY) / - ((_params.delta.p2pSupplyAmount * _params.lastP2PSupplyIndex) / RAY) - : 0; - uint256 shareOfTheBorrowDelta = _params.delta.p2pSupplyAmount > 0 - ? (((_params.delta.p2pBorrowDelta * _params.lastPoolBorrowIndex) / RAY) * RAY) / - ((_params.delta.p2pBorrowAmount * _params.lastP2PBorrowIndex) / RAY) - : 0; - p2pSupplyIndex_ = - _params.lastP2PSupplyIndex * - ((RAY - shareOfTheSupplyDelta) * (p2pIncrease - (_params.reserveFactor * (p2pIncrease - poolSupplyGrowthFactor) / MAX_BASIS_POINTS)) / RAY + - (shareOfTheSupplyDelta * poolSupplyGrowthFactor) / RAY) / - RAY; - p2pBorrowIndex_ = - _params.lastP2PBorrowIndex * - ((RAY - shareOfTheBorrowDelta) * (p2pIncrease + (_params.reserveFactor * (poolBorrowGrowthFactor - p2pIncrease) / MAX_BASIS_POINTS)) / RAY + - (shareOfTheBorrowDelta * poolBorrowGrowthFactor) / RAY) / - RAY; - } - - // prettier-ignore - function testFuzzInterestRates( - uint64 _1, - uint64 _2, - uint64 _3, - uint64 _4, - uint64 _5, - uint64 _6, - uint16 _7, - uint16 _8, - uint64 _9, - uint64 _10, - uint64 _11, - uint64 _12 - ) public { - uint256 _p2pSupplyIndex = RAY + _1; - uint256 _p2pBorrowIndex = RAY + _2; - uint256 _poolSupplyIndex = RAY + _3; - uint256 _poolBorrowIndex = RAY + _4; - uint256 _lastPoolSupplyIndex = RAY + _5; - uint256 _lastPoolBorrowIndex = RAY + _6; - uint256 _reserveFactor = _7 % 10_000; - uint256 _p2pIndexCursor = _8 % 10_000; - uint256 _p2pSupplyDelta = RAY + _9; - uint256 _p2pBorrowDelta = RAY + _10; - uint256 _p2pSupplyAmount = RAY + _11; - uint256 _p2pBorrowAmount = RAY + _12; - - hevm.assume(_lastPoolSupplyIndex <= _poolSupplyIndex); - hevm.assume(_lastPoolBorrowIndex <= _poolBorrowIndex); - hevm.assume(_poolBorrowIndex * RAY / _lastPoolBorrowIndex > _poolSupplyIndex * RAY / _lastPoolSupplyIndex); - hevm.assume(_p2pSupplyAmount * _p2pSupplyIndex / RAY > _p2pSupplyDelta * _poolSupplyIndex / RAY); - hevm.assume(_p2pBorrowAmount * _p2pBorrowIndex / RAY > _p2pBorrowDelta * _poolBorrowIndex / RAY); - - InterestRatesManager.Params memory params = InterestRatesManager.Params(_p2pSupplyIndex, _p2pBorrowIndex, _poolSupplyIndex, _poolBorrowIndex, _lastPoolSupplyIndex, _lastPoolBorrowIndex, _reserveFactor, _p2pIndexCursor, Types.Delta(_p2pSupplyDelta, _p2pBorrowDelta, _p2pSupplyAmount, _p2pBorrowAmount)); - - (uint256 newP2PSupplyIndex, uint256 newP2PBorrowIndex) = _computeP2PIndexes(params); - (uint256 expectednewP2PSupplyIndex, uint256 expectednewP2PBorrowIndex) = computeP2PIndexes(params); - assertApproxEqAbs(newP2PSupplyIndex, expectednewP2PSupplyIndex, 400); - assertApproxEqAbs(newP2PBorrowIndex, expectednewP2PBorrowIndex, 400); - } -} diff --git a/test-foundry/fuzzing/aave-v2/TestLiquidateFuzzing.t.sol b/test-foundry/fuzzing/aave-v2/TestLiquidateFuzzing.t.sol deleted file mode 100644 index 27d3274ff..000000000 --- a/test-foundry/fuzzing/aave-v2/TestLiquidateFuzzing.t.sol +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "./setup/TestSetupFuzzing.sol"; - -contract TestLiquidateFuzzing is TestSetupFuzzing { - struct addressVars { - address collateralAsset; - address collateralUnderlying; - address suppliedAsset; - address suppliedUnderlying; - address borrowedAsset; - address borrowedUnderlying; - } - - // Should not be able to liquidate a user with enough collateral. - function testLiquidate1Fuzzed( - uint128 _amountSupplied, - uint8 _suppliedAsset, - uint8 _borrowedAsset, - uint8 _firstModulo, - uint8 _secondModulo - ) public { - (address suppliedAsset, address suppliedUnderlying) = getSupplyAsset(_suppliedAsset); - (address borrowedAsset, address borrowedUnderlying) = getAsset(_borrowedAsset); - - uint256 amountSupplied = getSupplyAmount(suppliedUnderlying, _amountSupplied); - hevm.assume(_firstModulo != 0); - hevm.assume(_secondModulo != 0); - - borrower1.approve(suppliedUnderlying, amountSupplied); - borrower1.supply(suppliedAsset, amountSupplied); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - borrowedAsset - ); - uint256 borrowedAmount = (borrowable * _firstModulo) / 255; - - assumeBorrowAmountIsCorrect(borrowedAsset, borrowedAmount); - borrower1.borrow(borrowedAsset, borrowedAmount); - - // Liquidate - uint256 toRepay = ((borrowedAmount / 2) * _secondModulo) / 255; - assumeLiquidateAmountIsCorrect(toRepay); - - User liquidator = borrower3; - liquidator.approve(borrowedUnderlying, address(morpho), toRepay); - - hevm.expectRevert(abi.encodeWithSignature("UnauthorisedLiquidate()")); - liquidator.liquidate(borrowedAsset, suppliedAsset, address(borrower1), toRepay); - } -} diff --git a/test-foundry/fuzzing/aave-v2/TestRepayFuzzing.t.sol b/test-foundry/fuzzing/aave-v2/TestRepayFuzzing.t.sol deleted file mode 100644 index 1d0543d0e..000000000 --- a/test-foundry/fuzzing/aave-v2/TestRepayFuzzing.t.sol +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "./setup/TestSetupFuzzing.sol"; - -contract TestRepayFuzzing is TestSetupFuzzing { - // Simple repay on pool. - function testRepay1Fuzzed( - uint128 _supplied, - uint8 _suppliedAsset, - uint8 _borrowedAsset, - uint8 _random1, - uint8 _random2 - ) public { - hevm.assume(_random1 > 10); - hevm.assume(_random2 > 10); - - (address suppliedAsset, address suppliedUnderlying) = getSupplyAsset(_suppliedAsset); - (address borrowedAsset, address borrowedUnderlying) = getAsset(_borrowedAsset); - - uint256 supplied = getSupplyAmount(suppliedUnderlying, _supplied); - borrower1.approve(suppliedUnderlying, supplied); - borrower1.supply(suppliedAsset, supplied); - - uint256 borrowable = getBorrowAmount(borrowedAsset, 95); - uint256 borrowedAmount = (borrowable * _random1) / 255; - assumeBorrowAmountIsCorrect(borrowedAsset, borrowedAmount); - borrower1.borrow(borrowedAsset, borrowedAmount); - - uint256 repaidAmount = (borrowedAmount * _random2) / 255; - assumeRepayAmountIsCorrect(borrowedUnderlying, repaidAmount); - borrower1.approve(borrowedUnderlying, repaidAmount); - borrower1.repay(borrowedAsset, repaidAmount); - } - - // Matched, with random number of borrower await on pool to replace. - function testRepay3Fuzzed( - uint128 _suppliedAmount, - uint8 _suppliedAsset, - uint8 _borrowedAsset, - uint8 _random1, - uint8 _random2, - uint8 _random3 - ) public { - hevm.assume(_random1 > 10); - hevm.assume(_random2 > 10); - hevm.assume(_random3 > 10); - - (address suppliedAsset, address suppliedUnderlying) = getSupplyAsset(_suppliedAsset); - (address borrowedAsset, address borrowedUnderlying) = getAsset(_borrowedAsset); - - uint256 suppliedAmount = getSupplyAmount(suppliedUnderlying, _suppliedAmount); - borrower1.approve(suppliedUnderlying, suppliedAmount); - borrower1.supply(suppliedAsset, suppliedAmount); - - // Borrower1 borrows borrowedAmount. - uint256 borrowable = getBorrowAmount(borrowedAsset, 95); - uint256 borrowedAmount = (borrowable * _random1) / 255; - assumeBorrowAmountIsCorrect(borrowedAsset, borrowedAmount); - borrower1.borrow(borrowedAsset, borrowedAmount); - - // He is matched with supplier1. - supplier1.approve(borrowedUnderlying, borrowedAmount); - supplier1.supply(borrowedAsset, borrowedAmount); - - // There is a random number of waiting borrower on pool. - uint256 nbOfWaitingBorrowers = ((20 * uint256(_random2)) / 255) + 1; - createSigners(nbOfWaitingBorrowers); - uint256 amountPerBorrower = borrowedAmount / nbOfWaitingBorrowers; - assumeBorrowAmountIsCorrect(borrowedAsset, amountPerBorrower); - for (uint256 i = 2; i < nbOfWaitingBorrowers; i++) { - borrowers[i].approve(suppliedUnderlying, suppliedAmount); - borrowers[i].supply(suppliedAsset, suppliedAmount); - borrowers[i].borrow(borrowedAsset, amountPerBorrower); - } - - // Borrower1 repays a random amount. - uint256 repaidAmount = (borrowedAmount * _random3) / 255; - assumeRepayAmountIsCorrect(borrowedUnderlying, repaidAmount); - borrower1.approve(borrowedUnderlying, repaidAmount); - borrower1.repay(borrowedAsset, repaidAmount); - } -} diff --git a/test-foundry/fuzzing/aave-v2/TestSupplyFuzzing.t.sol b/test-foundry/fuzzing/aave-v2/TestSupplyFuzzing.t.sol deleted file mode 100644 index 7a0b5c051..000000000 --- a/test-foundry/fuzzing/aave-v2/TestSupplyFuzzing.t.sol +++ /dev/null @@ -1,191 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "./setup/TestSetupFuzzing.sol"; - -contract TestSupplyFuzzing is TestSetupFuzzing { - struct AssetVars { - address suppliedAToken; - address suppliedUnderlying; - address borrowedAToken; - address borrowedUnderlying; - address collateralAToken; - address collateralUnderlying; - } - - function testSupply1Fuzzed(uint128 _amount, uint8 _asset) public { - (address asset, address underlying) = getSupplyAsset(_asset); - uint256 amount = _amount; - - assumeSupplyAmountIsCorrect(underlying, amount); - supplier1.approve(underlying, amount); - supplier1.supply(asset, amount); - - uint256 normalizedIncome = lendingPool.getReserveNormalizedIncome(underlying); - uint256 expectedOnPool = amount.rayDiv(normalizedIncome); - - testEquality(ERC20(asset).balanceOf(address(morpho)), amount, "balance of aToken"); - - (uint256 inP2P, uint256 onPool) = morpho.supplyBalanceInOf(asset, address(supplier1)); - - testEquality(onPool, expectedOnPool, "on pool"); - assertEq(inP2P, 0, "in P2P"); - } - - function testSupply2Fuzzed( - uint128 _suppliedAmount, - uint8 _randomModulo, - uint8 _suppliedAToken, - uint8 _borrowedAToken - ) public { - hevm.assume(_randomModulo > 0); - AssetVars memory vars; - - (vars.suppliedAToken, vars.suppliedUnderlying) = getSupplyAsset(_suppliedAToken); - (vars.borrowedAToken, vars.borrowedUnderlying) = getAsset(_borrowedAToken); - - uint256 suppliedAmount = _suppliedAmount; - - assumeSupplyAmountIsCorrect(vars.suppliedUnderlying, 2 * suppliedAmount); - // Because there are two supply with suppliedAmount - - borrower1.approve(vars.suppliedUnderlying, suppliedAmount); - borrower1.supply(vars.suppliedAToken, suppliedAmount); - - uint256 borrowable = getBorrowAmount(vars.borrowedAToken, 95); - uint256 borrowedAmount = (borrowable * _randomModulo) / 255; - assumeBorrowAmountIsCorrect(vars.borrowedAToken, borrowedAmount); - borrower1.borrow(vars.borrowedAToken, borrowedAmount); - - borrower1.approve(vars.suppliedUnderlying, suppliedAmount); - borrower1.supply(vars.suppliedAToken, suppliedAmount); - } - - // what is fuzzed is the proportion in P2P on the supply of the second user - function testSupply3Fuzzed( - uint128 _suppliedAmount, - uint8 _collateralAsset, - uint8 _supplyAsset, - uint8 _random1 - ) public { - AssetVars memory vars; - (vars.suppliedAToken, vars.suppliedUnderlying) = getSupplyAsset(_supplyAsset); - (vars.collateralAToken, vars.collateralUnderlying) = getAsset(_collateralAsset); - - assumeSupplyAmountIsCorrect(vars.suppliedUnderlying, _suppliedAmount); - - uint256 collateralAmountToSupply = ERC20(vars.collateralUnderlying).balanceOf( - address(borrower1) - ); - - borrower1.approve(vars.collateralUnderlying, collateralAmountToSupply); - borrower1.supply(vars.collateralAToken, collateralAmountToSupply); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - vars.suppliedAToken - ); - uint256 borrowedAmount = (borrowable * _random1) / 255; - assumeBorrowAmountIsCorrect(vars.suppliedAToken, borrowedAmount); - - borrower1.borrow(vars.suppliedAToken, borrowedAmount); - - supplier1.approve(vars.suppliedUnderlying, _suppliedAmount); - supplier1.supply(vars.suppliedAToken, _suppliedAmount); - } - - // what is fuzzed is the amount supplied - function testSupply4Fuzzed( - uint128 _suppliedAmount, - uint8 _collateralAsset, - uint8 _supplyAsset, - uint8 _random1 - ) public { - AssetVars memory vars; - (vars.suppliedAToken, vars.suppliedUnderlying) = getSupplyAsset(_supplyAsset); - (vars.collateralAToken, vars.collateralUnderlying) = getAsset(_collateralAsset); - uint256 NMAX = ((20 * uint256(_random1)) / 255) + 1; - uint256 amountPerBorrower = _suppliedAmount / NMAX; - - assumeSupplyAmountIsCorrect(vars.suppliedUnderlying, _suppliedAmount); - assumeBorrowAmountIsCorrect(vars.suppliedAToken, NMAX * amountPerBorrower); - - setDefaultMaxGasForMatchingHelper( - type(uint64).max, - type(uint64).max, - type(uint64).max, - type(uint64).max - ); - createSigners(NMAX); - - uint256 collateralAmount = ERC20(vars.collateralUnderlying).balanceOf(address(borrower1)); - borrower1.approve(vars.collateralUnderlying, collateralAmount); - borrower1.supply(vars.collateralAToken, collateralAmount); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - vars.suppliedAToken - ); - - hevm.assume(amountPerBorrower < borrowable); - borrower1.borrow(vars.suppliedAToken, amountPerBorrower); - for (uint256 i = 1; i < NMAX - 1; i++) { - borrowers[i + 1].approve(vars.collateralUnderlying, collateralAmount); - borrowers[i + 1].supply(vars.collateralAToken, collateralAmount); - borrowers[i + 1].borrow(vars.suppliedAToken, amountPerBorrower); - } - - supplier1.approve(vars.suppliedUnderlying, _suppliedAmount); - supplier1.supply(vars.suppliedAToken, _suppliedAmount); - } - - // what is fuzzed is the amount supplied - function testSupply5Fuzzed( - uint128 _suppliedAmount, - uint8 _collateralAsset, - uint8 _supplyAsset, - uint8 _random1 - ) public { - AssetVars memory vars; - (vars.suppliedAToken, vars.suppliedUnderlying) = getSupplyAsset(_supplyAsset); - (vars.collateralAToken, vars.collateralUnderlying) = getAsset(_collateralAsset); - uint256 NMAX = ((20 * uint256(_random1)) / 255) + 1; - uint256 amountPerBorrower = _suppliedAmount / (2 * NMAX); - - assumeSupplyAmountIsCorrect(vars.suppliedUnderlying, _suppliedAmount); - assumeBorrowAmountIsCorrect(vars.suppliedAToken, NMAX * amountPerBorrower); - - setDefaultMaxGasForMatchingHelper( - type(uint64).max, - type(uint64).max, - type(uint64).max, - type(uint64).max - ); - - uint256 collateralAmount = ERC20(vars.collateralUnderlying).balanceOf(address(borrower1)); - - { - borrower1.approve(vars.collateralUnderlying, collateralAmount); - borrower1.supply(vars.collateralAToken, collateralAmount); - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - vars.suppliedAToken - ); - hevm.assume(borrowable >= amountPerBorrower); - borrower1.borrow(vars.suppliedAToken, amountPerBorrower); - } - createSigners(NMAX); - - for (uint256 i = 0; i < NMAX - 1; i++) { - borrowers[i + 1].approve(vars.collateralUnderlying, collateralAmount); - borrowers[i + 1].supply(vars.collateralAToken, collateralAmount); - borrowers[i + 1].borrow(vars.suppliedAToken, amountPerBorrower); - } - - { - uint256 actuallySupplied = (_suppliedAmount / NMAX) * NMAX; - supplier1.approve(vars.suppliedUnderlying, actuallySupplied); - supplier1.supply(vars.suppliedAToken, actuallySupplied); - } - } -} diff --git a/test-foundry/fuzzing/aave-v2/TestWithdrawFuzzing.t.sol b/test-foundry/fuzzing/aave-v2/TestWithdrawFuzzing.t.sol deleted file mode 100644 index af63d6b09..000000000 --- a/test-foundry/fuzzing/aave-v2/TestWithdrawFuzzing.t.sol +++ /dev/null @@ -1,150 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "./setup/TestSetupFuzzing.sol"; -import {Attacker} from "../../compound/helpers/Attacker.sol"; - -contract TestWithdrawFuzzing is TestSetupFuzzing { - function testWithdraw1Fuzzed( - uint128 _suppliedAmount, - uint8 _borrowedAsset, - uint8 _suppliedAsset - ) public { - (address suppliedAsset, address suppliedUnderlying) = getSupplyAsset(_suppliedAsset); - (address borrowedAsset, ) = getAsset(_borrowedAsset); - - uint256 suppliedAmount = _suppliedAmount; - assumeSupplyAmountIsCorrect(suppliedUnderlying, suppliedAmount); - hevm.assume(suppliedAmount > 10**ERC20(suppliedUnderlying).decimals()); - - borrower1.approve(suppliedUnderlying, suppliedAmount); - borrower1.supply(suppliedAsset, suppliedAmount); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - borrowedAsset - ); - borrowable = (borrowable * 95) / 100; - assumeBorrowAmountIsCorrect(borrowedAsset, borrowable); - borrower1.borrow(borrowedAsset, borrowable); - - assumeWithdrawAmountIsCorrect(suppliedAsset, suppliedAmount); - hevm.expectRevert(abi.encodeWithSignature("UnauthorisedWithdraw()")); - borrower1.withdraw(suppliedAsset, suppliedAmount); - } - - function testWithdraw2Fuzzed( - uint128 _suppliedAmount, - uint8 _suppliedAsset, - uint8 _random1 - ) public { - hevm.assume(_random1 != 0); - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - - uint256 suppliedAmount = _suppliedAmount; - assumeSupplyAmountIsCorrect(suppliedUnderlying, suppliedAmount); - hevm.assume(suppliedAmount > 10**ERC20(suppliedUnderlying).decimals()); - - supplier1.approve(suppliedUnderlying, suppliedAmount); - supplier1.supply(suppliedAsset, suppliedAmount); - - uint256 withdrawnAmount = (suppliedAmount * _random1) / 255; - assumeWithdrawAmountIsCorrect(suppliedAsset, withdrawnAmount); - supplier1.withdraw(suppliedAsset, withdrawnAmount); - } - - function testWithdrawAllFuzzed(uint128 _suppliedAmount, uint8 _suppliedAsset) public { - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - - uint256 suppliedAmount = _suppliedAmount; - assumeSupplyAmountIsCorrect(suppliedUnderlying, suppliedAmount); - hevm.assume(suppliedAmount > 10**ERC20(suppliedUnderlying).decimals()); - - supplier1.approve(suppliedUnderlying, suppliedAmount); - supplier1.supply(suppliedAsset, suppliedAmount); - supplier1.withdraw(suppliedAsset, type(uint256).max); - } - - function testWithdraw3_1Fuzzed( - uint128 _amountSupplied, - uint8 _collateralAsset, - uint8 _suppliedAsset, - uint8 _random1 - ) public { - hevm.assume(_random1 != 0); - - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - (address collateralAsset, address collateralUnderlying) = getAsset(_collateralAsset); - - uint256 amountSupplied = _amountSupplied; - - assumeSupplyAmountIsCorrect(suppliedUnderlying, amountSupplied); - hevm.assume(amountSupplied > 10**ERC20(suppliedUnderlying).decimals()); - - // Borrower1 & supplier1 are matched for amountSupplied. - uint256 collateralToSupply = ERC20(collateralUnderlying).balanceOf(address(borrower1)); - - borrower1.approve(collateralUnderlying, collateralToSupply); - borrower1.supply(collateralAsset, collateralToSupply); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - suppliedAsset - ); - hevm.assume(borrowable > amountSupplied); - assumeBorrowAmountIsCorrect(suppliedAsset, amountSupplied); - borrower1.borrow(suppliedAsset, amountSupplied); - - supplier1.approve(suppliedUnderlying, amountSupplied); - supplier1.supply(suppliedAsset, amountSupplied); - - // Supplier1 withdraws a random amount. - uint256 withdrawnAmount = (amountSupplied * _random1) / 255; - assumeWithdrawAmountIsCorrect(suppliedAsset, withdrawnAmount); - supplier1.withdraw(suppliedAsset, withdrawnAmount); - } - - function testWithdrawMultipleAssetsFuzzed( - uint8 _proportionBorrowed, - uint8 _suppliedAsset1, - uint8 _suppliedAsset2, - uint128 _amount1, - uint128 _amount2 - ) public { - (address asset1, address underlying1) = getAsset(_suppliedAsset1); - (address asset2, address underlying2) = getAsset(_suppliedAsset2); - - hevm.assume(_amount1 >= 1e14 && _amount1 < ERC20(underlying1).balanceOf(address(asset1))); - hevm.assume(_amount2 >= 1e14 && _amount2 < ERC20(underlying2).balanceOf(address(asset2))); - hevm.assume(_proportionBorrowed > 0); - - supplier1.approve(underlying1, _amount1); - supplier1.supply(asset1, _amount1); - supplier1.approve(underlying2, _amount2); - supplier1.supply(asset2, _amount2); - - borrower1.approve(dai, type(uint256).max); - borrower1.supply(aDai, 10_000_000 * 1e18); - - (, uint256 borrowable1) = lens.getUserMaxCapacitiesForAsset(address(borrower1), asset1); - (, uint256 borrowable2) = lens.getUserMaxCapacitiesForAsset(address(borrower1), asset2); - - // Amounts available in the cTokens - uint256 compBalance1 = ERC20(underlying1).balanceOf(asset1); - uint256 compBalance2 = ERC20(underlying2).balanceOf(asset2); - - borrowable1 = borrowable1 > compBalance1 ? compBalance1 : borrowable1; - borrowable2 = borrowable2 > compBalance2 ? compBalance2 : borrowable2; - - uint256 toBorrow1 = (_amount1 * _proportionBorrowed) / type(uint8).max; - toBorrow1 = toBorrow1 > borrowable1 / 2 ? borrowable1 / 2 : toBorrow1; - uint256 toBorrow2 = (_amount2 * _proportionBorrowed) / type(uint8).max; - toBorrow2 = toBorrow2 > borrowable2 / 2 ? borrowable2 / 2 : toBorrow2; - - borrower1.borrow(asset1, toBorrow1); - borrower1.borrow(asset2, toBorrow2); - - supplier1.withdraw(asset1, _amount1); - supplier1.withdraw(asset2, _amount2); - } -} diff --git a/test-foundry/fuzzing/aave-v2/setup/TestSetupFuzzing.sol b/test-foundry/fuzzing/aave-v2/setup/TestSetupFuzzing.sol deleted file mode 100644 index 9106ca83f..000000000 --- a/test-foundry/fuzzing/aave-v2/setup/TestSetupFuzzing.sol +++ /dev/null @@ -1,417 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "@contracts/aave-v2/interfaces/aave/IAaveIncentivesController.sol"; -import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; -import "@contracts/aave-v2/interfaces/aave/IPriceOracleGetter.sol"; -import "@contracts/aave-v2/interfaces/aave/IVariableDebtToken.sol"; -import "@contracts/aave-v2/interfaces/IInterestRatesManager.sol"; -import "@contracts/aave-v2/interfaces/aave/ILendingPool.sol"; -import "@contracts/aave-v2/interfaces/IRewardsManager.sol"; -import "@contracts/aave-v2/interfaces/aave/IAToken.sol"; -import "@contracts/aave-v2/interfaces/IMorpho.sol"; - -import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; - -import "@rari-capital/solmate/src/utils/SafeTransferLib.sol"; -import "@morpho-dao/morpho-utils/math/WadRayMath.sol"; -import "@openzeppelin/contracts/utils/Strings.sol"; -import "@contracts/aave-v2/libraries/Types.sol"; - -import {RewardsManagerOnMainnetAndAvalanche} from "@contracts/aave-v2/rewards-managers/RewardsManagerOnMainnetAndAvalanche.sol"; -import {RewardsManagerOnPolygon} from "@contracts/aave-v2/rewards-managers/RewardsManagerOnPolygon.sol"; -import {InterestRatesManager} from "@contracts/aave-v2/InterestRatesManager.sol"; -import {IncentivesVault} from "@contracts/aave-v2/IncentivesVault.sol"; -import {MatchingEngine} from "@contracts/aave-v2/MatchingEngine.sol"; -import {EntryPositionsManager} from "@contracts/aave-v2/EntryPositionsManager.sol"; -import {ExitPositionsManager} from "@contracts/aave-v2/ExitPositionsManager.sol"; -import {Lens} from "@contracts/aave-v2/lens/Lens.sol"; -import "@contracts/aave-v2/Morpho.sol"; - -import "../../../common/helpers/MorphoToken.sol"; -import "../../../aave-v2/helpers/SimplePriceOracle.sol"; -import {DumbOracle} from "../../../aave-v2/helpers/DumbOracle.sol"; -import "../../../common/helpers/Chains.sol"; -import {User} from "../../../aave-v2/helpers/User.sol"; -import {Utils} from "../../../aave-v2/setup/Utils.sol"; -import "@forge-std/stdlib.sol"; -import "@forge-std/console.sol"; -import "@config/Config.sol"; - -contract TestSetupFuzzing is Config, Utils, stdCheats { - Vm public hevm = Vm(HEVM_ADDRESS); - - uint256 public constant MAX_BASIS_POINTS = 10_000; - uint256 public constant INITIAL_BALANCE = 15_000_000_000; - - ProxyAdmin public proxyAdmin; - TransparentUpgradeableProxy public morphoProxy; - Morpho public morphoImplV1; - Morpho public morpho; - IInterestRatesManager public interestRatesManager; - TransparentUpgradeableProxy internal rewardsManagerProxy; - IRewardsManager internal rewardsManagerImplV1; - IRewardsManager public rewardsManager; - IEntryPositionsManager public entryManager; - IExitPositionsManager public exitManager; - Lens public lens; - MorphoToken public morphoToken; - address public REWARD_TOKEN = - IAaveIncentivesController(aaveIncentivesControllerAddress).REWARD_TOKEN(); - - IncentivesVault public incentivesVault; - DumbOracle internal dumbOracle; - ILendingPoolAddressesProvider public lendingPoolAddressesProvider; - IPriceOracleGetter public oracle; - ILendingPool public lendingPool; - - User public supplier1; - User public supplier2; - User public supplier3; - User[] public suppliers; - User public borrower1; - User public borrower2; - User public borrower3; - User[] public borrowers; - User public treasuryVault; - - address[] public pools; - - function setUp() public { - initContracts(); - setContractsLabels(); - initUsers(); - } - - function initContracts() internal { - Types.MaxGasForMatching memory defaultMaxGasForMatching = Types.MaxGasForMatching({ - supply: 3e6, - borrow: 3e6, - withdraw: 3e6, - repay: 3e6 - }); - - lendingPoolAddressesProvider = ILendingPoolAddressesProvider(poolAddressesProviderAddress); - lendingPool = ILendingPool(lendingPoolAddressesProvider.getLendingPool()); - entryManager = new EntryPositionsManager(); - exitManager = new ExitPositionsManager(); - - /// Deploy proxies /// - - proxyAdmin = new ProxyAdmin(); - interestRatesManager = new InterestRatesManager(); - - morphoImplV1 = new Morpho(); - morphoProxy = new TransparentUpgradeableProxy(address(morphoImplV1), address(this), ""); - - morphoProxy.changeAdmin(address(proxyAdmin)); - morpho = Morpho(payable(address(morphoProxy))); - morpho.initialize( - entryManager, - exitManager, - interestRatesManager, - ILendingPoolAddressesProvider(poolAddressesProviderAddress), - defaultMaxGasForMatching, - 20 - ); - - // make sure the wEth contract has enough ETH to unwrap any amount - hevm.deal(wEth, type(uint128).max); - - lens = new Lens(address(morpho), lendingPoolAddressesProvider); - treasuryVault = new User(morpho); - morpho.setTreasuryVault(address(treasuryVault)); - - if (block.chainid == Chains.ETH_MAINNET || block.chainid == Chains.AVALANCHE_MAINNET) { - rewardsManagerImplV1 = new RewardsManagerOnMainnetAndAvalanche(); - } else if (block.chainid == Chains.POLYGON_MAINNET) { - rewardsManagerImplV1 = new RewardsManagerOnPolygon(); - } - - rewardsManagerProxy = new TransparentUpgradeableProxy( - address(rewardsManagerImplV1), - address(proxyAdmin), - "" - ); - rewardsManager = IRewardsManager(address(rewardsManagerProxy)); - rewardsManager.initialize(address(morpho)); - rewardsManager.setAaveIncentivesController(aaveIncentivesControllerAddress); - morpho.setAaveIncentivesController(aaveIncentivesControllerAddress); - - /// Create markets /// - - createMarket(aDai); - createMarket(aUsdc); - createMarket(aUsdt); - createMarket(aWbtc); - createMarket(aWeth); - - hevm.warp(block.timestamp + 100); - - /// Create Morpho token, deploy Incentives Vault and activate rewards /// - - morphoToken = new MorphoToken(address(this)); - dumbOracle = new DumbOracle(); - incentivesVault = new IncentivesVault( - IMorpho(address(morpho)), - morphoToken, - ERC20(IAaveIncentivesController(aaveIncentivesControllerAddress).REWARD_TOKEN()), - address(1), - dumbOracle - ); - morphoToken.transfer(address(incentivesVault), 1_000_000 ether); - - oracle = IPriceOracleGetter(lendingPoolAddressesProvider.getPriceOracle()); - - morpho.setRewardsManager(rewardsManager); - morpho.setIncentivesVault(incentivesVault); - } - - function createMarket(address _aToken) internal { - address underlying = IAToken(_aToken).UNDERLYING_ASSET_ADDRESS(); - Types.Market memory market = Types.Market(0, 3_333); - morpho.createMarket(underlying, market); - - // All tokens must also be added to the pools array, for the correct behavior of TestLiquidate::createAndSetCustomPriceOracle. - pools.push(_aToken); - - hevm.label(_aToken, ERC20(_aToken).symbol()); - hevm.label(underlying, ERC20(underlying).symbol()); - } - - function initUsers() internal { - for (uint256 i = 0; i < 3; i++) { - suppliers.push(new User(morpho)); - hevm.label( - address(suppliers[i]), - string(abi.encodePacked("Supplier", Strings.toString(i + 1))) - ); - fillUserBalances(suppliers[i]); - } - supplier1 = suppliers[0]; - supplier2 = suppliers[1]; - supplier3 = suppliers[2]; - - for (uint256 i = 0; i < 3; i++) { - borrowers.push(new User(morpho)); - hevm.label( - address(borrowers[i]), - string(abi.encodePacked("Borrower", Strings.toString(i + 1))) - ); - fillUserBalances(borrowers[i]); - } - - borrower1 = borrowers[0]; - borrower2 = borrowers[1]; - borrower3 = borrowers[2]; - } - - function fillUserBalances(User _user) internal { - for (uint256 i; i < pools.length; i++) { - address token = getUnderlying(pools[i]); - if (token == wEth) { - deal(token, address(_user), uint256(5856057446759574251267521) / 2); - } else { - deal(token, address(_user), ERC20(token).totalSupply() / 2); - } - } - } - - function setContractsLabels() internal { - hevm.label(address(morpho), "Morpho"); - hevm.label(address(rewardsManager), "RewardsManager"); - hevm.label(address(morphoToken), "MorphoToken"); - hevm.label(aaveIncentivesControllerAddress, "AaveIncentivesController"); - hevm.label(address(lendingPoolAddressesProvider), "LendingPoolAddressesProvider"); - hevm.label(address(lendingPool), "LendingPool"); - hevm.label(address(oracle), "AaveOracle"); - hevm.label(address(treasuryVault), "TreasuryVault"); - hevm.label(address(interestRatesManager), "InterestRatesManager"); - hevm.label(address(incentivesVault), "IncentivesVault"); - } - - function createSigners(uint256 _nbOfSigners) internal { - while (borrowers.length < _nbOfSigners) { - borrowers.push(new User(morpho)); - fillUserBalances(borrowers[borrowers.length - 1]); - suppliers.push(new User(morpho)); - fillUserBalances(suppliers[suppliers.length - 1]); - } - } - - function createAndSetCustomPriceOracle() public returns (SimplePriceOracle) { - SimplePriceOracle customOracle = new SimplePriceOracle(); - - hevm.store( - address(lendingPoolAddressesProvider), - keccak256(abi.encode(bytes32("PRICE_ORACLE"), 2)), - bytes32(uint256(uint160(address(customOracle)))) - ); - - for (uint256 i = 0; i < pools.length; i++) { - address underlying = IAToken(pools[i]).UNDERLYING_ASSET_ADDRESS(); - - customOracle.setDirectPrice(underlying, oracle.getAssetPrice(underlying)); - } - - return customOracle; - } - - function setDefaultMaxGasForMatchingHelper( - uint64 _supply, - uint64 _borrow, - uint64 _withdraw, - uint64 _repay - ) public { - Types.MaxGasForMatching memory newMaxGas = Types.MaxGasForMatching({ - supply: _supply, - borrow: _borrow, - withdraw: _withdraw, - repay: _repay - }); - morpho.setDefaultMaxGasForMatching(newMaxGas); - } - - function move1YearForward(address _marketAddress) public { - for (uint256 k; k < 365; k++) { - hevm.warp(block.timestamp + (1 days)); - morpho.updateIndexes(_marketAddress); - } - } - - /// @notice Computes and returns peer-to-peer rates for a specific market (without taking into account deltas!). - /// @param _poolToken The market address. - /// @return p2pSupplyRate_ The market's supply rate in peer-to-peer (in ray). - /// @return p2pBorrowRate_ The market's borrow rate in peer-to-peer (in ray). - function getApproxP2PRates(address _poolToken) - public - view - returns (uint256 p2pSupplyRate_, uint256 p2pBorrowRate_) - { - DataTypes.ReserveData memory reserveData = lendingPool.getReserveData( - IAToken(_poolToken).UNDERLYING_ASSET_ADDRESS() - ); - - uint256 poolSupplyAPR = reserveData.currentLiquidityRate; - uint256 poolBorrowAPR = reserveData.currentVariableBorrowRate; - (uint16 reserveFactor, uint256 p2pIndexCursor) = morpho.market(_poolToken); - - // rate = (1 - p2pIndexCursor) * poolSupplyRate + p2pIndexCursor * poolBorrowRate. - uint256 rate = ((10_000 - p2pIndexCursor) * - poolSupplyAPR + - p2pIndexCursor * - poolBorrowAPR) / 10_000; - - p2pSupplyRate_ = rate - (reserveFactor * (rate - poolSupplyAPR)) / 10_000; - p2pBorrowRate_ = rate + (reserveFactor * (poolBorrowAPR - rate)) / 10_000; - } - - /// @notice Returns the underlying for a given market. - /// @param _poolToken The address of the market. - function getUnderlying(address _poolToken) internal view returns (address) { - return IAToken(_poolToken).UNDERLYING_ASSET_ADDRESS(); - } - - /// @notice Returns the asset and its underlying for a given market, excluding USDT. - /// @param _asset The fuzzing asset. - function getSupplyAsset(uint8 _asset) - internal - view - returns (address asset, address underlying) - { - asset = pools[_asset % pools.length]; - underlying = getUnderlying(asset); - if (underlying == usdt) { - uint256 index = _asset % pools.length; - index = index == pools.length - 1 ? 0 : index + 1; - asset = pools[index]; - underlying = getUnderlying(asset); - } - } - - function getAsset(uint8 _asset) internal view returns (address asset, address underlying) { - asset = pools[_asset % pools.length]; - underlying = getUnderlying(asset); - } - - /// @notice Checks morpho will not revert. - /// @param _underlying Address of the underlying to supply. - /// @param _amount To check. - function getSupplyAmount(address _underlying, uint256 _amount) internal view returns (uint256) { - uint256 min = 10**ERC20(_underlying).decimals(); - - return bound(_amount, min, ERC20(_underlying).balanceOf(address(supplier1))); - } - - /// @notice Checks morpho will not revert. - /// @param _underlying Address of the underlying to borrow. - /// @param _pcent Address of the underlying to borrow. - function getBorrowAmount(address _underlying, uint256 _pcent) internal view returns (uint256) { - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset(address(borrower1), _underlying); - - return (borrowable * _pcent) / 100; - } - - function bound( - uint256 x, - uint256 min, - uint256 max - ) internal pure returns (uint256 result) { - require(max >= min, "MAX_LESS_THAN_MIN"); - - uint256 size = max - min; - - if (max != type(uint256).max) size++; // Make the max inclusive. - if (size == 0) return min; // Using max would be equivalent as well. - // Ensure max is inclusive in cases where x != 0 and max is at uint max. - if (max == type(uint256).max && x != 0) x--; // Accounted for later. - - if (x < min) x += size * (((min - x) / size) + 1); - result = min + ((x - min) % size); - - // Account for decrementing x to make max inclusive. - if (max == type(uint256).max && x != 0) result++; - - // emit log_named_uint("Bound entry", x); - // emit log_named_uint("Bound result", result); - } - - /// @notice Checks morpho will not revert. - /// @param underlying Address of the underlying to supply. - /// @param amount To check. - function assumeSupplyAmountIsCorrect(address underlying, uint256 amount) internal { - hevm.assume(amount > 0); - // All the signers have the same balance at the beginning of a test. - hevm.assume(amount <= ERC20(underlying).balanceOf(address(supplier1))); - } - - /// @notice A borrow amount can be too high on Aave due to governance or unsufficient supply. - /// @param market Address of the AToken. - /// @param amount To check. - function assumeBorrowAmountIsCorrect(address market, uint256 amount) internal { - hevm.assume(amount <= IAToken(market).scaledTotalSupply()); - hevm.assume(amount > 10); - uint256 borrowCap = IERC20(getUnderlying(market)).balanceOf(market); - if (borrowCap != 0) hevm.assume(amount <= borrowCap); - } - - /// @notice Ensures the amount used for the liquidation is correct. - /// @param amount Considered for the liquidation. - function assumeLiquidateAmountIsCorrect(uint256 amount) internal { - hevm.assume(amount > 0); - } - - /// @notice Ensures the amount used for the repay is correct. - /// @param amount Considered for the repay. - function assumeRepayAmountIsCorrect(uint256 amount) internal { - hevm.assume(amount > 0); - } - - /// @notice Make sure the amount used for the withdraw is correct. - /// @param market Address of the AToken. - /// @param amount Considered for the repay. - function assumeWithdrawAmountIsCorrect(address market, uint256 amount) internal { - // TODO hevm.assume(amount.div(ICToken(market).exchangeRateCurrent()) > 0); - } -} diff --git a/test-foundry/fuzzing/compound/TestBorrowFuzzing.t.sol b/test-foundry/fuzzing/compound/TestBorrowFuzzing.t.sol deleted file mode 100644 index 46d3f7d2d..000000000 --- a/test-foundry/fuzzing/compound/TestBorrowFuzzing.t.sol +++ /dev/null @@ -1,179 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "./setup/TestSetupFuzzing.sol"; - -contract TestBorrowFuzzing is TestSetupFuzzing { - using CompoundMath for uint256; - - function testBorrow1( - uint128 _supplied, - uint128 _borrowed, - uint8 _suppliedAsset, - uint8 _borrowedAsset - ) public { - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - (address borrowedAsset, ) = getAsset(_borrowedAsset); - - uint256 supplied = _supplied; - uint256 borrowed = _borrowed; - - assumeSupplyAmountIsCorrect(suppliedUnderlying, supplied); - - borrower1.approve(suppliedUnderlying, supplied); - borrower1.supply(suppliedAsset, supplied); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - borrowedAsset - ); - - hevm.assume(borrowed > borrowable + 10); // +1 to cover for rounding error - - hevm.expectRevert(PositionsManager.UnauthorisedBorrow.selector); - borrower1.borrow(borrowedAsset, borrowed); - } - - function testBorrow2( - uint128 _amountSupplied, - uint8 _suppliedAsset, - uint8 _borrowedAsset, - uint8 _random1 - ) public { - hevm.assume(_random1 != 0); - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - (address borrowedAsset, ) = getAsset(_borrowedAsset); - - uint256 amountSupplied = _amountSupplied; - - assumeSupplyAmountIsCorrect(suppliedUnderlying, amountSupplied); - - borrower1.approve(suppliedUnderlying, amountSupplied); - borrower1.supply(suppliedAsset, amountSupplied); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - borrowedAsset - ); - - uint256 borrowedAmount = (borrowable * _random1) / 255; - hevm.assume(borrowedAmount + 5 < borrowable); // +5 to cover for rounding error - - assumeBorrowAmountIsCorrect(borrowedAsset, borrowedAmount); - borrower1.borrow(borrowedAsset, borrowedAmount); - } - - function testBorrow3( - uint128 _amountSupplied, - uint128 _amountCollateral, - uint8 _matchedAsset, - uint8 _collateralAsset, - uint8 _random1 - ) public { - hevm.assume(_random1 != 0); - (address matchedAsset, address matchedUnderlying) = getAsset(_matchedAsset); - (address collateralAsset, address collateralUnderlying) = getAsset(_collateralAsset); - - uint256 amountSupplied = _amountSupplied; - uint256 amountCollateral = _amountCollateral; - - assumeSupplyAmountIsCorrect(collateralUnderlying, _amountCollateral); - assumeSupplyAmountIsCorrect(matchedUnderlying, amountSupplied); - - supplier1.approve(matchedUnderlying, amountSupplied); - supplier1.supply(matchedAsset, amountSupplied); - - borrower1.approve(collateralUnderlying, amountCollateral); - borrower1.supply(collateralAsset, amountCollateral); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - matchedAsset - ); - - uint256 borrowedAmount = (borrowable * _random1) / 255; - hevm.assume(borrowedAmount + 5 < borrowable); // +5 to cover for rounding error - - assumeBorrowAmountIsCorrect(matchedAsset, borrowedAmount); - borrower1.borrow(matchedAsset, borrowedAmount); - } - - // There is no difference between Borrow3 & 4 because amount proportion aren't pre-determined. - - function testBorrow5( - uint128 _amountSupplied, - uint128 _amountCollateral, - uint8 _matchedAsset, - uint8 _collateralAsset, - uint8 _random1 - ) public { - hevm.assume(_random1 != 0); - (address matchedAsset, address matchedUnderlying) = getAsset(_matchedAsset); - (address collateralAsset, address collateralUnderlying) = getAsset(_collateralAsset); - - uint256 amountSupplied = _amountSupplied; - uint256 amountCollateral = _amountCollateral; - - assumeSupplyAmountIsCorrect(collateralUnderlying, amountCollateral); - - borrower1.approve(collateralUnderlying, amountCollateral); - borrower1.supply(collateralAsset, amountCollateral); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - matchedAsset - ); - uint256 borrowedAmount = (borrowable * _random1) / 255; - hevm.assume(borrowedAmount + 5 < borrowable); // +5 to cover for rounding error - assumeBorrowAmountIsCorrect(matchedAsset, borrowedAmount); - - uint256 NMAX = ((20 * uint256(_random1)) / 255) + 1; - createSigners(NMAX); - - uint256 amountPerSupplier = (amountSupplied / NMAX) + 1; - assumeSupplyAmountIsCorrect(matchedUnderlying, amountPerSupplier); - - for (uint256 i = 0; i < NMAX; i++) { - suppliers[i].approve(matchedUnderlying, amountPerSupplier); - suppliers[i].supply(matchedAsset, amountPerSupplier); - } - - borrower1.borrow(matchedAsset, borrowedAmount); - } - - function testBorrowMultipleAssets( - uint128 _amountCollateral, - uint8 _firstAsset, - uint8 _secondAsset, - uint8 _collateralAsset, - uint8 _random1, - uint8 _random2 - ) public { - hevm.assume(_random1 != 0); - hevm.assume(_random2 != 0); - - (address collateralAsset, address collateralUnderlying) = getAsset(_collateralAsset); - (address firstAsset, ) = getAsset(_firstAsset); - (address secondAsset, ) = getAsset(_secondAsset); - - uint256 amountCollateral = _amountCollateral; - - assumeSupplyAmountIsCorrect(collateralUnderlying, amountCollateral); - - borrower1.approve(collateralUnderlying, amountCollateral); - borrower1.supply(collateralAsset, amountCollateral); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset(address(borrower1), firstAsset); - uint256 borrowedAmount = (borrowable * _random1) / 255; - hevm.assume(borrowedAmount + 5 < borrowable); // +5 to cover for rounding error - - assumeBorrowAmountIsCorrect(firstAsset, borrowedAmount); - borrower1.borrow(firstAsset, borrowedAmount); - - (, borrowable) = lens.getUserMaxCapacitiesForAsset(address(borrower1), secondAsset); - borrowedAmount = (borrowable * _random2) / 255; - hevm.assume(borrowedAmount + 5 < borrowable); // +5 to cover for rounding error - assumeBorrowAmountIsCorrect(secondAsset, borrowedAmount); - borrower1.borrow(secondAsset, borrowedAmount); - } -} diff --git a/test-foundry/fuzzing/compound/TestInterestRateFuzzing.t.sol b/test-foundry/fuzzing/compound/TestInterestRateFuzzing.t.sol deleted file mode 100644 index c0f6b1d26..000000000 --- a/test-foundry/fuzzing/compound/TestInterestRateFuzzing.t.sol +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "@contracts/compound/InterestRatesManager.sol"; -import "@forge-std/Test.sol"; - -contract TestInterestRateFuzzing is InterestRatesManager, Test { - Vm public hevm = Vm(HEVM_ADDRESS); - - uint256 public p2pSupplyIndexTest = 1 * WAD; - uint256 public p2pBorrowIndexTest = 1 * WAD; - uint256 public poolSupplyIndexTest = 2 * WAD; - uint256 public poolBorrowIndexTest = 3 * WAD; - uint256 public lastPoolSupplyIndexTest = 1 * WAD; - uint256 public lastPoolBorrowIndexTest = 1 * WAD; - uint256 public reserveFactor0PerCentTest = 0; - uint256 public reserveFactor50PerCentTest = 5_000; - uint256 public p2pIndexCursorTest = 3_333; - - // prettier-ignore - function computeP2PIndexes(InterestRatesManager.Params memory _params) - public - pure - returns (uint256 p2pSupplyIndex_, uint256 p2pBorrowIndex_) - { - uint256 poolSupplyGrowthFactor = ((_params.poolSupplyIndex * WAD) / _params.lastPoolSupplyIndex); - uint256 poolBorrowGrowthFactor = ((_params.poolBorrowIndex * WAD) / _params.lastPoolBorrowIndex); - uint256 p2pIncrease = ((MAX_BASIS_POINTS - _params.p2pIndexCursor) * poolSupplyGrowthFactor + _params.p2pIndexCursor * poolBorrowGrowthFactor) / MAX_BASIS_POINTS; - uint256 shareOfTheSupplyDelta = _params.delta.p2pBorrowAmount > 0 - ? (((_params.delta.p2pSupplyDelta * _params.lastPoolSupplyIndex) / WAD) * WAD) / - ((_params.delta.p2pSupplyAmount * _params.lastP2PSupplyIndex) / WAD) - : 0; - uint256 shareOfTheBorrowDelta = _params.delta.p2pSupplyAmount > 0 - ? (((_params.delta.p2pBorrowDelta * _params.poolBorrowIndex) / WAD) * WAD) / - ((_params.delta.p2pBorrowAmount * _params.lastP2PBorrowIndex) / WAD) - : 0; - p2pSupplyIndex_ = - _params.lastP2PSupplyIndex * - ((WAD - shareOfTheSupplyDelta) * (p2pIncrease - (_params.reserveFactor * (p2pIncrease - poolSupplyGrowthFactor) / MAX_BASIS_POINTS)) / WAD + - (shareOfTheSupplyDelta * poolSupplyGrowthFactor) / WAD) / - WAD; - p2pBorrowIndex_ = - _params.lastP2PBorrowIndex * - ((WAD - shareOfTheBorrowDelta) * (p2pIncrease + (_params.reserveFactor * (poolBorrowGrowthFactor - p2pIncrease) / MAX_BASIS_POINTS)) / WAD + - (shareOfTheBorrowDelta * poolBorrowGrowthFactor) / WAD) / - WAD; - } - - function testFuzzInterestRates( - uint64 _1, - uint64 _2, - uint64 _3, - uint64 _4, - uint64 _5, - uint64 _6, - uint16 _7, - uint16 _8, - uint64 _9, - uint64 _10, - uint64 _11, - uint64 _12 - ) public { - uint256 _p2pSupplyIndex = WAD + _1; - uint256 _p2pBorrowIndex = WAD + _2; - uint256 _poolSupplyIndex = WAD + _3; - uint256 _poolBorrowIndex = WAD + _4; - uint256 _lastPoolSupplyIndex = WAD + _5; - uint256 _lastPoolBorrowIndex = WAD + _6; - uint256 _reserveFactor = _7 % 10_000; - uint256 _p2pIndexCursor = _8 % 10_000; - uint256 _p2pSupplyDelta = WAD + _9; - uint256 _p2pBorrowDelta = WAD + _10; - uint256 _p2pSupplyAmount = WAD + _11; - uint256 _p2pBorrowAmount = WAD + _12; - - hevm.assume(_lastPoolSupplyIndex <= _poolSupplyIndex); - hevm.assume(_lastPoolBorrowIndex <= _poolBorrowIndex); - hevm.assume( - (_poolBorrowIndex * WAD) / _lastPoolBorrowIndex > - (_poolSupplyIndex * WAD) / _lastPoolSupplyIndex - ); - hevm.assume( - (_p2pSupplyAmount * _p2pSupplyIndex) / WAD > (_p2pSupplyDelta * _poolSupplyIndex) / WAD - ); - hevm.assume( - (_p2pBorrowAmount * _p2pBorrowIndex) / WAD > (_p2pBorrowDelta * _poolBorrowIndex) / WAD - ); - - InterestRatesManager.Params memory params = InterestRatesManager.Params( - _p2pSupplyIndex, - _p2pBorrowIndex, - _poolSupplyIndex, - _poolBorrowIndex, - _lastPoolSupplyIndex, - _lastPoolBorrowIndex, - _reserveFactor, - _p2pIndexCursor, - Types.Delta(_p2pSupplyDelta, _p2pBorrowDelta, _p2pSupplyAmount, _p2pBorrowAmount) - ); - - (uint256 newP2PSupplyIndex, uint256 newP2PBorrowIndex) = _computeP2PIndexes(params); - (uint256 expectednewP2PSupplyIndex, uint256 expectednewP2PBorrowIndex) = computeP2PIndexes( - params - ); - assertApproxEqAbs(newP2PSupplyIndex, expectednewP2PSupplyIndex, 400); - assertApproxEqAbs(newP2PBorrowIndex, expectednewP2PBorrowIndex, 400); - } -} diff --git a/test-foundry/fuzzing/compound/TestLiquidateFuzzing.t.sol b/test-foundry/fuzzing/compound/TestLiquidateFuzzing.t.sol deleted file mode 100644 index 87a60735b..000000000 --- a/test-foundry/fuzzing/compound/TestLiquidateFuzzing.t.sol +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "./setup/TestSetupFuzzing.sol"; - -contract TestLiquidateFuzzing is TestSetupFuzzing { - using CompoundMath for uint256; - - struct addressVars { - address collateralAsset; - address collateralUnderlying; - address suppliedAsset; - address suppliedUnderlying; - address borrowedAsset; - address borrowedUnderlying; - } - - // Should not be able to liquidate a user with enough collateral. - function testLiquidate1Fuzzed( - uint128 _amountSupplied, - uint8 _suppliedAsset, - uint8 _borrowedAsset, - uint8 _firstModulo, - uint8 _secondModulo - ) public { - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - (address borrowedAsset, address borrowedUnderlying) = getAsset(_borrowedAsset); - - uint256 amountSupplied = _amountSupplied; - - // Because this is a Liquidation Test, we need to make sure that the supplied amount is enough - // To obtain a non zero borrow & liquidation amount. - hevm.assume(amountSupplied > 10**ERC20(suppliedUnderlying).decimals()); - hevm.assume(_firstModulo != 0); - hevm.assume(_secondModulo != 0); - assumeSupplyAmountIsCorrect(suppliedUnderlying, amountSupplied); - - borrower1.approve(suppliedUnderlying, amountSupplied); - borrower1.supply(suppliedAsset, amountSupplied); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - borrowedAsset - ); - uint256 borrowedAmount = (borrowable * _firstModulo) / 255; - - assumeBorrowAmountIsCorrect(borrowedAsset, borrowedAmount); - borrower1.borrow(borrowedAsset, borrowedAmount); - - // Liquidate - uint256 toRepay = ((borrowedAmount / 2) * _secondModulo) / 255; - assumeLiquidateAmountIsCorrect(toRepay); - - User liquidator = borrower3; - liquidator.approve(borrowedUnderlying, address(morpho), toRepay); - - hevm.expectRevert(abi.encodeWithSignature("UnauthorisedLiquidate()")); - liquidator.liquidate(borrowedAsset, suppliedAsset, address(borrower1), toRepay); - } - - function testLiquidate2Fuzzed( - uint128 _amountSupplied, - uint8 _suppliedAsset, - uint8 _borrowedAsset, - uint8 _random1 - ) public { - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - (address borrowedAsset, address borrowedUnderlying) = getAsset(_borrowedAsset); - - uint256 amountSupplied = _amountSupplied; - - // Because this is a Liquidation Test, we need to make sure that the supplied amount is enough - // To obtain a non zero borrow & liquidation amount. - hevm.assume(amountSupplied > 10**ERC20(suppliedUnderlying).decimals()); - hevm.assume(_random1 != 0); - assumeSupplyAmountIsCorrect(suppliedUnderlying, amountSupplied); - - borrower1.approve(suppliedUnderlying, amountSupplied); - borrower1.supply(suppliedAsset, amountSupplied); - - (, uint256 borrowedAmount) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - borrowedAsset - ); - - assumeBorrowAmountIsCorrect(borrowedAsset, borrowedAmount); - borrower1.borrow(borrowedAsset, borrowedAmount); - - // Change Oracle. - SimplePriceOracle customOracle = createAndSetCustomPriceOracle(); - customOracle.setDirectPrice( - suppliedUnderlying, - (oracle.getUnderlyingPrice(suppliedAsset) * 94) / 100 - ); - - // Before Liquidation - (, uint256 onPoolBorrowerBefore) = morpho.borrowBalanceInOf( - borrowedAsset, - address(borrower1) - ); - - (, uint256 suppliedBorrowerBefore) = morpho.supplyBalanceInOf( - suppliedAsset, - address(borrower1) - ); - - moveOneBlockForwardBorrowRepay(); - - // Liquidate - uint256 toRepay = ((borrowedAmount / 2) * _random1) / 255; - assumeLiquidateAmountIsCorrect(toRepay); - - User liquidator = borrower3; - liquidator.approve(borrowedUnderlying, address(morpho), toRepay); - - liquidator.liquidate(borrowedAsset, suppliedAsset, address(borrower1), toRepay); - - // After Liquidation - (, uint256 onPoolBorrowerAfter) = morpho.borrowBalanceInOf( - borrowedAsset, - address(borrower1) - ); - (, uint256 suppliedBorrowerAfter) = morpho.supplyBalanceInOf( - suppliedAsset, - address(borrower1) - ); - - assertLt(onPoolBorrowerBefore, onPoolBorrowerAfter); - assertLt(suppliedBorrowerBefore, suppliedBorrowerAfter); - } - - function testLiquidate3Fuzzed( - uint128 _amountSuppliedForMatch, - uint128 _amountCollateral, - uint128 _amountSupplied, - uint8 _collateralAsset, - uint8 _suppliedAsset, - uint8 _borrowedAsset, - uint8 _random1, - uint8 _random2 - ) public { - hevm.assume(_random1 != 0); - hevm.assume(_random2 != 0); - addressVars memory vars; - - (vars.suppliedAsset, vars.suppliedUnderlying) = getAsset(_suppliedAsset); - (vars.borrowedAsset, vars.borrowedUnderlying) = getAsset(_borrowedAsset); - (vars.collateralAsset, vars.collateralUnderlying) = getAsset(_collateralAsset); - - uint256 amountSupplied = _amountSupplied; - uint256 amountSuppliedForMatch = _amountSuppliedForMatch; - uint256 amountCollateral = _amountCollateral; - - // Because this is a Liquidation Test, we need to make sure that the supplied amount is enough - // To obtain a non zero borrow & liquidation amount. - hevm.assume(amountSupplied > 10**ERC20(vars.suppliedUnderlying).decimals()); - hevm.assume(_random1 != 0); - assumeSupplyAmountIsCorrect(vars.suppliedUnderlying, amountSupplied); - - // Borrower1 get his supply & borrow. - borrower1.approve(vars.suppliedUnderlying, amountSupplied); - borrower1.supply(vars.suppliedAsset, amountSupplied); - (, uint256 borrowedAmount) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - vars.borrowedAsset - ); - assumeBorrowAmountIsCorrect(vars.borrowedAsset, borrowedAmount); - borrower1.borrow(vars.borrowedAsset, borrowedAmount); - - // Set up Supplier2 to match the borrow asset of Borrower1. - assumeSupplyAmountIsCorrect(vars.borrowedUnderlying, amountSuppliedForMatch); - supplier2.approve(vars.borrowedUnderlying, amountSuppliedForMatch); - supplier2.supply(vars.borrowedAsset, amountSuppliedForMatch); - - // Set up Borrower2 to match the supplied asset of Borrower1. - assumeSupplyAmountIsCorrect(vars.collateralUnderlying, amountCollateral); - borrower2.approve(vars.collateralUnderlying, amountCollateral); - borrower2.supply(vars.collateralAsset, amountCollateral); - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower2), - vars.suppliedAsset - ); - borrowedAmount = (borrowable * _random1) / 255; - assumeBorrowAmountIsCorrect(vars.suppliedAsset, borrowedAmount); - borrower1.borrow(vars.suppliedAsset, borrowedAmount); - - moveOneBlockForwardBorrowRepay(); - - // Change Oracle. - SimplePriceOracle customOracle = createAndSetCustomPriceOracle(); - customOracle.setDirectPrice( - vars.suppliedUnderlying, - (oracle.getUnderlyingPrice(vars.suppliedAsset) * 94) / 100 - ); - - // Before Liquidation - (, uint256 onPoolBorrowerBefore) = morpho.borrowBalanceInOf( - vars.borrowedAsset, - address(borrower1) - ); - - (, uint256 suppliedBorrowerBefore) = morpho.supplyBalanceInOf( - vars.suppliedAsset, - address(borrower1) - ); - - // Liquidate - uint256 toRepay = ((borrowedAmount / 2) * _random2) / 255; - assumeLiquidateAmountIsCorrect(toRepay); - - User liquidator = borrower3; - liquidator.approve(vars.borrowedUnderlying, address(morpho), toRepay); - - liquidator.liquidate(vars.borrowedAsset, vars.suppliedAsset, address(borrower1), toRepay); - - // After Liquidation - (, uint256 onPoolBorrowerAfter) = morpho.borrowBalanceInOf( - vars.borrowedAsset, - address(borrower1) - ); - - (, uint256 suppliedBorrowerAfter) = morpho.supplyBalanceInOf( - vars.suppliedAsset, - address(borrower1) - ); - - assertLt(onPoolBorrowerBefore, onPoolBorrowerAfter); - assertLt(suppliedBorrowerBefore, suppliedBorrowerAfter); - } -} diff --git a/test-foundry/fuzzing/compound/TestRepayFuzzing.t.sol b/test-foundry/fuzzing/compound/TestRepayFuzzing.t.sol deleted file mode 100644 index c6fc20086..000000000 --- a/test-foundry/fuzzing/compound/TestRepayFuzzing.t.sol +++ /dev/null @@ -1,215 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "./setup/TestSetupFuzzing.sol"; - -contract TestRepayFuzzing is TestSetupFuzzing { - using CompoundMath for uint256; - - // Simple repay on pool. - function testRepay1Fuzzed( - uint128 _supplied, - uint8 _suppliedAsset, - uint8 _borrowedAsset, - uint8 _random1, - uint8 _random2 - ) public { - hevm.assume(_random1 > 10); - hevm.assume(_random2 > 10); - - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - (address borrowedAsset, address borrowedUnderlying) = getAsset(_borrowedAsset); - - uint256 supplied = _supplied; - // To limit number of run where computed borrow & repay amounts are 0. - hevm.assume(supplied > 10**ERC20(suppliedUnderlying).decimals()); - - assumeSupplyAmountIsCorrect(suppliedUnderlying, supplied); - - borrower1.approve(suppliedUnderlying, supplied); - borrower1.supply(suppliedAsset, supplied); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - borrowedAsset - ); - - uint256 borrowedAmount = (borrowable * _random1) / 255; - assumeBorrowAmountIsCorrect(borrowedAsset, borrowedAmount); - borrower1.borrow(borrowedAsset, borrowedAmount); - - moveOneBlockForwardBorrowRepay(); - - uint256 repaidAmount = (borrowedAmount * _random2) / 255; - assumeRepayAmountIsCorrect(borrowedUnderlying, repaidAmount); - borrower1.approve(borrowedUnderlying, repaidAmount); - borrower1.repay(borrowedAsset, repaidAmount); - } - - // Partially matched with one borrower waiting. - function testRepay2Fuzzed( - uint128 _supplied, - uint8 _suppliedAsset, - uint8 _borrowedAsset, - uint8 _random1, - uint8 _random2, - uint8 _random3 - ) public { - hevm.assume(_random1 > 10); - hevm.assume(_random2 > 10); - hevm.assume(_random3 > 10); - - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - (address borrowedAsset, address borrowedUnderlying) = getAsset(_borrowedAsset); - - uint256 supplied = _supplied; - // To limit number of run where computed borrow & repay amounts are 0. - hevm.assume(supplied > 10**ERC20(suppliedUnderlying).decimals()); - - assumeSupplyAmountIsCorrect(suppliedUnderlying, supplied); - - borrower1.approve(suppliedUnderlying, supplied); - borrower1.supply(suppliedAsset, supplied); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - borrowedAsset - ); - - // Borrower1 borrow borrowedAmount. - uint256 borrowedAmount = (borrowable * _random1) / 255; - assumeBorrowAmountIsCorrect(borrowedAsset, borrowedAmount); - borrower1.borrow(borrowedAsset, borrowedAmount); - - // He is matched up to matched amount with supplier1. - uint256 matchedAmount = (borrowedAmount * _random2) / 255; - hevm.assume(matchedAmount != 0); - supplier1.approve(borrowedUnderlying, matchedAmount); - supplier1.supply(borrowedAsset, matchedAmount); - - // Borrower2 has his debt waiting on pool. - borrower2.approve(suppliedUnderlying, supplied); - borrower2.supply(suppliedAsset, supplied); - borrower2.borrow(borrowedAsset, borrowedAmount); - - moveOneBlockForwardBorrowRepay(); - - // Borrower1 repays a random amount. - uint256 repaidAmount = (borrowedAmount * _random3) / 255; - assumeRepayAmountIsCorrect(borrowedUnderlying, repaidAmount); - borrower1.approve(borrowedUnderlying, repaidAmount); - borrower1.repay(borrowedAsset, repaidAmount); - } - - // Matched, with random number of borrower await on pool to replace. - function testRepay3Fuzzed( - uint128 _suppliedAmount, - uint8 _suppliedAsset, - uint8 _borrowedAsset, - uint8 _random1, - uint8 _random2, - uint8 _random3 - ) public { - hevm.assume(_random1 > 10); - hevm.assume(_random2 > 10); - hevm.assume(_random3 > 10); - - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - (address borrowedAsset, address borrowedUnderlying) = getAsset(_borrowedAsset); - - uint256 suppliedAmount = _suppliedAmount; - // To limit number of run where computed amounts are 0. - hevm.assume(suppliedAmount > 10**ERC20(suppliedUnderlying).decimals()); - - assumeSupplyAmountIsCorrect(suppliedUnderlying, suppliedAmount); - - borrower1.approve(suppliedUnderlying, suppliedAmount); - borrower1.supply(suppliedAsset, suppliedAmount); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - borrowedAsset - ); - - // Borrower1 borrows borrowedAmount. - uint256 borrowedAmount = (borrowable * _random1) / 255; - assumeBorrowAmountIsCorrect(borrowedAsset, borrowedAmount); - borrower1.borrow(borrowedAsset, borrowedAmount); - - // He is matched with supplier1. - supplier1.approve(borrowedUnderlying, borrowedAmount); - supplier1.supply(borrowedAsset, borrowedAmount); - - // There is a random number of waiting borrower on pool. - uint256 nbOfWaitingBorrowers = ((20 * uint256(_random2)) / 255) + 1; - createSigners(nbOfWaitingBorrowers); - uint256 amountPerBorrower = borrowedAmount / nbOfWaitingBorrowers; - assumeBorrowAmountIsCorrect(borrowedAsset, amountPerBorrower); - for (uint256 i = 2; i < nbOfWaitingBorrowers; i++) { - borrowers[i].approve(suppliedUnderlying, suppliedAmount); - borrowers[i].supply(suppliedAsset, suppliedAmount); - borrowers[i].borrow(borrowedAsset, amountPerBorrower); - } - - moveOneBlockForwardBorrowRepay(); - - // Borrower1 repays a random amount. - uint256 repaidAmount = (borrowedAmount * _random3) / 255; - assumeRepayAmountIsCorrect(borrowedUnderlying, repaidAmount); - borrower1.approve(borrowedUnderlying, repaidAmount); - borrower1.repay(borrowedAsset, repaidAmount); - } - - function testRepay4Fuzzed( - uint128 _borrowAmount, - uint8 _borrowedAsset, - uint8 _collateralAsset, - uint8 _random1, - uint8 _random2 - ) public { - hevm.assume(_random1 > 10); - hevm.assume(_random2 > 10); - uint256 borrowAmount = _borrowAmount; - - (address collateralAsset, address collateralUnderlying) = getAsset(_collateralAsset); - (address borrowedAsset, address borrowedUnderlying) = getAsset(_borrowedAsset); - - uint256 collateralToSupply = ERC20(collateralUnderlying).balanceOf(address(borrower1)); - - borrower1.approve(collateralUnderlying, collateralToSupply); - borrower1.supply(collateralAsset, collateralToSupply); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - borrowedAsset - ); - hevm.assume(borrowAmount < borrowable); - assumeBorrowAmountIsCorrect(borrowedAsset, borrowAmount); - borrower1.borrow(borrowedAsset, borrowAmount); - - uint256 NMAX = ((20 * uint256(_random1)) / 255) + 1; - uint256 amountPerUser = borrowAmount / (2 * NMAX); - - assumeSupplyAmountIsCorrect(borrowedUnderlying, amountPerUser); - - createSigners(2 * NMAX); - - for (uint256 i; i < 2 * NMAX; i++) { - suppliers[i].approve(borrowedUnderlying, amountPerUser); - suppliers[i].supply(borrowedAsset, amountPerUser); - } - for (uint256 i = 1; i <= NMAX; i++) { - borrowers[i].approve(collateralUnderlying, collateralToSupply); - borrowers[i].supply(collateralAsset, collateralToSupply); - borrowers[i].borrow(borrowedAsset, amountPerUser); - } - - moveOneBlockForwardBorrowRepay(); - - // Borrower1 repays a random amount. - uint256 repaidAmount = (borrowAmount * _random2) / 255; - assumeRepayAmountIsCorrect(borrowedUnderlying, repaidAmount); - borrower1.approve(borrowedUnderlying, type(uint256).max); - borrower1.repay(borrowedAsset, type(uint256).max); - } -} diff --git a/test-foundry/fuzzing/compound/TestSupplyFuzzing.t.sol b/test-foundry/fuzzing/compound/TestSupplyFuzzing.t.sol deleted file mode 100644 index 3798592dd..000000000 --- a/test-foundry/fuzzing/compound/TestSupplyFuzzing.t.sol +++ /dev/null @@ -1,198 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "./setup/TestSetupFuzzing.sol"; - -contract TestSupplyFuzzing is TestSetupFuzzing { - using CompoundMath for uint256; - - struct AssetVars { - address suppliedCToken; - address suppliedUnderlying; - address borrowedCToken; - address borrowedUnderlying; - address collateralCToken; - address collateralUnderlying; - } - - function testSupply1Fuzzed(uint128 _amount, uint8 _asset) public { - (address asset, address underlying) = getAsset(_asset); - uint256 amount = _amount; - - assumeSupplyAmountIsCorrect(underlying, amount); - supplier1.approve(underlying, amount); - supplier1.supply(asset, amount); - - uint256 supplyPoolIndex = ICToken(asset).exchangeRateCurrent(); - uint256 expectedOnPool = amount.div(supplyPoolIndex); - - testEquality(ERC20(asset).balanceOf(address(morpho)), expectedOnPool, "balance of cToken"); - - (uint256 inP2P, uint256 onPool) = morpho.supplyBalanceInOf(asset, address(supplier1)); - - testEquality(onPool, ICToken(asset).balanceOf(address(morpho)), "on pool"); - testEquality(onPool, expectedOnPool, "on pool"); - assertEq(inP2P, 0, "in P2P"); - } - - function testSupply2Fuzzed( - uint128 _suppliedAmount, - uint8 _randomModulo, - uint8 _suppliedCToken, - uint8 _borrowedCToken - ) public { - hevm.assume(_randomModulo > 0); - AssetVars memory vars; - - (vars.suppliedCToken, vars.suppliedUnderlying) = getAsset(_suppliedCToken); - (vars.borrowedCToken, vars.borrowedUnderlying) = getAsset(_borrowedCToken); - - uint256 suppliedAmount = _suppliedAmount; - - assumeSupplyAmountIsCorrect(vars.suppliedUnderlying, 2 * suppliedAmount); - // Because there are two supply with suppliedAmount - - borrower1.approve(vars.suppliedUnderlying, suppliedAmount); - borrower1.supply(vars.suppliedCToken, suppliedAmount); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - vars.borrowedCToken - ); - - uint256 borrowedAmount = (borrowable * _randomModulo) / 255; - assumeBorrowAmountIsCorrect(vars.borrowedCToken, borrowedAmount); - borrower1.borrow(vars.borrowedCToken, borrowedAmount); - - borrower1.approve(vars.suppliedUnderlying, suppliedAmount); - borrower1.supply(vars.suppliedCToken, suppliedAmount); - } - - // what is fuzzed is the proportion in P2P on the supply of the second user - function testSupply3Fuzzed( - uint128 _suppliedAmount, - uint8 _collateralAsset, - uint8 _supplyAsset, - uint8 _random1 - ) public { - AssetVars memory vars; - (vars.suppliedCToken, vars.suppliedUnderlying) = getAsset(_supplyAsset); - (vars.collateralCToken, vars.collateralUnderlying) = getAsset(_collateralAsset); - - assumeSupplyAmountIsCorrect(vars.suppliedUnderlying, _suppliedAmount); - - uint256 collateralAmountToSupply = ERC20(vars.collateralUnderlying).balanceOf( - address(borrower1) - ); - - borrower1.approve(vars.collateralUnderlying, collateralAmountToSupply); - borrower1.supply(vars.collateralCToken, collateralAmountToSupply); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - vars.suppliedCToken - ); - uint256 borrowedAmount = (borrowable * _random1) / 255; - assumeBorrowAmountIsCorrect(vars.suppliedCToken, borrowedAmount); - - borrower1.borrow(vars.suppliedCToken, borrowedAmount); - - supplier1.approve(vars.suppliedUnderlying, _suppliedAmount); - supplier1.supply(vars.suppliedCToken, _suppliedAmount); - } - - // what is fuzzed is the amount supplied - function testSupply4Fuzzed( - uint128 _suppliedAmount, - uint8 _collateralAsset, - uint8 _supplyAsset, - uint8 _random1 - ) public { - AssetVars memory vars; - (vars.suppliedCToken, vars.suppliedUnderlying) = getAsset(_supplyAsset); - (vars.collateralCToken, vars.collateralUnderlying) = getAsset(_collateralAsset); - uint256 NMAX = ((20 * uint256(_random1)) / 255) + 1; - uint256 amountPerBorrower = _suppliedAmount / NMAX; - - assumeSupplyAmountIsCorrect(vars.suppliedUnderlying, _suppliedAmount); - assumeBorrowAmountIsCorrect(vars.suppliedCToken, NMAX * amountPerBorrower); - - setDefaultMaxGasForMatchingHelper( - type(uint64).max, - type(uint64).max, - type(uint64).max, - type(uint64).max - ); - createSigners(NMAX); - - uint256 collateralAmount = ERC20(vars.collateralUnderlying).balanceOf(address(borrower1)); - borrower1.approve(vars.collateralUnderlying, collateralAmount); - borrower1.supply(vars.collateralCToken, collateralAmount); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - vars.suppliedCToken - ); - - hevm.assume(amountPerBorrower < borrowable); - borrower1.borrow(vars.suppliedCToken, amountPerBorrower); - for (uint256 i = 1; i < NMAX - 1; i++) { - borrowers[i + 1].approve(vars.collateralUnderlying, collateralAmount); - borrowers[i + 1].supply(vars.collateralCToken, collateralAmount); - borrowers[i + 1].borrow(vars.suppliedCToken, amountPerBorrower); - } - - supplier1.approve(vars.suppliedUnderlying, _suppliedAmount); - supplier1.supply(vars.suppliedCToken, _suppliedAmount); - } - - // what is fuzzed is the amount supplied - function testSupply5Fuzzed( - uint128 _suppliedAmount, - uint8 _collateralAsset, - uint8 _supplyAsset, - uint8 _random1 - ) public { - AssetVars memory vars; - (vars.suppliedCToken, vars.suppliedUnderlying) = getAsset(_supplyAsset); - (vars.collateralCToken, vars.collateralUnderlying) = getAsset(_collateralAsset); - uint256 NMAX = ((20 * uint256(_random1)) / 255) + 1; - uint256 amountPerBorrower = _suppliedAmount / (2 * NMAX); - - assumeSupplyAmountIsCorrect(vars.suppliedUnderlying, _suppliedAmount); - assumeBorrowAmountIsCorrect(vars.suppliedCToken, NMAX * amountPerBorrower); - - setDefaultMaxGasForMatchingHelper( - type(uint64).max, - type(uint64).max, - type(uint64).max, - type(uint64).max - ); - - uint256 collateralAmount = ERC20(vars.collateralUnderlying).balanceOf(address(borrower1)); - - { - borrower1.approve(vars.collateralUnderlying, collateralAmount); - borrower1.supply(vars.collateralCToken, collateralAmount); - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - vars.suppliedCToken - ); - hevm.assume(borrowable >= amountPerBorrower); - borrower1.borrow(vars.suppliedCToken, amountPerBorrower); - } - createSigners(NMAX); - - for (uint256 i = 0; i < NMAX - 1; i++) { - borrowers[i + 1].approve(vars.collateralUnderlying, collateralAmount); - borrowers[i + 1].supply(vars.collateralCToken, collateralAmount); - borrowers[i + 1].borrow(vars.suppliedCToken, amountPerBorrower); - } - - { - uint256 actuallySupplied = (_suppliedAmount / NMAX) * NMAX; - supplier1.approve(vars.suppliedUnderlying, actuallySupplied); - supplier1.supply(vars.suppliedCToken, actuallySupplied); - } - } -} diff --git a/test-foundry/fuzzing/compound/TestWithdrawFuzzing.t.sol b/test-foundry/fuzzing/compound/TestWithdrawFuzzing.t.sol deleted file mode 100644 index fa20b5688..000000000 --- a/test-foundry/fuzzing/compound/TestWithdrawFuzzing.t.sol +++ /dev/null @@ -1,341 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "./setup/TestSetupFuzzing.sol"; -import {Attacker} from "../../compound/helpers/Attacker.sol"; - -contract TestWithdrawFuzzing is TestSetupFuzzing { - using CompoundMath for uint256; - - function testWithdraw1Fuzzed( - uint128 _suppliedAmount, - uint8 _borrowedAsset, - uint8 _suppliedAsset - ) public { - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - (address borrowedAsset, ) = getAsset(_borrowedAsset); - - uint256 suppliedAmount = _suppliedAmount; - assumeSupplyAmountIsCorrect(suppliedUnderlying, suppliedAmount); - hevm.assume(suppliedAmount > 10**ERC20(suppliedUnderlying).decimals()); - // You need this to make sure that even with compound's approximation, you'll have an amount to withdraw - - borrower1.approve(suppliedUnderlying, suppliedAmount); - borrower1.supply(suppliedAsset, suppliedAmount); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - borrowedAsset - ); - assumeBorrowAmountIsCorrect(borrowedAsset, borrowable); - borrower1.borrow(borrowedAsset, borrowable); - - assumeWithdrawAmountIsCorrect(suppliedAsset, suppliedAmount); - hevm.expectRevert(abi.encodeWithSignature("UnauthorisedWithdraw()")); - borrower1.withdraw(suppliedAsset, suppliedAmount); - } - - function testWithdraw2Fuzzed( - uint128 _suppliedAmount, - uint8 _suppliedAsset, - uint8 _random1 - ) public { - hevm.assume(_random1 != 0); - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - - uint256 suppliedAmount = _suppliedAmount; - assumeSupplyAmountIsCorrect(suppliedUnderlying, suppliedAmount); - hevm.assume(suppliedAmount > 10**ERC20(suppliedUnderlying).decimals()); - // You need this to make sure that even with compound's approximation, you'll have an amount to withdraw - - supplier1.approve(suppliedUnderlying, suppliedAmount); - supplier1.supply(suppliedAsset, suppliedAmount); - - uint256 withdrawnAmount = (suppliedAmount * _random1) / 255; - assumeWithdrawAmountIsCorrect(suppliedAsset, withdrawnAmount); - supplier1.withdraw(suppliedAsset, withdrawnAmount); - } - - function testWithdrawAllFuzzed(uint128 _suppliedAmount, uint8 _suppliedAsset) public { - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - - uint256 suppliedAmount = _suppliedAmount; - assumeSupplyAmountIsCorrect(suppliedUnderlying, suppliedAmount); - hevm.assume(suppliedAmount > 10**ERC20(suppliedUnderlying).decimals()); - // You need this to make sure that even with compound's approximation, you'll have an amount to withdraw - - supplier1.approve(suppliedUnderlying, suppliedAmount); - supplier1.supply(suppliedAsset, suppliedAmount); - supplier1.withdraw(suppliedAsset, type(uint256).max); - } - - function testWithdraw3_1Fuzzed( - uint128 _amountSupplied, - uint8 _collateralAsset, - uint8 _suppliedAsset, - uint8 _random1 - ) public { - hevm.assume(_random1 != 0); - - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - (address collateralAsset, address collateralUnderlying) = getAsset(_collateralAsset); - - uint256 amountSupplied = _amountSupplied; - - assumeSupplyAmountIsCorrect(suppliedUnderlying, amountSupplied); - hevm.assume(amountSupplied > 10**ERC20(suppliedUnderlying).decimals()); - // You need this to make sure that even with compound's approximation, you'll have an amount to withdraw - - // Borrower1 & supplier1 are matched for amountSupplied. - uint256 collateralToSupply = ERC20(collateralUnderlying).balanceOf(address(borrower1)); - - borrower1.approve(collateralUnderlying, collateralToSupply); - borrower1.supply(collateralAsset, collateralToSupply); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - suppliedAsset - ); - hevm.assume(borrowable > amountSupplied); - assumeBorrowAmountIsCorrect(suppliedAsset, amountSupplied); - borrower1.borrow(suppliedAsset, amountSupplied); - - supplier1.approve(suppliedUnderlying, amountSupplied); - supplier1.supply(suppliedAsset, amountSupplied); - - // Supplier1 withdraws a random amount. - uint256 withdrawnAmount = (amountSupplied * _random1) / 255; - assumeWithdrawAmountIsCorrect(suppliedAsset, withdrawnAmount); - supplier1.withdraw(suppliedAsset, withdrawnAmount); - } - - function testWithdraw3_2Fuzzed( - uint128 _amountSupplied, - uint8 _collateralAsset, - uint8 _suppliedAsset, - uint8 _random1, - uint8 _random2 - ) public { - hevm.assume(_random1 != 0); - hevm.assume(_random2 != 0); - - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - (address collateralAsset, address collateralUnderlying) = getAsset(_collateralAsset); - - uint256 amountSupplied = _amountSupplied; - - assumeSupplyAmountIsCorrect(suppliedUnderlying, amountSupplied); - hevm.assume(amountSupplied > 10**ERC20(suppliedUnderlying).decimals()); - // You need this to make sure that even with compound's a3_2pproximation, you'll have an amount to withdraw - hevm.assume(amountSupplied < ICToken(suppliedAsset).getCash()); - // In order to make sure that the Delta from the withdraw won't take more than what's available on the market - - // Borrower1 & supplier1 are matched for suppliedAmount. - supplier1.approve(suppliedUnderlying, amountSupplied); - supplier1.supply(suppliedAsset, amountSupplied); - - uint256 collateralToSupply = ERC20(collateralUnderlying).balanceOf(address(borrower1)); - borrower1.approve(collateralUnderlying, collateralToSupply); - borrower1.supply(collateralAsset, collateralToSupply); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - suppliedAsset - ); - hevm.assume(borrowable > amountSupplied); - assumeBorrowAmountIsCorrect(suppliedAsset, amountSupplied); - borrower1.borrow(suppliedAsset, amountSupplied); - - // NMAX suppliers have up to suppliedAmount waiting on pool - uint256 NMAX = ((20 * uint256(_random1)) / 255) + 1; - createSigners(NMAX); - - uint256 amountPerSupplier = amountSupplied / NMAX; - assumeSupplyAmountIsCorrect(suppliedUnderlying, amountPerSupplier); - - for (uint256 i = 1; i < NMAX; i++) { - suppliers[i].approve(suppliedUnderlying, amountPerSupplier); - suppliers[i].supply(suppliedAsset, amountPerSupplier); - } - - uint256 withdrawnAmount = (amountSupplied * _random2) / 255; - assumeWithdrawAmountIsCorrect(suppliedAsset, withdrawnAmount); - supplier1.withdraw(suppliedAsset, type(uint256).max); - } - - function testWithdraw3_4Fuzzed( - uint128 _amountSupplied, - uint8 _collateralAsset, - uint8 _suppliedAsset, - uint8 _random1, - uint8 _random2 - ) public { - hevm.assume(_random1 != 0); - hevm.assume(_random2 != 0); - - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - (address collateralAsset, address collateralUnderlying) = getAsset(_collateralAsset); - - uint256 amountSupplied = _amountSupplied; - - assumeSupplyAmountIsCorrect(suppliedUnderlying, amountSupplied); - hevm.assume(amountSupplied > 10**ERC20(suppliedUnderlying).decimals()); - // You need this to make sure that even with compound's approximation, you'll have an amount to withdraw - hevm.assume(amountSupplied < ICToken(suppliedAsset).getCash()); - // In order to make sure that the Delta from the withdraw won't take more than what's available on the market - - // Borrower1 & supplier1 are matched for suppliedAmount. - supplier1.approve(suppliedUnderlying, amountSupplied); - supplier1.supply(suppliedAsset, amountSupplied); - - uint256 collateralToSupply = ERC20(collateralUnderlying).balanceOf(address(borrower1)); - borrower1.approve(collateralUnderlying, collateralToSupply); - borrower1.supply(collateralAsset, collateralToSupply); - - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - suppliedAsset - ); - hevm.assume(borrowable > amountSupplied); - assumeBorrowAmountIsCorrect(suppliedAsset, amountSupplied); - borrower1.borrow(suppliedAsset, amountSupplied); - - // NMAX suppliers have up to suppliedAmount waiting on pool - uint256 NMAX = ((20 * uint256(_random1)) / 255) + 1; - createSigners(NMAX); - - uint256 amountPerSupplier = amountSupplied / (2 * NMAX); - assumeSupplyAmountIsCorrect(suppliedUnderlying, amountPerSupplier); - - for (uint256 i = 1; i < NMAX; i++) { - suppliers[i].approve(suppliedUnderlying, amountPerSupplier); - suppliers[i].supply(suppliedAsset, amountPerSupplier); - } - - uint256 withdrawnAmount = (amountSupplied * _random2) / 255; - assumeWithdrawAmountIsCorrect(suppliedAsset, withdrawnAmount); - supplier1.withdraw(suppliedAsset, type(uint256).max); - } - - function testDeltaWithdrawFuzzed( - uint128 _amountSupplied, - uint8 _collateralAsset, - uint8 _suppliedAsset, - uint8 _random1, - uint8 _random2 - ) public { - hevm.assume(_random1 != 0); - hevm.assume(_random2 != 0); - - (address suppliedAsset, address suppliedUnderlying) = getAsset(_suppliedAsset); - (address collateralAsset, address collateralUnderlying) = getAsset(_collateralAsset); - - uint256 amountSupplied = _amountSupplied; - - // 2e6 allows only 10 unmatch borrowers. - setDefaultMaxGasForMatchingHelper(3e6, 3e6, 2e6, 2e6); - - // supplier1 and 20 borrowers are matched for amountSupplied. - assumeSupplyAmountIsCorrect(suppliedUnderlying, amountSupplied); - hevm.assume(amountSupplied < ICToken(suppliedAsset).getCash()); - // In order to make sure that the Delta from the withdraw won't take more than what's available on the market - - hevm.assume(amountSupplied > 10**ERC20(suppliedUnderlying).decimals()); - // You need this to make sure that even with compound's approximation, you'll have an amount to withdraw - - supplier1.approve(suppliedUnderlying, amountSupplied); - supplier1.supply(suppliedAsset, amountSupplied); - - uint256 NMAX = ((20 * uint256(_random1)) / 255) + 1; - createSigners(NMAX); - - uint256 collateralToSupply = ERC20(collateralUnderlying).balanceOf(address(borrower1)); - borrower1.approve(collateralUnderlying, collateralToSupply); - borrower1.supply(collateralAsset, collateralToSupply); - - // Use borrower1 first to check that those borrow are fine. - (, uint256 borrowable) = lens.getUserMaxCapacitiesForAsset( - address(borrower1), - suppliedAsset - ); - uint256 amountPerBorrower = amountSupplied / NMAX; - hevm.assume(borrowable >= amountPerBorrower); - - assumeBorrowAmountIsCorrect(suppliedAsset, NMAX * amountPerBorrower); - borrower1.borrow(suppliedAsset, amountPerBorrower); - - for (uint256 i = 1; i < NMAX; i++) { - borrowers[i].approve(collateralUnderlying, collateralToSupply); - borrowers[i].supply(collateralAsset, collateralToSupply); - borrowers[i].borrow(suppliedAsset, amountPerBorrower); - } - - { - // Supplier withdraws max. - // Should create a delta on borrowers side. - supplier1.withdraw(suppliedAsset, type(uint256).max); - - // supplier should be able to deposit to help remove delta - supplier2.approve(suppliedUnderlying, amountSupplied); - supplier2.supply(suppliedAsset, amountSupplied); - } - - moveOneBlockForwardBorrowRepay(); - - // Borrow delta reduction with borrowers repaying - for (uint256 i = NMAX / 2; i < NMAX; i++) { - borrowers[i].approve(suppliedUnderlying, amountPerBorrower); - borrowers[i].repay(suppliedAsset, amountPerBorrower); - } - } - - function testWithdrawMultipleAssetsFuzzed( - uint8 _proportionBorrowed, - uint8 _suppliedAsset1, - uint8 _suppliedAsset2, - uint128 _amount1, - uint128 _amount2 - ) public { - (address asset1, address underlying1) = getAsset(_suppliedAsset1); - (address asset2, address underlying2) = getAsset(_suppliedAsset2); - - hevm.assume( - _amount1 >= 1e14 && _amount1 < ERC20(underlying1).balanceOf(address(asset1)) // Less than the available liquidity of CTokens, but more than would be rounded to zero - ); - hevm.assume(_amount2 >= 1e14 && _amount2 < ERC20(underlying2).balanceOf(address(asset2))); - hevm.assume(_proportionBorrowed > 0); - - supplier1.approve(underlying1, _amount1); - supplier1.supply(asset1, _amount1); - supplier1.approve(underlying2, _amount2); - supplier1.supply(asset2, _amount2); - - borrower1.approve(dai, type(uint256).max); - borrower1.supply(cDai, 10_000_000 * 1e18); - - (, uint256 borrowable1) = lens.getUserMaxCapacitiesForAsset(address(borrower1), asset1); - (, uint256 borrowable2) = lens.getUserMaxCapacitiesForAsset(address(borrower1), asset2); - - // Amounts available in the cTokens - uint256 compBalance1 = asset1 == cEth - ? asset1.balance - : ERC20(underlying1).balanceOf(asset1); - uint256 compBalance2 = asset2 == cEth - ? asset2.balance - : ERC20(underlying2).balanceOf(asset2); - - borrowable1 = borrowable1 > compBalance1 ? compBalance1 : borrowable1; - borrowable2 = borrowable2 > compBalance2 ? compBalance2 : borrowable2; - - uint256 toBorrow1 = (_amount1 * _proportionBorrowed) / type(uint8).max; - toBorrow1 = toBorrow1 > borrowable1 / 2 ? borrowable1 / 2 : toBorrow1; - uint256 toBorrow2 = (_amount2 * _proportionBorrowed) / type(uint8).max; - toBorrow2 = toBorrow2 > borrowable2 / 2 ? borrowable2 / 2 : toBorrow2; - - borrower1.borrow(asset1, toBorrow1); - borrower1.borrow(asset2, toBorrow2); - - supplier1.withdraw(asset1, _amount1); - supplier1.withdraw(asset2, _amount2); - } -} diff --git a/test-foundry/fuzzing/compound/setup/TestSetupFuzzing.sol b/test-foundry/fuzzing/compound/setup/TestSetupFuzzing.sol deleted file mode 100644 index d394e5d89..000000000 --- a/test-foundry/fuzzing/compound/setup/TestSetupFuzzing.sol +++ /dev/null @@ -1,413 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "@contracts/compound/interfaces/compound/ICompound.sol"; -import "@contracts/compound/interfaces/ICompRewardsLens.sol"; -import "@contracts/compound/interfaces/IRewardsManager.sol"; - -import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; -import "@openzeppelin/contracts/utils/Strings.sol"; - -import "@contracts/compound/IncentivesVault.sol"; -import "@contracts/compound/RewardsManager.sol"; -import "@contracts/compound/CompRewardsLens.sol"; -import "@contracts/compound/PositionsManager.sol"; -import "@contracts/compound/MatchingEngine.sol"; -import "@contracts/compound/InterestRatesManager.sol"; -import "@contracts/compound/Morpho.sol"; -import "@contracts/compound/Lens.sol"; - -import "../../../common/helpers/MorphoToken.sol"; -import "../../../common/helpers/Chains.sol"; -import "../../../compound/helpers/SimplePriceOracle.sol"; -import "../../../compound/helpers/DumbOracle.sol"; -import {User} from "../../../compound/helpers/User.sol"; -import {Utils} from "../../../compound/setup/Utils.sol"; -import "@forge-std/stdlib.sol"; -import "@forge-std/console.sol"; -import "@config/Config.sol"; - -interface IAdminComptroller { - function _setPriceOracle(SimplePriceOracle newOracle) external returns (uint256); - - function admin() external view returns (address); -} - -contract TestSetupFuzzing is Config, Utils, stdCheats { - using CompoundMath for uint256; - - Vm public hevm = Vm(HEVM_ADDRESS); - - uint256 public constant MAX_BASIS_POINTS = 10_000; - uint256 public constant INITIAL_BALANCE = 15_000_000_000; - uint256 public NMAX = 20; - address[] internal tokens = [ - dai, - usdc, - usdt, - wbtc, - wEth, - comp, - bat, - tusd, - uni, - zrx, - link, - mkr, - fei, - yfi, - usdp, - sushi, - aave - ]; - - ProxyAdmin public proxyAdmin; - TransparentUpgradeableProxy public morphoProxy; - Morpho internal morphoImplV1; - Morpho internal morpho; - InterestRatesManager internal interestRatesManager; - TransparentUpgradeableProxy internal rewardsManagerProxy; - IRewardsManager internal rewardsManagerImplV1; - IRewardsManager internal rewardsManager; - ICompRewardsLens internal compRewardsLens; - IPositionsManager internal positionsManager; - Lens internal lens; - - IncentivesVault public incentivesVault; - DumbOracle internal dumbOracle; - MorphoToken public morphoToken; - IComptroller public comptroller; - ICompoundOracle public oracle; - - User public supplier1; - User public supplier2; - User public supplier3; - User[] public suppliers; - User public borrower1; - User public borrower2; - User public borrower3; - User[] public borrowers; - User public treasuryVault; - - address[] public pools; - - function setUp() public { - initContracts(); - setContractsLabels(); - initUsers(); - } - - function initContracts() internal { - Types.MaxGasForMatching memory defaultMaxGasForMatching = Types.MaxGasForMatching({ - supply: 3e6, - borrow: 3e6, - withdraw: 3e6, - repay: 3e6 - }); - - interestRatesManager = new InterestRatesManager(); - positionsManager = new PositionsManager(); - - /// Deploy proxies /// - - proxyAdmin = new ProxyAdmin(); - - morphoImplV1 = new Morpho(); - morphoProxy = new TransparentUpgradeableProxy(address(morphoImplV1), address(this), ""); - - morphoProxy.changeAdmin(address(proxyAdmin)); - morpho = Morpho(payable(address(morphoProxy))); - morpho.initialize( - positionsManager, - interestRatesManager, - comptroller, - defaultMaxGasForMatching, - 1, - 20, - cEth, - wEth - ); - - treasuryVault = new User(morpho); - - oracle = ICompoundOracle(comptroller.oracle()); - morpho.setTreasuryVault(address(treasuryVault)); - - // make sure the wEth contract has enough ETH to unwrap any amount - hevm.deal(wEth, type(uint128).max); - - lens = new Lens(address(morpho)); - - /// Create markets /// - - createMarket(cDai); - createMarket(cUsdc); - createMarket(cUsdt); - createMarket(cBat); - createMarket(cEth); - createMarket(cAave); - createMarket(cTusd); - createMarket(cUni); - // createMarket(cComp); - createMarket(cZrx); - createMarket(cLink); - createMarket(cMkr); - // createMarket(cFei); - createMarket(cYfi); - createMarket(cUsdp); - createMarket(cSushi); - // createMarket(cWbtc2); // Mint is paused on compound - - hevm.roll(block.number + 1); - - /// Create Morpho token, deploy Incentives Vault and activate COMP rewards /// - - morphoToken = new MorphoToken(address(this)); - dumbOracle = new DumbOracle(); - incentivesVault = new IncentivesVault( - IComptroller(comptrollerAddress), - IMorpho(address(morpho)), - morphoToken, - address(1), - dumbOracle - ); - morphoToken.transfer(address(incentivesVault), 1_000_000 ether); - morpho.setIncentivesVault(incentivesVault); - - rewardsManagerImplV1 = new RewardsManager(); - rewardsManagerProxy = new TransparentUpgradeableProxy( - address(rewardsManagerImplV1), - address(proxyAdmin), - "" - ); - rewardsManager = RewardsManager(address(rewardsManagerProxy)); - rewardsManager.initialize(address(morpho)); - - morpho.setRewardsManager(rewardsManager); - compRewardsLens = new CompRewardsLens(address(morpho)); - - // Tip the Morpho contract to ensure that there are no dust errors on withdraw - deal(aave, address(morpho), 10**ERC20(aave).decimals()); - deal(dai, address(morpho), 10**ERC20(dai).decimals()); - deal(usdc, address(morpho), 10**ERC20(usdc).decimals()); - deal(usdt, address(morpho), 10**ERC20(usdt).decimals()); - deal(wbtc, address(morpho), 10**ERC20(wbtc).decimals()); - deal(wEth, address(morpho), 10**ERC20(wEth).decimals()); - deal(comp, address(morpho), 10**ERC20(comp).decimals()); - deal(bat, address(morpho), 10**ERC20(bat).decimals()); - deal(tusd, address(morpho), 10**ERC20(tusd).decimals()); - deal(uni, address(morpho), 10**ERC20(uni).decimals()); - deal(zrx, address(morpho), 10**ERC20(zrx).decimals()); - deal(link, address(morpho), 10**ERC20(link).decimals()); - deal(mkr, address(morpho), 10**ERC20(mkr).decimals()); - deal(fei, address(morpho), 10**ERC20(fei).decimals()); - deal(yfi, address(morpho), 10**ERC20(yfi).decimals()); - deal(usdp, address(morpho), 10**ERC20(usdp).decimals()); - deal(sushi, address(morpho), 10**ERC20(sushi).decimals()); - } - - function createMarket(address _cToken) internal { - Types.MarketParameters memory defaultMarketParams = Types.MarketParameters({ - reserveFactor: 0, - p2pIndexCursor: 5000 - }); - - morpho.createMarket(_cToken, defaultMarketParams); - morpho.setP2PIndexCursor(_cToken, 3_333); - - // All tokens must also be added to the pools array, for the correct behavior of TestLiquidate::createAndSetCustomPriceOracle. - pools.push(_cToken); - - hevm.label(_cToken, ERC20(_cToken).symbol()); - if (_cToken == cEth) hevm.label(wEth, "WETH"); - else { - address underlying = ICToken(_cToken).underlying(); - if (underlying == 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2) { - hevm.label(underlying, "mkr"); - // This is because mkr symbol is a byte32 - } else { - hevm.label(underlying, ERC20(underlying).symbol()); - } - } - } - - function initUsers() internal { - for (uint256 i = 0; i < 3; i++) { - suppliers.push(new User(morpho)); - hevm.label( - address(suppliers[i]), - string(abi.encodePacked("Supplier", Strings.toString(i + 1))) - ); - fillUserBalances(suppliers[i]); - } - supplier1 = suppliers[0]; - supplier2 = suppliers[1]; - supplier3 = suppliers[2]; - - for (uint256 i = 0; i < 3; i++) { - borrowers.push(new User(morpho)); - hevm.label( - address(borrowers[i]), - string(abi.encodePacked("Borrower", Strings.toString(i + 1))) - ); - fillUserBalances(borrowers[i]); - } - - borrower1 = borrowers[0]; - borrower2 = borrowers[1]; - borrower3 = borrowers[2]; - } - - function fillUserBalances(User _user) internal { - for (uint256 i; i < tokens.length; i++) { - if (tokens[i] == wEth) { - deal(tokens[i], address(_user), uint256(5856057446759574251267521) / 2); // wEth totalSupply() returns a weird value on pinned block - } else { - deal(tokens[i], address(_user), ERC20(tokens[i]).totalSupply() / 2); - } - } - } - - function setContractsLabels() internal { - hevm.label(address(proxyAdmin), "ProxyAdmin"); - hevm.label(address(morphoImplV1), "MorphoImplV1"); - hevm.label(address(morpho), "Morpho"); - hevm.label(address(interestRatesManager), "InterestRatesManager"); - hevm.label(address(rewardsManager), "RewardsManager"); - hevm.label(address(morphoToken), "MorphoToken"); - hevm.label(address(comptroller), "Comptroller"); - hevm.label(address(oracle), "CompoundOracle"); - hevm.label(address(dumbOracle), "DumbOracle"); - hevm.label(address(incentivesVault), "IncentivesVault"); - hevm.label(address(treasuryVault), "TreasuryVault"); - hevm.label(address(lens), "Lens"); - } - - function createSigners(uint256 _nbOfSigners) internal { - while (borrowers.length < _nbOfSigners) { - borrowers.push(new User(morpho)); - fillUserBalances(borrowers[borrowers.length - 1]); - suppliers.push(new User(morpho)); - fillUserBalances(suppliers[suppliers.length - 1]); - } - } - - function createAndSetCustomPriceOracle() public returns (SimplePriceOracle) { - SimplePriceOracle customOracle = new SimplePriceOracle(); - - IAdminComptroller adminComptroller = IAdminComptroller(address(comptroller)); - hevm.prank(adminComptroller.admin()); - uint256 result = adminComptroller._setPriceOracle(customOracle); - require(result == 0); // No error - - for (uint256 i = 0; i < pools.length; i++) { - customOracle.setUnderlyingPrice(pools[i], oracle.getUnderlyingPrice(pools[i])); - } - return customOracle; - } - - function setDefaultMaxGasForMatchingHelper( - uint64 _supply, - uint64 _borrow, - uint64 _withdraw, - uint64 _repay - ) public { - Types.MaxGasForMatching memory newMaxGas = Types.MaxGasForMatching({ - supply: _supply, - borrow: _borrow, - withdraw: _withdraw, - repay: _repay - }); - morpho.setDefaultMaxGasForMatching(newMaxGas); - } - - function move1000BlocksForward(address _marketAddress) public { - hevm.roll(block.number + 1_000); - hevm.warp(block.timestamp + 13 * 1_000); // mainnet block time is around 13 sec - morpho.updateP2PIndexes(_marketAddress); - } - - /// @notice Computes and returns peer-to-peer rates for a specific market (without taking into account deltas !). - /// @param _poolToken The market address. - /// @return p2pSupplyRate_ The market's supply rate in peer-to-peer (in ray). - /// @return p2pBorrowRate_ The market's borrow rate in peer-to-peer (in ray). - function getApproxBPYs(address _poolToken) - public - view - returns (uint256 p2pSupplyRate_, uint256 p2pBorrowRate_) - { - ICToken cToken = ICToken(_poolToken); - - uint256 poolSupplyBPY = cToken.supplyRatePerBlock(); - uint256 poolBorrowBPY = cToken.borrowRatePerBlock(); - (uint256 reserveFactor, uint256 p2pIndexCursor) = morpho.marketParameters(_poolToken); - - // rate = 2/3 * poolSupplyRate + 1/3 * poolBorrowRate. - uint256 rate = ((10_000 - p2pIndexCursor) * - poolSupplyBPY + - p2pIndexCursor * - poolBorrowBPY) / 10_000; - - p2pSupplyRate_ = rate - (reserveFactor * (rate - poolSupplyBPY)) / 10_000; - p2pBorrowRate_ = rate + (reserveFactor * (poolBorrowBPY - rate)) / 10_000; - } - - /// @notice Returns the underlying for a given market. - /// @param _poolToken The address of the market. - function getUnderlying(address _poolToken) internal view returns (address) { - if (_poolToken == cEth) - // cETH has no underlying() function. - return wEth; - else return ICToken(_poolToken).underlying(); - } - - function getAsset(uint8 _asset) internal view returns (address asset, address underlying) { - asset = pools[_asset % pools.length]; - underlying = getUnderlying(asset); - } - - /// @notice Checks morpho will not revert because of Compound rounding the amount to 0. - /// @param underlying Address of the underlying to supply. - /// @param amount To check. - function assumeSupplyAmountIsCorrect(address underlying, uint256 amount) internal { - hevm.assume(amount > 0); - // All the signers have the same balance at the beginning of a test. - hevm.assume(amount <= ERC20(underlying).balanceOf(address(supplier1))); - } - - /// @notice A borrow amount can be too high on compound due to governance or unsufficient supply. - /// @param market Address of the CToken. - /// @param amount To check. - function assumeBorrowAmountIsCorrect(address market, uint256 amount) internal { - hevm.assume(amount <= ICToken(market).getCash()); - hevm.assume(amount > 0); - uint256 borrowCap = comptroller.borrowCaps(market); - if (borrowCap != 0) hevm.assume(amount <= borrowCap); - } - - /// @notice Ensures the amount used for the liquidation is correct. - /// @param amount Considered for the liquidation. - function assumeLiquidateAmountIsCorrect(uint256 amount) internal { - hevm.assume(amount > 0); - } - - /// @notice Ensures the amount used for the repay is correct. - /// @param amount Considered for the repay. - function assumeRepayAmountIsCorrect(address underlying, uint256 amount) internal { - hevm.assume(amount > 0); - // All the signers have the same balance at the beginning of a test. - hevm.assume(amount <= ERC20(underlying).balanceOf(address(supplier1))); - } - - /// @notice Make sure the amount used for the withdraw is correct. - /// @param market Address of the CToken. - /// @param amount Considered for the repay. - function assumeWithdrawAmountIsCorrect(address market, uint256 amount) internal { - hevm.assume(amount.div(ICToken(market).exchangeRateCurrent()) > 0); - } - - function moveOneBlockForwardBorrowRepay() public { - hevm.roll(block.number + 1); - } -} From 2b61c944552e8e4a756fff111f1040087aa279b0 Mon Sep 17 00:00:00 2001 From: MerlinEgalite Date: Fri, 11 Nov 2022 13:02:33 +0100 Subject: [PATCH 03/11] =?UTF-8?q?=F0=9F=94=A7=20Update=20makefile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Makefile b/Makefile index 3c8e47680..a39880583 100644 --- a/Makefile +++ b/Makefile @@ -98,11 +98,6 @@ lcov-html: @echo Transforming the lcov coverage report into html @genhtml lcov.info -o coverage -fuzz: - $(eval FOUNDRY_TEST=test-foundry/fuzzing/${PROTOCOL}/) - @echo Running all Morpho-${PROTOCOL} fuzzing tests on "${NETWORK}" at block "${FOUNDRY_FORK_BLOCK_NUMBER}" with seed "${FOUNDRY_FUZZ_SEED}" - @forge test -vv - gas-report: @echo Creating gas report for Morpho-${PROTOCOL} on "${NETWORK}" at block "${FOUNDRY_FORK_BLOCK_NUMBER}" with seed "${FOUNDRY_FUZZ_SEED}" @forge test --gas-report From 7d80f8fadb566b9e3be0adf29fdcc864ae6b63aa Mon Sep 17 00:00:00 2001 From: MerlinEgalite Date: Fri, 11 Nov 2022 13:06:38 +0100 Subject: [PATCH 04/11] =?UTF-8?q?=E2=9A=B0=EF=B8=8F=20Remove=20rewards=20m?= =?UTF-8?q?anager=20tests=20on=20Aave=20V2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/eth-mainnet/aave-v2/Config.sol | 3 - contracts/aave-v2/RewardsManager.sol | 327 -------------- .../RewardsManagerOnMainnetAndAvalanche.sol | 36 -- .../RewardsManagerOnPolygon.sol | 34 -- scripts/aave-v2/Deploy.s.sol | 13 - test-foundry/aave-v2/TestGovernance.t.sol | 8 +- test-foundry/aave-v2/TestRewards.t.sol | 427 ------------------ test-foundry/aave-v2/TestUpgradeable.t.sol | 46 -- test-foundry/aave-v2/helpers/User.sol | 3 - test-foundry/aave-v2/setup/TestSetup.sol | 14 - test-foundry/prod/aave-v2/setup/TestSetup.sol | 5 - 11 files changed, 3 insertions(+), 913 deletions(-) delete mode 100644 contracts/aave-v2/RewardsManager.sol delete mode 100644 contracts/aave-v2/rewards-managers/RewardsManagerOnMainnetAndAvalanche.sol delete mode 100644 contracts/aave-v2/rewards-managers/RewardsManagerOnPolygon.sol delete mode 100644 test-foundry/aave-v2/TestRewards.t.sol diff --git a/config/eth-mainnet/aave-v2/Config.sol b/config/eth-mainnet/aave-v2/Config.sol index 1969099f5..ee91eafce 100644 --- a/config/eth-mainnet/aave-v2/Config.sol +++ b/config/eth-mainnet/aave-v2/Config.sol @@ -9,7 +9,6 @@ import {IIncentivesVault} from "@contracts/aave-v2/interfaces/IIncentivesVault.s import {IEntryPositionsManager} from "@contracts/aave-v2/interfaces/IEntryPositionsManager.sol"; import {IExitPositionsManager} from "@contracts/aave-v2/interfaces/IExitPositionsManager.sol"; import {IInterestRatesManager} from "@contracts/aave-v2/interfaces/IInterestRatesManager.sol"; -import {IRewardsManager} from "@contracts/aave-v2/interfaces/IRewardsManager.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; @@ -58,11 +57,9 @@ contract Config is BaseConfig { Lens public lensImplV1; Morpho public morphoImplV1; - IRewardsManager public rewardsManagerImplV1; Lens public lens; Morpho public morpho; - IRewardsManager public rewardsManager; IIncentivesVault public incentivesVault; IEntryPositionsManager public entryPositionsManager; IExitPositionsManager public exitPositionsManager; diff --git a/contracts/aave-v2/RewardsManager.sol b/contracts/aave-v2/RewardsManager.sol deleted file mode 100644 index cafffa880..000000000 --- a/contracts/aave-v2/RewardsManager.sol +++ /dev/null @@ -1,327 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity 0.8.13; - -import "./interfaces/aave/IAaveIncentivesController.sol"; -import "./interfaces/aave/IScaledBalanceToken.sol"; -import "./interfaces/aave/ILendingPool.sol"; -import "./interfaces/IGetterUnderlyingAsset.sol"; -import "./interfaces/IRewardsManager.sol"; -import "./interfaces/IMorpho.sol"; - -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -/// @title RewardsManager. -/// @author Morpho Labs. -/// @custom:contact security@morpho.xyz -/// @notice This abstract contract is a base for rewards managers managing the rewards from the Aave protocol. -abstract contract RewardsManager is IRewardsManager, OwnableUpgradeable { - /// STRUCTS /// - - struct LocalAssetData { - uint256 lastIndex; // The last index for the given market. - uint256 lastUpdateTimestamp; // The last time the index has been updated for the given market. - mapping(address => uint256) userIndex; // The current index for a given user. - } - - /// STORAGE /// - - mapping(address => uint256) public userUnclaimedRewards; // The unclaimed rewards of the user. - mapping(address => LocalAssetData) public localAssetData; // The local data related to a given market. - - IMorpho public morpho; - ILendingPool public pool; - - /// EVENTS /// - - /// @notice Emitted when rewards of an asset are accrued on behalf of a user. - /// @param _asset The address of the incentivized asset. - /// @param _user The address of the user that rewards are accrued on behalf of. - /// @param _assetIndex The index of the asset distribution. - /// @param _userIndex The index of the asset distribution on behalf of the user. - /// @param _rewardsAccrued The amount of rewards accrued. - event Accrued( - address indexed _asset, - address indexed _user, - uint256 _assetIndex, - uint256 _userIndex, - uint256 _rewardsAccrued - ); - - /// ERRORS /// - - /// @notice Thrown when only the main Morpho contract can call the function. - error OnlyMorpho(); - - /// @notice Thrown when an invalid asset is passed to accrue rewards. - error InvalidAsset(); - - /// MODIFIERS /// - - /// @notice Prevents a user to call function allowed for the main Morpho contract only. - modifier onlyMorpho() { - if (msg.sender != address(morpho)) revert OnlyMorpho(); - _; - } - - /// CONSTRUCTOR /// - - /// @notice Constructs the contract. - /// @dev The contract is automatically marked as initialized when deployed so that nobody can highjack the implementation contract. - constructor() initializer {} - - /// UPGRADE /// - - /// @notice Initializes the RewardsManager contract. - /// @param _morpho The address of Morpho's main contract's proxy. - function initialize(address _morpho) external initializer { - __Ownable_init(); - - morpho = IMorpho(_morpho); - pool = ILendingPool(morpho.pool()); - } - - /// EXTERNAL /// - - /// @notice Accrues unclaimed rewards for the given assets and returns the total unclaimed rewards. - /// @param _aaveIncentivesController The incentives controller used to query rewards. - /// @param _assets The assets for which to accrue rewards (aToken or variable debt token). - /// @param _user The address of the user. - /// @return unclaimedRewards The unclaimed rewards claimed by the user. - function claimRewards( - IAaveIncentivesController _aaveIncentivesController, - address[] calldata _assets, - address _user - ) external override onlyMorpho returns (uint256 unclaimedRewards) { - unclaimedRewards = _accrueUserUnclaimedRewards(_aaveIncentivesController, _assets, _user); - userUnclaimedRewards[_user] = 0; - } - - /// @notice Updates the unclaimed rewards of an user. - /// @param _aaveIncentivesController The incentives controller used to query rewards. - /// @param _user The address of the user. - /// @param _asset The address of the reference asset of the distribution (aToken or variable debt token). - /// @param _userBalance The user balance of tokens in the distribution. - /// @param _totalBalance The total balance of tokens in the distribution. - function updateUserAssetAndAccruedRewards( - IAaveIncentivesController _aaveIncentivesController, - address _user, - address _asset, - uint256 _userBalance, - uint256 _totalBalance - ) external onlyMorpho { - userUnclaimedRewards[_user] += _updateUserAsset( - _aaveIncentivesController, - _user, - _asset, - _userBalance, - _totalBalance - ); - } - - /// @notice Returns the index of the `_user` for a given `_asset`. - /// @param _asset The address of the reference asset of the distribution (aToken or variable debt token). - /// @param _user The address of the user. - /// @return The index of the user. - function getUserIndex(address _asset, address _user) external view override returns (uint256) { - return localAssetData[_asset].userIndex[_user]; - } - - /// @notice Get the unclaimed rewards for the given assets and returns the total unclaimed rewards. - /// @param _assets The assets for which to accrue rewards (aToken or variable debt token). - /// @param _user The address of the user. - /// @return unclaimedRewards The user unclaimed rewards. - function getUserUnclaimedRewards(address[] calldata _assets, address _user) - external - view - override - returns (uint256 unclaimedRewards) - { - unclaimedRewards = userUnclaimedRewards[_user]; - - for (uint256 i; i < _assets.length; ) { - address asset = _assets[i]; - DataTypes.ReserveData memory reserve = pool.getReserveData( - IGetterUnderlyingAsset(asset).UNDERLYING_ASSET_ADDRESS() - ); - uint256 userBalance; - if (asset == reserve.aTokenAddress) - userBalance = morpho.supplyBalanceInOf(reserve.aTokenAddress, _user).onPool; - else if (asset == reserve.variableDebtTokenAddress) - userBalance = morpho.borrowBalanceInOf(reserve.aTokenAddress, _user).onPool; - else revert InvalidAsset(); - - uint256 totalBalance = IScaledBalanceToken(asset).scaledTotalSupply(); - - unclaimedRewards += _getUserAsset(_user, asset, userBalance, totalBalance); - - unchecked { - ++i; - } - } - } - - /// INTERNAL /// - - /// @notice Accrues unclaimed rewards for the given assets and returns the total unclaimed rewards. - /// @param _aaveIncentivesController The incentives controller used to query rewards. - /// @param _assets The assets for which to accrue rewards (aToken or variable debt token). - /// @param _user The address of the user. - /// @return unclaimedRewards The user unclaimed rewards. - function _accrueUserUnclaimedRewards( - IAaveIncentivesController _aaveIncentivesController, - address[] calldata _assets, - address _user - ) internal returns (uint256 unclaimedRewards) { - unclaimedRewards = userUnclaimedRewards[_user]; - uint256 assetsLength = _assets.length; - - for (uint256 i; i < assetsLength; ) { - address asset = _assets[i]; - DataTypes.ReserveData memory reserve = pool.getReserveData( - IGetterUnderlyingAsset(asset).UNDERLYING_ASSET_ADDRESS() - ); - uint256 userBalance; - if (asset == reserve.aTokenAddress) - userBalance = morpho.supplyBalanceInOf(reserve.aTokenAddress, _user).onPool; - else if (asset == reserve.variableDebtTokenAddress) - userBalance = morpho.borrowBalanceInOf(reserve.aTokenAddress, _user).onPool; - else revert InvalidAsset(); - - uint256 totalBalance = IScaledBalanceToken(asset).scaledTotalSupply(); - - unclaimedRewards += _updateUserAsset( - _aaveIncentivesController, - _user, - asset, - userBalance, - totalBalance - ); - - unchecked { - ++i; - } - } - - userUnclaimedRewards[_user] = unclaimedRewards; - } - - /// @dev Updates asset's data. - /// @param _aaveIncentivesController The incentives controller used to query rewards. - /// @param _asset The address of the reference asset of the distribution (aToken or variable debt token). - /// @param _totalBalance The total balance of tokens in the distribution. - function _updateAsset( - IAaveIncentivesController _aaveIncentivesController, - address _asset, - uint256 _totalBalance - ) internal returns (uint256 oldIndex, uint256 newIndex) { - (oldIndex, newIndex) = _getAssetIndex(_aaveIncentivesController, _asset, _totalBalance); - if (oldIndex != newIndex) { - localAssetData[_asset].lastUpdateTimestamp = block.timestamp; - localAssetData[_asset].lastIndex = newIndex; - } - } - - /// @dev Updates the state of a user in a distribution. - /// @param _aaveIncentivesController The incentives controller used to query rewards. - /// @param _user The address of the user. - /// @param _asset The address of the reference asset of the distribution (aToken or variable debt token). - /// @param _userBalance The user balance of tokens in the distribution. - /// @param _totalBalance The total balance of tokens in the distribution. - /// @return accruedRewards The accrued rewards for the user until the moment for this asset. - function _updateUserAsset( - IAaveIncentivesController _aaveIncentivesController, - address _user, - address _asset, - uint256 _userBalance, - uint256 _totalBalance - ) internal returns (uint256 accruedRewards) { - uint256 formerUserIndex = localAssetData[_asset].userIndex[_user]; - (, uint256 newIndex) = _updateAsset(_aaveIncentivesController, _asset, _totalBalance); - - if (formerUserIndex != newIndex) { - if (_userBalance != 0) {} - accruedRewards = _getRewards(_userBalance, newIndex, formerUserIndex); - - localAssetData[_asset].userIndex[_user] = newIndex; - emit Accrued(_asset, _user, newIndex, formerUserIndex, accruedRewards); - } - } - - /// @dev Gets the state of a user in a distribution. - /// @dev This function is the equivalent of _updateUserAsset but as a view. - /// @param _user The address of the user. - /// @param _asset The address of the reference asset of the distribution (aToken or variable debt token). - /// @param _userBalance The user balance of tokens in the distribution. - /// @param _totalBalance The total balance of tokens in the distribution. - /// @return accruedRewards The accrued rewards for the user until the moment for this asset. - function _getUserAsset( - address _user, - address _asset, - uint256 _userBalance, - uint256 _totalBalance - ) internal view returns (uint256 accruedRewards) { - uint256 formerUserIndex = localAssetData[_asset].userIndex[_user]; - (, uint256 newIndex) = _getAssetIndex( - morpho.aaveIncentivesController(), - _asset, - _totalBalance - ); - - if (formerUserIndex != newIndex && _userBalance != 0) - accruedRewards = _getRewards(_userBalance, newIndex, formerUserIndex); - } - - /// @dev Computes and returns the next value of a specific distribution index. - /// @param _aaveIncentivesController The incentives controller used to query rewards. - /// @param _currentIndex The current index of the distribution. - /// @param _emissionPerSecond The total rewards distributed per second per asset unit, on the distribution. - /// @param _lastUpdateTimestamp The last moment this distribution was updated. - /// @param _totalBalance The total balance of tokens in the distribution. - /// @return The new index. - function _computeIndex( - IAaveIncentivesController _aaveIncentivesController, - uint256 _currentIndex, - uint256 _emissionPerSecond, - uint256 _lastUpdateTimestamp, - uint256 _totalBalance - ) internal view returns (uint256) { - uint256 distributionEnd = _aaveIncentivesController.DISTRIBUTION_END(); - uint256 currentTimestamp = block.timestamp; - - if ( - _lastUpdateTimestamp == currentTimestamp || - _emissionPerSecond == 0 || - _totalBalance == 0 || - _lastUpdateTimestamp >= distributionEnd - ) return _currentIndex; - - if (currentTimestamp > distributionEnd) currentTimestamp = distributionEnd; - uint256 timeDelta = currentTimestamp - _lastUpdateTimestamp; - return ((_emissionPerSecond * timeDelta * 1e18) / _totalBalance) + _currentIndex; - } - - /// @dev Computes and returns the rewards on a distribution. - /// @param _userBalance The user balance of tokens in the distribution. - /// @param _reserveIndex The current index of the distribution. - /// @param _userIndex The index stored for the user, representing his staking moment. - /// @return The rewards. - function _getRewards( - uint256 _userBalance, - uint256 _reserveIndex, - uint256 _userIndex - ) internal pure returns (uint256) { - return (_userBalance * (_reserveIndex - _userIndex)) / 1e18; - } - - /// @dev Returns the next reward index. - /// @param _aaveIncentivesController The incentives controller used to query rewards. - /// @param _asset The address of the reference asset of the distribution (aToken or variable debt token). - /// @param _totalBalance The total balance of tokens in the distribution. - /// @return oldIndex The old distribution index. - /// @return newIndex The new distribution index. - function _getAssetIndex( - IAaveIncentivesController _aaveIncentivesController, - address _asset, - uint256 _totalBalance - ) internal view virtual returns (uint256 oldIndex, uint256 newIndex); -} diff --git a/contracts/aave-v2/rewards-managers/RewardsManagerOnMainnetAndAvalanche.sol b/contracts/aave-v2/rewards-managers/RewardsManagerOnMainnetAndAvalanche.sol deleted file mode 100644 index 692390925..000000000 --- a/contracts/aave-v2/rewards-managers/RewardsManagerOnMainnetAndAvalanche.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity 0.8.13; - -import "../RewardsManager.sol"; - -/// @title RewardsManagerOnMainnetAndAvalanche. -/// @author Morpho Labs. -/// @custom:contact security@morpho.xyz -/// @notice This contract is used to manage the rewards from the Aave protocol on Mainnet or Avalanche. -contract RewardsManagerOnMainnetAndAvalanche is RewardsManager { - /// @inheritdoc RewardsManager - function _getAssetIndex( - IAaveIncentivesController _aaveIncentivesController, - address _asset, - uint256 _totalBalance - ) internal view override returns (uint256 oldIndex, uint256 newIndex) { - if (localAssetData[_asset].lastUpdateTimestamp == block.timestamp) - oldIndex = newIndex = localAssetData[_asset].lastIndex; - else { - ( - uint256 oldIndexOnAave, - uint256 emissionPerSecond, - uint256 lastTimestampOnAave - ) = _aaveIncentivesController.getAssetData(_asset); - - oldIndex = localAssetData[_asset].lastIndex; - newIndex = _computeIndex( - _aaveIncentivesController, - oldIndexOnAave, - emissionPerSecond, - lastTimestampOnAave, - _totalBalance - ); - } - } -} diff --git a/contracts/aave-v2/rewards-managers/RewardsManagerOnPolygon.sol b/contracts/aave-v2/rewards-managers/RewardsManagerOnPolygon.sol deleted file mode 100644 index 3703ca7e6..000000000 --- a/contracts/aave-v2/rewards-managers/RewardsManagerOnPolygon.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity 0.8.13; - -import "../RewardsManager.sol"; - -/// @title RewardsManagerOnPolygon. -/// @author Morpho Labs. -/// @custom:contact security@morpho.xyz -/// @notice This contract is used to manage the rewards from the Aave protocol on Polygon. -contract RewardsManagerOnPolygon is RewardsManager { - /// @inheritdoc RewardsManager - function _getAssetIndex( - IAaveIncentivesController _aaveIncentivesController, - address _asset, - uint256 _totalBalance - ) internal view override returns (uint256 oldIndex, uint256 newIndex) { - if (localAssetData[_asset].lastUpdateTimestamp == block.timestamp) - oldIndex = newIndex = localAssetData[_asset].lastIndex; - else { - IAaveIncentivesController.AssetData memory assetData = _aaveIncentivesController.assets( - _asset - ); - - oldIndex = localAssetData[_asset].lastIndex; - newIndex = _computeIndex( - _aaveIncentivesController, - assetData.index, - assetData.emissionPerSecond, - assetData.lastUpdateTimestamp, - _totalBalance - ); - } - } -} diff --git a/scripts/aave-v2/Deploy.s.sol b/scripts/aave-v2/Deploy.s.sol index 76df5693e..c1e3e3d20 100644 --- a/scripts/aave-v2/Deploy.s.sol +++ b/scripts/aave-v2/Deploy.s.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GNU AGPLv3 pragma solidity 0.8.13; -import "@contracts/aave-v2/interfaces/IRewardsManager.sol"; import "@contracts/aave-v2/interfaces/IIncentivesVault.sol"; import "@contracts/aave-v2/interfaces/IInterestRatesManager.sol"; import "@contracts/aave-v2/interfaces/IExitPositionsManager.sol"; @@ -12,7 +11,6 @@ import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.so import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import {InterestRatesManager} from "@contracts/aave-v2/InterestRatesManager.sol"; -import {RewardsManagerOnPolygon} from "@contracts/aave-v2/rewards-managers/RewardsManagerOnPolygon.sol"; import {EntryPositionsManager} from "@contracts/aave-v2/EntryPositionsManager.sol"; import {ExitPositionsManager} from "@contracts/aave-v2/ExitPositionsManager.sol"; import {Morpho} from "@contracts/aave-v2/Morpho.sol"; @@ -30,7 +28,6 @@ contract Deploy is Script, Config { IExitPositionsManager public exitPositionsManager; IInterestRatesManager public interestRatesManager; IIncentivesVault public incentivesVault; - RewardsManagerOnPolygon public rewardsManager; function run() external { vm.startBroadcast(); @@ -59,16 +56,6 @@ contract Deploy is Script, Config { ); morpho = Morpho(address(morphoProxy)); - // Deploy RewardsManager - IRewardsManager rewardsManagerImpl = new RewardsManagerOnPolygon(); - - TransparentUpgradeableProxy rewardsManagerProxy = new TransparentUpgradeableProxy( - address(rewardsManagerImpl), - address(proxyAdmin), - abi.encodeWithSelector(rewardsManagerImpl.initialize.selector, address(morphoProxy)) - ); - morpho.setRewardsManager(IRewardsManager(address(rewardsManagerProxy))); - // Deploy Lens lens = new Lens( address(morpho), diff --git a/test-foundry/aave-v2/TestGovernance.t.sol b/test-foundry/aave-v2/TestGovernance.t.sol index 23333d493..ba4e308cc 100644 --- a/test-foundry/aave-v2/TestGovernance.t.sol +++ b/test-foundry/aave-v2/TestGovernance.t.sol @@ -138,14 +138,12 @@ contract TestGovernance is TestSetup { } function testOnlyOwnerShouldSetRewardsManager() public { - IRewardsManager rewardsManagerV2 = new RewardsManagerOnMainnetAndAvalanche(); - hevm.prank(address(0)); hevm.expectRevert("Ownable: caller is not the owner"); - morpho.setRewardsManager(rewardsManagerV2); + morpho.setRewardsManager(IRewardsManager(address(1))); - morpho.setRewardsManager(rewardsManagerV2); - assertEq(address(morpho.rewardsManager()), address(rewardsManagerV2)); + morpho.setRewardsManager(IRewardsManager(address(1))); + assertEq(address(morpho.rewardsManager()), address(1)); } function testOnlyOwnerShouldSetInterestRatesManager() public { diff --git a/test-foundry/aave-v2/TestRewards.t.sol b/test-foundry/aave-v2/TestRewards.t.sol deleted file mode 100644 index 01caa7edc..000000000 --- a/test-foundry/aave-v2/TestRewards.t.sol +++ /dev/null @@ -1,427 +0,0 @@ -// SPDX-License-Identifier: GNU AGPLv3 -pragma solidity ^0.8.0; - -import "./setup/TestSetup.sol"; - -contract TestRewards is TestSetup { - function testShouldRevertWhenClaimRewardsIsPaused() public { - address[] memory aDaiInArray = new address[](1); - aDaiInArray[0] = aDai; - - morpho.setIsClaimRewardsPaused(true); - - hevm.expectRevert(abi.encodeWithSignature("ClaimRewardsPaused()")); - morpho.claimRewards(aDaiInArray, false); - } - - function testShouldClaimRightAmountOfSupplyRewards() public { - uint256 toSupply = 100 ether; - supplier1.approve(dai, toSupply); - supplier1.supply(aDai, toSupply); - uint256 balanceBefore = supplier1.balanceOf(REWARD_TOKEN); - - (uint256 index, , ) = aaveIncentivesController.getAssetData(aDai); - (, uint256 onPool) = morpho.supplyBalanceInOf(aDai, address(supplier1)); - uint256 userIndex = rewardsManager.getUserIndex(aDai, address(supplier1)); - address[] memory aDaiInArray = new address[](1); - aDaiInArray[0] = aDai; - uint256 unclaimedRewards = rewardsManager.getUserUnclaimedRewards( - aDaiInArray, - address(supplier1) - ); - - assertEq(index, userIndex, "user index wrong"); - assertEq(unclaimedRewards, 0, "unclaimed rewards should be 0"); - - supplier2.approve(dai, toSupply); - supplier2.supply(aDai, toSupply); - - hevm.warp(block.timestamp + 365 days); - supplier1.claimRewards(aDaiInArray, false); - - (index, , ) = aaveIncentivesController.getAssetData(aDai); - - uint256 expectedClaimed = (onPool * (index - userIndex)) / WAD; - uint256 balanceAfter = supplier1.balanceOf(REWARD_TOKEN); - uint256 expectedNewBalance = expectedClaimed + balanceBefore; - - assertEq(balanceAfter, expectedNewBalance, "balance after wrong"); - } - - function testShouldGetRightAmountOfSupplyRewards() public { - uint256 toSupply = 100 ether; - supplier1.approve(dai, toSupply); - supplier1.supply(aDai, toSupply); - - (uint256 index, , ) = aaveIncentivesController.getAssetData(aDai); - (, uint256 onPool) = morpho.supplyBalanceInOf(aDai, address(supplier1)); - uint256 userIndex = rewardsManager.getUserIndex(aDai, address(supplier1)); - address[] memory aDaiInArray = new address[](1); - aDaiInArray[0] = aDai; - uint256 unclaimedRewards = rewardsManager.getUserUnclaimedRewards( - aDaiInArray, - address(supplier1) - ); - - assertEq(index, userIndex, "user index wrong"); - assertEq(unclaimedRewards, 0, "unclaimed rewards should be 0"); - - supplier2.approve(dai, toSupply); - supplier2.supply(aDai, toSupply); - - hevm.warp(block.timestamp + 365 days); - unclaimedRewards = rewardsManager.getUserUnclaimedRewards(aDaiInArray, address(supplier1)); - - supplier1.claimRewards(aDaiInArray, false); - (index, , ) = aaveIncentivesController.getAssetData(aDai); - - uint256 expectedClaimed = (onPool * (index - userIndex)) / WAD; - assertEq(unclaimedRewards, expectedClaimed); - } - - function testShouldClaimRightAmountOfBorrowRewards() public { - uint256 toSupply = 100 ether; - supplier1.approve(dai, toSupply); - supplier1.supply(aDai, toSupply); - supplier1.borrow(aUsdc, to6Decimals(50 ether)); - uint256 balanceBefore = supplier1.balanceOf(REWARD_TOKEN); - - (uint256 index, , ) = aaveIncentivesController.getAssetData(variableDebtUsdc); - (, uint256 onPool) = morpho.borrowBalanceInOf(aUsdc, address(supplier1)); - uint256 userIndex = rewardsManager.getUserIndex(variableDebtUsdc, address(supplier1)); - address[] memory variableDebtUsdcArray = new address[](1); - variableDebtUsdcArray[0] = variableDebtUsdc; - uint256 unclaimedRewards = rewardsManager.getUserUnclaimedRewards( - variableDebtUsdcArray, - address(supplier1) - ); - - assertEq(index, userIndex, "user index wrong"); - assertEq(unclaimedRewards, 0, "unclaimed rewards should be 0"); - - hevm.warp(block.timestamp + 365 days); - supplier1.claimRewards(variableDebtUsdcArray, false); - - (index, , ) = aaveIncentivesController.getAssetData(variableDebtUsdc); - uint256 expectedClaimed = (onPool * (index - userIndex)) / WAD; - uint256 balanceAfter = supplier1.balanceOf(REWARD_TOKEN); - uint256 expectedNewBalance = expectedClaimed + balanceBefore; - - assertEq(balanceAfter, expectedNewBalance, "balance after wrong"); - } - - function testShouldGetRightAmountOfBorrowRewards() public { - uint256 toSupply = 100 ether; - supplier1.approve(dai, toSupply); - supplier1.supply(aDai, toSupply); - supplier1.borrow(aUsdc, to6Decimals(50 ether)); - - (uint256 index, , ) = aaveIncentivesController.getAssetData(variableDebtUsdc); - (, uint256 onPool) = morpho.borrowBalanceInOf(aUsdc, address(supplier1)); - uint256 userIndex = rewardsManager.getUserIndex(variableDebtUsdc, address(supplier1)); - address[] memory variableDebtUsdcArray = new address[](1); - variableDebtUsdcArray[0] = variableDebtUsdc; - uint256 unclaimedRewards = rewardsManager.getUserUnclaimedRewards( - variableDebtUsdcArray, - address(supplier1) - ); - - assertEq(index, userIndex, "user index wrong"); - assertEq(unclaimedRewards, 0, "unclaimed rewards should be 0"); - - hevm.warp(block.timestamp + 365 days); - unclaimedRewards = rewardsManager.getUserUnclaimedRewards( - variableDebtUsdcArray, - address(supplier1) - ); - - supplier1.claimRewards(variableDebtUsdcArray, false); - (index, , ) = aaveIncentivesController.getAssetData(variableDebtUsdc); - - uint256 expectedClaimed = (onPool * (index - userIndex)) / WAD; - assertEq(unclaimedRewards, expectedClaimed); - } - - function testShouldClaimOnSeveralMarkets() public { - uint256 toSupply = 100 ether; - uint256 toBorrow = 50 * 1e6; - supplier1.approve(dai, toSupply); - supplier1.supply(aDai, toSupply); - supplier1.borrow(aUsdc, toBorrow); - uint256 rewardBalanceBefore = supplier1.balanceOf(REWARD_TOKEN); - - hevm.warp(block.timestamp + 365 days); - - address[] memory aDaiInArray = new address[](1); - aDaiInArray[0] = aDai; - supplier1.claimRewards(aDaiInArray, false); - uint256 rewardBalanceAfter1 = supplier1.balanceOf(REWARD_TOKEN); - assertGt(rewardBalanceAfter1, rewardBalanceBefore); - - address[] memory debtUsdcInArray = new address[](1); - debtUsdcInArray[0] = variableDebtUsdc; - supplier1.claimRewards(debtUsdcInArray, false); - uint256 rewardBalanceAfter2 = supplier1.balanceOf(REWARD_TOKEN); - assertGt(rewardBalanceAfter2, rewardBalanceAfter1); - } - - function testShouldNotBePossibleToClaimRewardsOnOtherMarket() public { - uint256 toSupply = 100 ether; - uint256 toSupply2 = 50 * 1e6; - - uint256 balanceBefore = supplier1.balanceOf(REWARD_TOKEN); - supplier1.approve(dai, toSupply); - supplier1.supply(aDai, toSupply); - supplier2.approve(usdc, toSupply2); - supplier2.supply(aUsdc, toSupply2); - - hevm.warp(block.timestamp + 365 days); - - address[] memory aUsdcInArray = new address[](1); - aUsdcInArray[0] = aUsdc; - - assertEq(supplier1.claimRewards(aUsdcInArray, false), 0); - - uint256 balanceAfter = supplier1.balanceOf(REWARD_TOKEN); - assertEq(balanceAfter, balanceBefore); - } - - function testShouldClaimRewardsOnSeveralMarketsAtOnce() public { - uint256 toSupply = 100 ether; - uint256 toBorrow = 50 * 1e6; - supplier1.approve(dai, toSupply); - supplier1.supply(aDai, toSupply); - supplier1.borrow(aUsdc, toBorrow); - uint256 rewardBalanceBefore = supplier1.balanceOf(REWARD_TOKEN); - - hevm.warp(block.timestamp + 365 days); - - address[] memory aDaiInArray = new address[](1); - aDaiInArray[0] = aDai; - - address[] memory tokensInArray = new address[](2); - tokensInArray[0] = aDai; - tokensInArray[1] = variableDebtUsdc; - - uint256 unclaimedRewardsForDaiView = rewardsManager.getUserUnclaimedRewards( - aDaiInArray, - address(supplier1) - ); - uint256 unclaimedRewardsForDai = rewardsManager.getUserUnclaimedRewards( - aDaiInArray, - address(supplier1) - ); - assertEq(unclaimedRewardsForDaiView, unclaimedRewardsForDai); - - uint256 allUnclaimedRewardsView = rewardsManager.getUserUnclaimedRewards( - tokensInArray, - address(supplier1) - ); - uint256 allUnclaimedRewards = rewardsManager.getUserUnclaimedRewards( - tokensInArray, - address(supplier1) - ); - assertEq(allUnclaimedRewardsView, allUnclaimedRewards); - assertGt(allUnclaimedRewards, unclaimedRewardsForDai); - - supplier1.claimRewards(tokensInArray, false); - uint256 rewardBalanceAfter = supplier1.balanceOf(REWARD_TOKEN); - - assertGt(rewardBalanceAfter, rewardBalanceBefore); - - allUnclaimedRewardsView = rewardsManager.getUserUnclaimedRewards( - tokensInArray, - address(supplier1) - ); - allUnclaimedRewards = rewardsManager.getUserUnclaimedRewards( - tokensInArray, - address(supplier1) - ); - assertEq(allUnclaimedRewardsView, allUnclaimedRewards); - assertEq(allUnclaimedRewards, 0); - - uint256 protocolUnclaimedRewards = aaveIncentivesController.getRewardsBalance( - tokensInArray, - address(morpho) - ); - - assertEq(protocolUnclaimedRewards, 0); - } - - function testUsersShouldClaimRewardsIndependently() public { - interactWithAave(); - interactWithMorpho(); - - uint256[4] memory balanceBefore; - balanceBefore[1] = IERC20(REWARD_TOKEN).balanceOf(address(supplier1)); - balanceBefore[2] = IERC20(REWARD_TOKEN).balanceOf(address(supplier2)); - balanceBefore[3] = IERC20(REWARD_TOKEN).balanceOf(address(supplier3)); - - hevm.warp(block.timestamp + 365 days); - - address[] memory tokensInArray = new address[](2); - tokensInArray[0] = aDai; - tokensInArray[1] = variableDebtUsdc; - supplier1.claimRewards(tokensInArray, false); - supplier2.claimRewards(tokensInArray, false); - supplier3.claimRewards(tokensInArray, false); - - uint256[4] memory balanceAfter; - balanceAfter[1] = IERC20(REWARD_TOKEN).balanceOf(address(supplier1)); - balanceAfter[2] = IERC20(REWARD_TOKEN).balanceOf(address(supplier2)); - balanceAfter[3] = IERC20(REWARD_TOKEN).balanceOf(address(supplier3)); - - supplier1.aaveClaimRewards(tokensInArray); - supplier2.aaveClaimRewards(tokensInArray); - supplier3.aaveClaimRewards(tokensInArray); - - uint256[4] memory balanceAfterAave; - balanceAfterAave[1] = IERC20(REWARD_TOKEN).balanceOf(address(supplier1)); - balanceAfterAave[2] = IERC20(REWARD_TOKEN).balanceOf(address(supplier2)); - balanceAfterAave[3] = IERC20(REWARD_TOKEN).balanceOf(address(supplier3)); - - uint256[4] memory claimedFromAave; - claimedFromAave[1] = balanceAfterAave[1] - balanceAfter[1]; - claimedFromAave[2] = balanceAfterAave[2] - balanceAfter[2]; - claimedFromAave[3] = balanceAfterAave[3] - balanceAfter[3]; - - uint256[4] memory claimedFromMorpho; - claimedFromMorpho[1] = balanceAfter[1] - balanceBefore[1]; - claimedFromMorpho[2] = balanceAfter[2] - balanceBefore[2]; - claimedFromMorpho[3] = balanceAfter[3] - balanceBefore[3]; - assertEq(claimedFromAave[1], claimedFromMorpho[1]); - assertEq(claimedFromAave[2], claimedFromMorpho[2]); - assertEq(claimedFromAave[3], claimedFromMorpho[3]); - - assertGt(balanceAfter[1], balanceBefore[1]); - assertGt(balanceAfter[2], balanceBefore[2]); - assertGt(balanceAfter[3], balanceBefore[3]); - - uint256 unclaimedRewards1 = rewardsManager.getUserUnclaimedRewards( - tokensInArray, - address(supplier1) - ); - uint256 unclaimedRewards2 = rewardsManager.getUserUnclaimedRewards( - tokensInArray, - address(supplier2) - ); - uint256 unclaimedRewards3 = rewardsManager.getUserUnclaimedRewards( - tokensInArray, - address(supplier3) - ); - - assertEq(unclaimedRewards1, 0); - assertEq(unclaimedRewards2, 0); - assertEq(unclaimedRewards3, 0); - - uint256 protocolUnclaimedRewards = aaveIncentivesController.getRewardsBalance( - tokensInArray, - address(morpho) - ); - - assertApproxEqAbs(protocolUnclaimedRewards, 0, 5); - } - - function interactWithAave() internal { - uint256 toSupply = 100 ether; - uint256 toBorrow = 50 * 1e6; - - supplier1.aaveSupply(dai, toSupply); - supplier1.aaveBorrow(usdc, toBorrow); - supplier2.aaveSupply(dai, toSupply); - supplier2.aaveBorrow(usdc, toBorrow); - supplier3.aaveSupply(dai, toSupply); - supplier3.aaveBorrow(usdc, toBorrow); - } - - function interactWithMorpho() internal { - uint256 toSupply = 100 ether; - uint256 toBorrow = 50 * 1e6; - - supplier1.approve(dai, toSupply); - supplier2.approve(dai, toSupply); - supplier3.approve(dai, toSupply); - supplier1.supply(aDai, toSupply); - supplier1.borrow(aUsdc, toBorrow); - supplier2.supply(aDai, toSupply); - supplier2.borrow(aUsdc, toBorrow); - supplier3.supply(aDai, toSupply); - supplier3.borrow(aUsdc, toBorrow); - } - - function testShouldClaimRewardsAndTradeForMorpkoTokens() public { - // 10% bonus. - incentivesVault.setBonus(1_000); - - uint256 toSupply = 100 ether; - supplier1.approve(dai, toSupply); - supplier1.supply(aDai, toSupply); - - (, uint256 onPool) = morpho.supplyBalanceInOf(aDai, address(supplier1)); - uint256 userIndex = rewardsManager.getUserIndex(aDai, address(supplier1)); - uint256 rewardBalanceBefore = supplier1.balanceOf(REWARD_TOKEN); - - address[] memory aDaiInArray = new address[](1); - aDaiInArray[0] = aDai; - - hevm.warp(block.timestamp + 365 days); - supplier1.claimRewards(aDaiInArray, true); - - (uint256 index, , ) = aaveIncentivesController.getAssetData(aDai); - uint256 expectedClaimed = (onPool * (index - userIndex)) / WAD; - uint256 expectedMorphoTokens = (expectedClaimed * 11_000) / 10_000; // 10% bonus with a dumb oracle 1:1 exchange from COMP to MORPHO. - - uint256 morphoBalance = supplier1.balanceOf(address(morphoToken)); - uint256 rewardBalanceAfter = supplier1.balanceOf(REWARD_TOKEN); - testEquality(morphoBalance, expectedMorphoTokens, "expected Morpho balance"); - testEquality(rewardBalanceBefore, rewardBalanceAfter, "expected reward balance"); - } - - function testShouldClaimTheSameAmountOfRewards() public { - uint256 smallAmount = 1 ether; - uint256 bigAmount = 10_000 ether; - - supplier1.approve(usdc, type(uint256).max); - supplier1.supply(aUsdc, to6Decimals(smallAmount)); - supplier2.approve(usdc, type(uint256).max); - supplier2.supply(aUsdc, to6Decimals(smallAmount)); - - move1YearForward(aUsdc); - - address[] memory markets = new address[](1); - markets[0] = aUsdc; - - uint256 unclaimedRewards1 = rewardsManager.getUserUnclaimedRewards( - markets, - address(supplier1) - ); - - // supplier2 tries to game the system by supplying a huge amount of tokens and withdrawing right after accruing its rewards. - supplier2.supply(aUsdc, to6Decimals(bigAmount)); - uint256 unclaimedRewards2 = rewardsManager.getUserUnclaimedRewards( - markets, - address(supplier2) - ); - supplier2.withdraw(aUsdc, to6Decimals(bigAmount)); - - assertEq(unclaimedRewards1, unclaimedRewards2); - } - - function testFailShouldNotClaimRewardsWhenRewardsManagerIsAddressZero() public { - uint256 amount = 1 ether; - - supplier1.approve(usdc, type(uint256).max); - supplier1.supply(aUsdc, to6Decimals(amount)); - - // Set RewardsManager to address(0). - morpho.setRewardsManager(IRewardsManager(address(0))); - - move1YearForward(aUsdc); - - address[] memory markets = new address[](1); - markets[0] = aUsdc; - - // User tries to claim its rewards on Morpho. - supplier1.claimRewards(markets, false); - } -} diff --git a/test-foundry/aave-v2/TestUpgradeable.t.sol b/test-foundry/aave-v2/TestUpgradeable.t.sol index 9a5b926cc..e31dad535 100644 --- a/test-foundry/aave-v2/TestUpgradeable.t.sol +++ b/test-foundry/aave-v2/TestUpgradeable.t.sol @@ -48,52 +48,6 @@ contract TestUpgradeable is TestSetup { proxyAdmin.upgradeAndCall(morphoProxy, address(morphoImplV2), ""); } - function testUpgradeRewardsManager() public { - IRewardsManager rewardsManagerImplV2 = new RewardsManagerOnPolygon(); - - hevm.record(); - proxyAdmin.upgrade(rewardsManagerProxy, address(rewardsManagerImplV2)); - (, bytes32[] memory writes) = hevm.accesses(address(rewardsManager)); - - // 1 write for the implemention. - assertEq(writes.length, 1); - address newImplem = bytes32ToAddress( - hevm.load( - address(rewardsManagerProxy), - bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1) // Implementation slot. - ) - ); - assertEq(newImplem, address(rewardsManagerImplV2)); - } - - function testOnlyProxyOwnerCanUpgradeRewardsManager() public { - IRewardsManager rewardsManagerImplV2 = new RewardsManagerOnPolygon(); - - hevm.prank(address(supplier1)); - hevm.expectRevert("Ownable: caller is not the owner"); - proxyAdmin.upgrade(rewardsManagerProxy, address(rewardsManagerImplV2)); - - proxyAdmin.upgrade(rewardsManagerProxy, address(rewardsManagerImplV2)); - } - - function testOnlyProxyOwnerCanUpgradeAndCallRewardsManager() public { - IRewardsManager rewardsManagerImplV2 = new RewardsManagerOnPolygon(); - - hevm.prank(address(supplier1)); - hevm.expectRevert("Ownable: caller is not the owner"); - proxyAdmin.upgradeAndCall(rewardsManagerProxy, payable(address(rewardsManagerImplV2)), ""); - - // Revert for wrong data not wrong caller. - hevm.expectRevert("Address: low-level delegate call failed"); - proxyAdmin.upgradeAndCall(rewardsManagerProxy, payable(address(rewardsManagerImplV2)), ""); - } - - function testRewardsManagerImplementationsShouldBeInitialized() public { - // Test for RewardsManagerOnPolygon Implementation. - hevm.expectRevert("Initializable: contract is already initialized"); - rewardsManagerImplV1.initialize(address(morpho)); - } - function testPositionsManagerImplementationsShouldBeInitialized() public { Types.MaxGasForMatching memory defaultMaxGasForMatching = Types.MaxGasForMatching({ supply: 3e6, diff --git a/test-foundry/aave-v2/helpers/User.sol b/test-foundry/aave-v2/helpers/User.sol index a6e1e207b..e047643a0 100644 --- a/test-foundry/aave-v2/helpers/User.sol +++ b/test-foundry/aave-v2/helpers/User.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.0; import "@contracts/aave-v2/interfaces/aave/ILendingPool.sol"; -import "@contracts/aave-v2/interfaces/IRewardsManager.sol"; import "@contracts/aave-v2/Morpho.sol"; @@ -10,7 +9,6 @@ contract User { using SafeTransferLib for ERC20; Morpho internal morpho; - IRewardsManager internal rewardsManager; ILendingPool public pool; IAaveIncentivesController public aaveIncentivesController; @@ -182,7 +180,6 @@ contract User { function setMorphoAddresses(Morpho _morpho) public { morpho = _morpho; - rewardsManager = _morpho.rewardsManager(); pool = _morpho.pool(); aaveIncentivesController = _morpho.aaveIncentivesController(); } diff --git a/test-foundry/aave-v2/setup/TestSetup.sol b/test-foundry/aave-v2/setup/TestSetup.sol index 6716d2208..c1e4ac742 100644 --- a/test-foundry/aave-v2/setup/TestSetup.sol +++ b/test-foundry/aave-v2/setup/TestSetup.sol @@ -13,8 +13,6 @@ import "@morpho-dao/morpho-utils/math/WadRayMath.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "@contracts/aave-v2/libraries/Types.sol"; -import {RewardsManagerOnMainnetAndAvalanche} from "@contracts/aave-v2/rewards-managers/RewardsManagerOnMainnetAndAvalanche.sol"; -import {RewardsManagerOnPolygon} from "@contracts/aave-v2/rewards-managers/RewardsManagerOnPolygon.sol"; import {InterestRatesManager} from "@contracts/aave-v2/InterestRatesManager.sol"; import {IncentivesVault} from "@contracts/aave-v2/IncentivesVault.sol"; import {MatchingEngine} from "@contracts/aave-v2/MatchingEngine.sol"; @@ -94,15 +92,6 @@ contract TestSetup is Config, Utils { morpho.setTreasuryVault(address(treasuryVault)); morpho.setAaveIncentivesController(address(aaveIncentivesController)); - rewardsManagerImplV1 = new RewardsManagerOnMainnetAndAvalanche(); - rewardsManagerProxy = new TransparentUpgradeableProxy( - address(rewardsManagerImplV1), - address(proxyAdmin), - "" - ); - rewardsManager = IRewardsManager(address(rewardsManagerProxy)); - rewardsManager.initialize(address(morpho)); - /// Create markets /// createMarket(aDai); @@ -127,8 +116,6 @@ contract TestSetup is Config, Utils { morphoToken.transfer(address(incentivesVault), 1_000_000 ether); morpho.setIncentivesVault(incentivesVault); - morpho.setRewardsManager(rewardsManager); - lensImplV1 = new Lens(address(morpho)); lensProxy = new TransparentUpgradeableProxy(address(lensImplV1), address(proxyAdmin), ""); lens = Lens(address(lensProxy)); @@ -183,7 +170,6 @@ contract TestSetup is Config, Utils { function setContractsLabels() internal { hevm.label(address(morpho), "Morpho"); - hevm.label(address(rewardsManager), "RewardsManager"); hevm.label(address(morphoToken), "MorphoToken"); hevm.label(address(aaveIncentivesController), "AaveIncentivesController"); hevm.label(address(poolAddressesProvider), "PoolAddressesProvider"); diff --git a/test-foundry/prod/aave-v2/setup/TestSetup.sol b/test-foundry/prod/aave-v2/setup/TestSetup.sol index 61c87666e..f4449b71f 100644 --- a/test-foundry/prod/aave-v2/setup/TestSetup.sol +++ b/test-foundry/prod/aave-v2/setup/TestSetup.sol @@ -12,8 +12,6 @@ import "@morpho-dao/morpho-utils/math/PercentageMath.sol"; import "@rari-capital/solmate/src/utils/SafeTransferLib.sol"; import "@morpho-dao/morpho-utils/math/Math.sol"; -import {RewardsManagerOnMainnetAndAvalanche} from "@contracts/aave-v2/rewards-managers/RewardsManagerOnMainnetAndAvalanche.sol"; -import {RewardsManagerOnPolygon} from "@contracts/aave-v2/rewards-managers/RewardsManagerOnPolygon.sol"; import {InterestRatesManager} from "@contracts/aave-v2/InterestRatesManager.sol"; import {IncentivesVault} from "@contracts/aave-v2/IncentivesVault.sol"; import {MatchingEngine} from "@contracts/aave-v2/MatchingEngine.sol"; @@ -76,8 +74,6 @@ contract TestSetup is Config, Test { entryPositionsManager = morpho.entryPositionsManager(); exitPositionsManager = morpho.exitPositionsManager(); interestRatesManager = morpho.interestRatesManager(); - - rewardsManagerProxy = TransparentUpgradeableProxy(payable(address(rewardsManager))); } function initUsers() internal { @@ -119,7 +115,6 @@ contract TestSetup is Config, Test { vm.label(address(morphoImplV1), "MorphoImplV1"); vm.label(address(morpho), "Morpho"); vm.label(address(interestRatesManager), "InterestRatesManager"); - vm.label(address(rewardsManager), "RewardsManager"); vm.label(address(oracle), "Oracle"); vm.label(address(incentivesVault), "IncentivesVault"); vm.label(address(lens), "Lens"); From 7e8a5a92f4245d6f9a65369dabbe23b9fc560c14 Mon Sep 17 00:00:00 2001 From: MerlinEgalite Date: Fri, 11 Nov 2022 15:24:57 +0100 Subject: [PATCH 05/11] =?UTF-8?q?=E2=9C=85=20Fix=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test-foundry/aave-v2/TestLiquidate.t.sol | 6 ++-- test-foundry/aave-v2/TestPausableMarket.t.sol | 1 + test-foundry/aave-v2/TestRatesLens.t.sol | 2 +- test-foundry/aave-v2/TestRepay.t.sol | 4 +-- test-foundry/aave-v2/TestWithdraw.t.sol | 32 +++++++++++-------- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/test-foundry/aave-v2/TestLiquidate.t.sol b/test-foundry/aave-v2/TestLiquidate.t.sol index dc5816630..01ac0cabc 100644 --- a/test-foundry/aave-v2/TestLiquidate.t.sol +++ b/test-foundry/aave-v2/TestLiquidate.t.sol @@ -83,7 +83,7 @@ contract TestLiquidate is TestSetup { // Change Oracle SimplePriceOracle customOracle = createAndSetCustomPriceOracle(); - customOracle.setDirectPrice(usdc, (oracle.getAssetPrice(usdc) * 93) / 100); + customOracle.setDirectPrice(usdc, (oracle.getAssetPrice(usdc) * 95) / 100); // Liquidate uint256 toRepay = amount / 2; @@ -155,7 +155,7 @@ contract TestLiquidate is TestSetup { // Change Oracle. SimplePriceOracle customOracle = createAndSetCustomPriceOracle(); - customOracle.setDirectPrice(dai, (oracle.getAssetPrice(dai) * 93) / 100); + customOracle.setDirectPrice(dai, (oracle.getAssetPrice(dai) * 80) / 100); // Liquidate. uint256 toRepay = (borrowerDebt / 2); @@ -235,7 +235,7 @@ contract TestLiquidate is TestSetup { // Change Oracle. SimplePriceOracle customOracle = createAndSetCustomPriceOracle(); - customOracle.setDirectPrice(dai, (oracle.getAssetPrice(dai) * 93) / 100); + customOracle.setDirectPrice(dai, (oracle.getAssetPrice(dai) * 80) / 100); // Liquidate. uint256 toRepay = (borrowerDebt / 4); diff --git a/test-foundry/aave-v2/TestPausableMarket.t.sol b/test-foundry/aave-v2/TestPausableMarket.t.sol index d9f6f4374..dcb742702 100644 --- a/test-foundry/aave-v2/TestPausableMarket.t.sol +++ b/test-foundry/aave-v2/TestPausableMarket.t.sol @@ -72,6 +72,7 @@ contract TestPausableMarket is TestSetup { uint256 toLiquidate = toBorrow / 2; User liquidator = borrower3; liquidator.approve(usdc, toLiquidate); + vm.expectRevert(abi.encodeWithSignature("UnauthorisedLiquidate()")); liquidator.liquidate(aUsdc, aDai, address(supplier1), toLiquidate); supplier1.withdraw(aDai, 1); diff --git a/test-foundry/aave-v2/TestRatesLens.t.sol b/test-foundry/aave-v2/TestRatesLens.t.sol index 03c50eca2..f95c522ad 100644 --- a/test-foundry/aave-v2/TestRatesLens.t.sol +++ b/test-foundry/aave-v2/TestRatesLens.t.sol @@ -141,7 +141,7 @@ contract TestRatesLens is TestSetup { (uint256 p2pSupplyRate, , uint256 poolSupplyRate, ) = lens.getRatesPerYear(aDai); - assertApproxEqAbs(p2pSupplyRate, poolSupplyRate, 1); + assertApproxEqAbs(p2pSupplyRate, poolSupplyRate, 100); } function testBorrowRateShouldEqualPoolRateWithFullBorrowDelta() public { diff --git a/test-foundry/aave-v2/TestRepay.t.sol b/test-foundry/aave-v2/TestRepay.t.sol index ec54738ac..07d9e9c12 100644 --- a/test-foundry/aave-v2/TestRepay.t.sol +++ b/test-foundry/aave-v2/TestRepay.t.sol @@ -347,7 +347,7 @@ contract TestRepay is TestSetup { function testDeltaRepay() public { // Allows only 10 unmatch borrowers - setDefaultMaxGasForMatchingHelper(3e6, 3e6, 3e6, 1.2e6); + setDefaultMaxGasForMatchingHelper(3e6, 3e6, 3e6, 0.8e6); uint256 suppliedAmount = 1 ether; uint256 borrowedAmount = 20 * suppliedAmount; @@ -508,7 +508,7 @@ contract TestRepay is TestSetup { function testDeltaRepayAll() public { // Allows only 10 unmatch suppliers. - setDefaultMaxGasForMatchingHelper(3e6, 3e6, 3e6, 1.2e6); + setDefaultMaxGasForMatchingHelper(3e6, 3e6, 3e6, 0.8e6); uint256 suppliedAmount = 1 ether; uint256 borrowedAmount = 20 * suppliedAmount + 1e12; diff --git a/test-foundry/aave-v2/TestWithdraw.t.sol b/test-foundry/aave-v2/TestWithdraw.t.sol index c346b48c3..d8ae07950 100644 --- a/test-foundry/aave-v2/TestWithdraw.t.sol +++ b/test-foundry/aave-v2/TestWithdraw.t.sol @@ -128,7 +128,7 @@ contract TestWithdraw is TestSetup { // There are NMAX (or less) suppliers `onPool` available to replace him `inP2P`, they supply enough to cover for the withdrawn liquidity. First, his liquidity `onPool` is taken, his matched is replaced by NMAX (or less) suppliers up to his withdrawal amount. function testWithdraw3_2() public { // TODO: fix this. - deal(dai, address(morpho), 1); + deal(dai, address(morpho), 10); setDefaultMaxGasForMatchingHelper( type(uint64).max, @@ -370,11 +370,11 @@ contract TestWithdraw is TestSetup { function testDeltaWithdraw() public { // Allows only 10 unmatch borrowers - setDefaultMaxGasForMatchingHelper(3e6, 3e6, 1.2e6, 3e6); + setDefaultMaxGasForMatchingHelper(3e6, 3e6, 0.75e6, 3e6); uint256 borrowedAmount = 1 ether; uint256 collateral = 2 * borrowedAmount; - uint256 suppliedAmount = 20 * borrowedAmount + 7; + uint256 suppliedAmount = 20 * borrowedAmount + 20; uint256 expectedSupplyBalanceInP2P; // supplier1 and 20 borrowers are matched for suppliedAmount @@ -399,8 +399,8 @@ contract TestWithdraw is TestSetup { aDai, address(supplier1) ); - testEquality(onPoolSupplier, 0); - testEquality(inP2PSupplier, expectedSupplyBalanceInP2P); + testEquality(onPoolSupplier, 0, "on pool supplier"); + testEquality(inP2PSupplier, expectedSupplyBalanceInP2P, "in P2P supplier"); uint256 p2pBorrowIndex = morpho.p2pBorrowIndex(aDai); uint256 expectedBorrowBalanceInP2P = borrowedAmount.rayDiv(p2pBorrowIndex); @@ -526,7 +526,7 @@ contract TestWithdraw is TestSetup { function testDeltaWithdrawAll() public { // Allows only 10 unmatch borrowers - setDefaultMaxGasForMatchingHelper(3e6, 3e6, 1.2e6, 3e6); + setDefaultMaxGasForMatchingHelper(3e6, 3e6, 0.8e6, 3e6); uint256 borrowedAmount = 1 ether; uint256 collateral = 2 * borrowedAmount; @@ -547,8 +547,13 @@ contract TestWithdraw is TestSetup { for (uint256 i = 0; i < 20; i++) { (uint256 inP2P, uint256 onPool) = morpho.borrowBalanceInOf(aDai, address(borrowers[i])); - assertEq(inP2P, (borrowedAmount + i).rayDiv(morpho.p2pBorrowIndex(aDai)), "inP2P"); - assertEq(onPool, 0, "onPool"); + assertApproxEqAbs( + inP2P, + (borrowedAmount + i).rayDiv(morpho.p2pBorrowIndex(aDai)), + 1e4, + "inP2P" + ); + assertApproxEqAbs(onPool, 0, 1e4, "onPool"); } // Supplier withdraws max @@ -565,14 +570,15 @@ contract TestWithdraw is TestSetup { string.concat("onPool", Strings.toString(i)) ); } - for (uint256 i = 0; i < 10; i++) { + for (uint256 i; i < 10; i++) { (uint256 inP2P, uint256 onPool) = morpho.borrowBalanceInOf(aDai, address(borrowers[i])); - assertEq( + assertApproxEqAbs( inP2P, (borrowedAmount + i).rayDiv(morpho.p2pBorrowIndex(aDai)), + 1e2, string.concat("inP2P", Strings.toString(i)) ); - assertEq(onPool, 0, string.concat("onPool", Strings.toString(i))); + assertApproxEqAbs(onPool, 0, 1e2, string.concat("onPool", Strings.toString(i))); } ( @@ -586,14 +592,14 @@ contract TestWithdraw is TestSetup { assertApproxEqAbs( p2pBorrowDelta, (10 * borrowedAmount).rayDiv(pool.getReserveNormalizedVariableDebt(dai)), - 1e2, + 1e3, "p2pBorrowDelta" ); assertApproxEqAbs(p2pSupplyAmount, 0, 1, "p2pSupplyAmount"); assertApproxEqAbs( p2pBorrowAmount, (10 * borrowedAmount).rayDiv(morpho.p2pBorrowIndex(aDai)), - 1e2, + 1e3, "p2pBorrowAmount" ); From ef33666cbfd6fb9523abaf84f54cce297337a917 Mon Sep 17 00:00:00 2001 From: MerlinEgalite Date: Fri, 11 Nov 2022 18:14:55 +0100 Subject: [PATCH 06/11] =?UTF-8?q?=F0=9F=92=9A=20Fix=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-storage-check-aave-v2.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/ci-storage-check-aave-v2.yml b/.github/workflows/ci-storage-check-aave-v2.yml index 50d2e81d8..3786496da 100644 --- a/.github/workflows/ci-storage-check-aave-v2.yml +++ b/.github/workflows/ci-storage-check-aave-v2.yml @@ -41,8 +41,3 @@ jobs: uses: Rubilmax/foundry-storage-check@v2.1 with: contract: contracts/aave-v2/Morpho.sol:Morpho - - - name: Check RewardsManager storage layout - uses: Rubilmax/foundry-storage-check@v2.1 - with: - contract: contracts/aave-v2/RewardsManager.sol:RewardsManager From e683c652090ab069e667caf92671c7c0c6c6a0a6 Mon Sep 17 00:00:00 2001 From: MerlinEgalite Date: Fri, 11 Nov 2022 18:30:56 +0100 Subject: [PATCH 07/11] =?UTF-8?q?=F0=9F=94=A5=20Remove=20var?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/eth-mainnet/aave-v2/Config.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/config/eth-mainnet/aave-v2/Config.sol b/config/eth-mainnet/aave-v2/Config.sol index ee91eafce..d34087e77 100644 --- a/config/eth-mainnet/aave-v2/Config.sol +++ b/config/eth-mainnet/aave-v2/Config.sol @@ -53,7 +53,6 @@ contract Config is BaseConfig { TransparentUpgradeableProxy(payable(0x507fA343d0A90786d86C7cd885f5C49263A91FF4)); TransparentUpgradeableProxy public morphoProxy = TransparentUpgradeableProxy(payable(0x777777c9898D384F785Ee44Acfe945efDFf5f3E0)); - TransparentUpgradeableProxy public rewardsManagerProxy; Lens public lensImplV1; Morpho public morphoImplV1; From 7280cd10393a70ba01659ec351e1942eac0a4c5b Mon Sep 17 00:00:00 2001 From: patrick Date: Fri, 11 Nov 2022 13:17:34 -0500 Subject: [PATCH 08/11] Fix aave v2 ci --- .github/workflows/ci-storage-snapshot-check-aave-v2.yml | 2 +- Makefile | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-storage-snapshot-check-aave-v2.yml b/.github/workflows/ci-storage-snapshot-check-aave-v2.yml index b8ac9a760..97f279326 100644 --- a/.github/workflows/ci-storage-snapshot-check-aave-v2.yml +++ b/.github/workflows/ci-storage-snapshot-check-aave-v2.yml @@ -37,6 +37,6 @@ jobs: version: nightly - name: Run tests - run: make storage-layout-check + run: make storage-layout-check-no-rewards env: PROTOCOL: aave-v2 diff --git a/Makefile b/Makefile index a39880583..ce8e50e8e 100644 --- a/Makefile +++ b/Makefile @@ -120,6 +120,12 @@ storage-layout-generate: storage-layout-check: @./scripts/storage-layout.sh check snapshots/.storage-layout-${PROTOCOL} Morpho RewardsManager Lens +storage-layout-generate-no-rewards: + @./scripts/storage-layout.sh generate snapshots/.storage-layout-${PROTOCOL} Morpho Lens + +storage-layout-check-no-rewards: + @./scripts/storage-layout.sh check snapshots/.storage-layout-${PROTOCOL} Morpho Lens + config: @forge config From 57b310db5d65fa7e29da079367e14675b736bd7b Mon Sep 17 00:00:00 2001 From: MerlinEgalite Date: Fri, 11 Nov 2022 19:47:59 +0100 Subject: [PATCH 09/11] =?UTF-8?q?=F0=9F=92=9A=20Fix=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a39880583..29089a49c 100644 --- a/Makefile +++ b/Makefile @@ -115,10 +115,10 @@ single-% s-%: @forge test -vvvv --match-test $* | tee trace.ansi storage-layout-generate: - @./scripts/storage-layout.sh generate snapshots/.storage-layout-${PROTOCOL} Morpho RewardsManager Lens + @./scripts/storage-layout.sh generate snapshots/.storage-layout-${PROTOCOL} Morpho Lens storage-layout-check: - @./scripts/storage-layout.sh check snapshots/.storage-layout-${PROTOCOL} Morpho RewardsManager Lens + @./scripts/storage-layout.sh check snapshots/.storage-layout-${PROTOCOL} Morpho Lens config: @forge config From 191284c2a4e26bbd7c2a44925d12bd74fe2d0394 Mon Sep 17 00:00:00 2001 From: MerlinEgalite Date: Mon, 14 Nov 2022 16:09:03 +0100 Subject: [PATCH 10/11] =?UTF-8?q?=F0=9F=93=B8=20Update=20snapshot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 6 ------ snapshots/.storage-layout-aave-v2 | 26 -------------------------- 2 files changed, 32 deletions(-) diff --git a/Makefile b/Makefile index dd36f4457..29089a49c 100644 --- a/Makefile +++ b/Makefile @@ -120,12 +120,6 @@ storage-layout-generate: storage-layout-check: @./scripts/storage-layout.sh check snapshots/.storage-layout-${PROTOCOL} Morpho Lens -storage-layout-generate-no-rewards: - @./scripts/storage-layout.sh generate snapshots/.storage-layout-${PROTOCOL} Morpho Lens - -storage-layout-check-no-rewards: - @./scripts/storage-layout.sh check snapshots/.storage-layout-${PROTOCOL} Morpho Lens - config: @forge config diff --git a/snapshots/.storage-layout-aave-v2 b/snapshots/.storage-layout-aave-v2 index 095fcdb76..8326c5f75 100644 --- a/snapshots/.storage-layout-aave-v2 +++ b/snapshots/.storage-layout-aave-v2 @@ -75,32 +75,6 @@ | marketPauseStatus | mapping(address => struct Types.MarketPauseStatus) | 177 | 0 | 32 | contracts/aave-v2/Morpho.sol:Morpho | +--------------------------+--------------------------------------------------------------------+------+--------+-------+-------------------------------------+ -======================= -➡ RewardsManager -======================= - -+----------------------+----------------------------------------------------------+------+--------+-------+-----------------------------------------------------+ -| Name | Type | Slot | Offset | Bytes | Contract | -+===============================================================================================================================================================+ -| _initialized | bool | 0 | 0 | 1 | contracts/aave-v2/RewardsManager.sol:RewardsManager | -|----------------------+----------------------------------------------------------+------+--------+-------+-----------------------------------------------------| -| _initializing | bool | 0 | 1 | 1 | contracts/aave-v2/RewardsManager.sol:RewardsManager | -|----------------------+----------------------------------------------------------+------+--------+-------+-----------------------------------------------------| -| __gap | uint256[50] | 1 | 0 | 1600 | contracts/aave-v2/RewardsManager.sol:RewardsManager | -|----------------------+----------------------------------------------------------+------+--------+-------+-----------------------------------------------------| -| _owner | address | 51 | 0 | 20 | contracts/aave-v2/RewardsManager.sol:RewardsManager | -|----------------------+----------------------------------------------------------+------+--------+-------+-----------------------------------------------------| -| __gap | uint256[49] | 52 | 0 | 1568 | contracts/aave-v2/RewardsManager.sol:RewardsManager | -|----------------------+----------------------------------------------------------+------+--------+-------+-----------------------------------------------------| -| userUnclaimedRewards | mapping(address => uint256) | 101 | 0 | 32 | contracts/aave-v2/RewardsManager.sol:RewardsManager | -|----------------------+----------------------------------------------------------+------+--------+-------+-----------------------------------------------------| -| localAssetData | mapping(address => struct RewardsManager.LocalAssetData) | 102 | 0 | 32 | contracts/aave-v2/RewardsManager.sol:RewardsManager | -|----------------------+----------------------------------------------------------+------+--------+-------+-----------------------------------------------------| -| morpho | contract IMorpho | 103 | 0 | 20 | contracts/aave-v2/RewardsManager.sol:RewardsManager | -|----------------------+----------------------------------------------------------+------+--------+-------+-----------------------------------------------------| -| pool | contract ILendingPool | 104 | 0 | 20 | contracts/aave-v2/RewardsManager.sol:RewardsManager | -+----------------------+----------------------------------------------------------+------+--------+-------+-----------------------------------------------------+ - ======================= ➡ Lens ======================= From 37bb077872b774e8b08198a2e5d787fc544917e6 Mon Sep 17 00:00:00 2001 From: MerlinEgalite Date: Mon, 14 Nov 2022 16:21:03 +0100 Subject: [PATCH 11/11] =?UTF-8?q?=F0=9F=94=A7=20Update=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-storage-snapshot-check-aave-v2.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-storage-snapshot-check-aave-v2.yml b/.github/workflows/ci-storage-snapshot-check-aave-v2.yml index 97f279326..b8ac9a760 100644 --- a/.github/workflows/ci-storage-snapshot-check-aave-v2.yml +++ b/.github/workflows/ci-storage-snapshot-check-aave-v2.yml @@ -37,6 +37,6 @@ jobs: version: nightly - name: Run tests - run: make storage-layout-check-no-rewards + run: make storage-layout-check env: PROTOCOL: aave-v2