From dc49848696be62e107689be3295e85994964890c Mon Sep 17 00:00:00 2001 From: Ian Harvey Date: Fri, 13 Oct 2023 04:30:53 -0400 Subject: [PATCH] Merge develop into master (#951) * Logging for RewardsManager and PositionManager invariants (#925) * added logging for positionManager * added rewards and position logging * clean up * updated rewards mapping back to public so tests pass * how modifier was being called in rewardsPoolHandler * revised so logging pools is not required when logging positions * cleanup * readme cleanup --------- Co-authored-by: Ian Harvey * Invariants Improvement: Add multiple pool support in position and rewards manager invariant testing (#927) * Add multiple pools in position and rewards manager invariant testing * Fix RW6 regression test * Fix rewardsClaimed and updateRewardsClaimed in Rewards manager * Fix compile error * PR feedback * Add configurable number of pools for position and rewards manager invariant testing * Positions Invariants: Multiple positions, transfer positions (#926) * added randomness * added the ability to transfer positions * increased chance of rewards being claimed in handlers * cleanup * responded to comments --------- Co-authored-by: Ian Harvey * Fuzz test additions (#924) * Add fuzz test for borrower borrows fuzzed amount and getting kick after some time * Add fuzz test for take fuzzed amount of collateral from auction * Add fuzz test for settle with fuzzed pool deposit * Add fuzz test for add and remove collateral in ERC721Pool * Fuzzed buckets used in borrow and kick fuzz test * PR feedback * Invariant Improvements: Position rewards logging for multiple pools (#931) * Update position and rewards manager invariant logging for multiple pools * Fix regression test to run for any token precision and Quote token limits * PR feedback * Invariants Improvements: Add Multiple position in single handler in Position (#928) * Update Position invariants handler to memorialize and redeem multiple positions * PR feedback * Add partial random positions redeem in redeem position handler * Add random time skips between epochs in rewards manager * Add bucket bankruptcy scenario for rewards manager (#930) * Add bucket bankruptcy scenario for rewards manager * Fix evm reverts * PR feedback * Update prepare test methods to add position in NFT if there is no position in it * Fixed RewardsManager exchangeRate emit (#941) * stopped updatedExchangeRates emit when the rates are not updated * removed epoch check in _updateBucketExchangeRates --------- Co-authored-by: Ian Harvey * Invariant Improvements: Add settle invariant scenario (#933) * Add settle invariant scenario * Reduce Loans and skip time to make undercollateralize * Reduce time to skip in bucket bankruptcy scenario setup to fix regression tests (#936) * Update unit test to increase test coverage (#938) * Add unit tests to check deposits and debt limits in pool (#939) * Add unit test to check exp function limit * Add unit tests to check pool deposit and debt limits * PR cleanup * Add missing external function calls (#946) * Update Position Manager unit tests to test against both ERC721 subset Pool and Collection Pool (#945) * Merge changes from private-contracts repo into develop (#950) * Merge Develop into Master (#934) * Logging for RewardsManager and PositionManager invariants (#925) * added logging for positionManager * added rewards and position logging * clean up * updated rewards mapping back to public so tests pass * how modifier was being called in rewardsPoolHandler * revised so logging pools is not required when logging positions * cleanup * readme cleanup --------- Co-authored-by: Ian Harvey * Invariants Improvement: Add multiple pool support in position and rewards manager invariant testing (#927) * Add multiple pools in position and rewards manager invariant testing * Fix RW6 regression test * Fix rewardsClaimed and updateRewardsClaimed in Rewards manager * Fix compile error * PR feedback * Add configurable number of pools for position and rewards manager invariant testing * Positions Invariants: Multiple positions, transfer positions (#926) * added randomness * added the ability to transfer positions * increased chance of rewards being claimed in handlers * cleanup * responded to comments --------- Co-authored-by: Ian Harvey * Fuzz test additions (#924) * Add fuzz test for borrower borrows fuzzed amount and getting kick after some time * Add fuzz test for take fuzzed amount of collateral from auction * Add fuzz test for settle with fuzzed pool deposit * Add fuzz test for add and remove collateral in ERC721Pool * Fuzzed buckets used in borrow and kick fuzz test * PR feedback * Invariant Improvements: Position rewards logging for multiple pools (#931) * Update position and rewards manager invariant logging for multiple pools * Fix regression test to run for any token precision and Quote token limits * PR feedback * Invariants Improvements: Add Multiple position in single handler in Position (#928) * Update Position invariants handler to memorialize and redeem multiple positions * PR feedback * Add partial random positions redeem in redeem position handler * Add random time skips between epochs in rewards manager * Add bucket bankruptcy scenario for rewards manager (#930) * Add bucket bankruptcy scenario for rewards manager * Fix evm reverts * PR feedback * Update prepare test methods to add position in NFT if there is no position in it --------- Co-authored-by: Ian Harvey Co-authored-by: Prateek Gupta * manually merged from private-contracts/immutable-kicks * eliminated alreadyTaken (drawio needs updating) * annotated failing unit tests * new limit to induce testAccruePoolInterestRevertDueToExpLimit revert * fixed testUpdateInterestTuLimit * fixed testAccrueInterestNewInterestLimit * removed alreadyTaken from drawios * updated drawio-generated html * merged Prateek's post-merge changes --------- Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: Ian Harvey Co-authored-by: Ian Harvey Co-authored-by: Prateek Gupta * Return amount repaid in repayDebt and amount take in take (#947) * Remove multicall from position manager (#948) * L2 license grant (#949) * updated license * adjustment for public chains * Pool info utils multicall (#944) * Add PoolInfoUtilsMulticall contract to call multiple PoolInfoUtils methods in a single call to reduce rpc calls from subgraph * Add tests for PoolInfoutilsMulticall * Added comments and code improvements * altered license --------- Co-authored-by: Ian Harvey * removed mention of momp in testPoolInfoUtilsMulticall (#952) Co-authored-by: Ian Harvey * resolved compilation warnings and removed unused code (#953) --------- Co-authored-by: Ian Harvey Co-authored-by: Prateek Gupta Co-authored-by: Ed Noepel <46749157+EdNoepel@users.noreply.github.com> Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: Ed Noepel --- .gitignore | 2 +- README.md | 6 +- docs/Functions.md | 24 - docs/drawio/bucketTake.drawio | 6 +- docs/drawio/drawDebt.drawio | 454 +++---- docs/drawio/repayDebt.drawio | 468 +++---- docs/drawio/take.drawio | 6 +- docs/html/bucketTake.html | 2 +- docs/html/take.html | 2 +- src/ERC20Pool.sol | 60 +- src/ERC721Pool.sol | 58 +- src/PoolInfoUtils.sol | 33 +- src/PoolInfoUtilsMulticall.sol | 308 +++++ src/PositionManager.sol | 5 +- src/RewardsManager.sol | 5 +- src/base/Pool.sol | 30 +- .../pool/commons/IPoolBorrowerActions.sol | 4 +- src/interfaces/pool/commons/IPoolErrors.sol | 10 +- src/interfaces/pool/commons/IPoolEvents.sol | 4 +- .../pool/commons/IPoolInternals.sol | 11 +- src/interfaces/pool/commons/IPoolState.sol | 49 +- .../pool/commons/IPoolTakerActions.sol | 3 +- .../pool/erc20/IERC20PoolBorrowerActions.sol | 3 +- .../erc721/IERC721PoolBorrowerActions.sol | 3 +- src/libraries/external/BorrowerActions.sol | 130 +- src/libraries/external/KickerActions.sol | 71 +- src/libraries/external/PoolCommons.sol | 4 +- src/libraries/external/SettlerActions.sol | 3 +- src/libraries/external/TakerActions.sol | 133 +- src/libraries/helpers/PoolHelper.sol | 60 +- src/libraries/internal/Deposits.sol | 4 +- src/libraries/internal/Loans.sol | 27 +- tests/INVARIANTS.md | 9 +- tests/brownie/conftest.py | 2 +- .../interactions/BalancerUniswapExample.sol | 2 +- .../ERC20TakeWithExternalLiquidity.t.sol | 8 +- .../ERC721TakeWithExternalLiquidity.sol | 14 +- .../PanicExitERC20PoolInvariants.t.sol | 1 - .../RealWorldScenarioInvariants.t.sol | 1 - .../ERC20Pool/SettleERC20PoolInvariants.t.sol | 84 ++ .../handlers/BasicERC20PoolHandler.sol | 31 +- .../handlers/PanicExitERC20PoolHandler.sol | 8 +- .../handlers/SettleERC20PoolHandler.sol | 303 +++++ .../handlers/TradingERC20PoolHandler.sol | 3 +- .../PanicExitERC721PoolInvariants.t.sol | 1 - .../RealWorldScenarioInvariants.t.sol | 1 - .../handlers/BasicERC721PoolHandler.sol | 31 +- .../handlers/PanicExitERC721PoolHandler.sol | 8 +- ...ucketBankruptcyERC20PoolRewardsHandler.sol | 7 +- .../invariants/base/BasicInvariants.t.sol | 2 +- .../base/LiquidationInvariants.t.sol | 36 +- .../base/handlers/LiquidationPoolHandler.sol | 14 +- .../base/handlers/unbounded/BaseHandler.sol | 64 +- .../UnboundedLiquidationPoolHandler.sol | 91 +- .../invariants/interfaces/IBaseHandler.sol | 8 +- .../RegressionTestLiquidationERC20Pool.t.sol | 55 +- .../RegressionTestReservesERC20Pool.t.sol | 50 +- .../RegressionTestReservesERC721Pool.t.sol | 3 +- ...sionTestBankBankruptcyERC20PoolRewards.sol | 390 ++++++ ...gressionTestERC721PoolRewardsManager.t.sol | 46 + tests/forge/unit/Auctions.t.sol | 58 +- .../forge/unit/ERC20Pool/ERC20DSTestPlus.sol | 61 +- .../unit/ERC20Pool/ERC20PoolBorrow.t.sol | 15 +- .../unit/ERC20Pool/ERC20PoolCollateral.t.sol | 12 +- .../unit/ERC20Pool/ERC20PoolInfoUtils.t.sol | 70 +- .../ERC20PoolInterestRateAndEMAs.t.sol | 290 +++++ .../ERC20PoolLiquidationsArbTake.t.sol | 319 ++--- .../ERC20PoolLiquidationsDepositTake.t.sol | 316 ++--- .../ERC20Pool/ERC20PoolLiquidationsKick.t.sol | 506 ++----- .../ERC20PoolLiquidationsLenderKick.t.sol | 370 +++--- .../ERC20Pool/ERC20PoolLiquidationsMisc.t.sol | 162 +-- .../ERC20PoolLiquidationsScaled.t.sol | 36 +- .../ERC20PoolLiquidationsSettle.t.sol | 485 ++++--- .../ERC20Pool/ERC20PoolLiquidationsTake.t.sol | 1159 ++++++++--------- .../unit/ERC20Pool/ERC20PoolPrecision.t.sol | 7 +- .../unit/ERC20Pool/ERC20PoolQuoteToken.t.sol | 2 +- .../ERC20Pool/ERC20PoolReserveAuction.t.sol | 108 +- .../unit/ERC721Pool/ERC721DSTestPlus.sol | 56 +- .../unit/ERC721Pool/ERC721PoolBorrow.t.sol | 14 +- .../ERC721Pool/ERC721PoolCollateral.t.sol | 160 +-- .../unit/ERC721Pool/ERC721PoolInterest.t.sol | 44 +- .../ERC721PoolLiquidationsDepositTake.t.sol | 121 +- .../ERC721PoolLiquidationsKick.t.sol | 154 +-- .../ERC721PoolLiquidationsSettle.t.sol | 171 +-- .../ERC721PoolLiquidationsSettleAuction.t.sol | 951 +++++--------- .../ERC721PoolLiquidationsTake.t.sol | 423 +++--- .../ERC721Pool/ERC721PoolReserveAuction.t.sol | 24 +- .../unit/Positions/CodearenaReports.t.sol | 14 +- .../unit/Positions/PositionManager.t.sol | 96 +- tests/forge/unit/Rewards/ClaimRewards.t.sol | 26 +- .../forge/unit/Rewards/RewardsDSTestPlus.sol | 8 +- tests/forge/unit/Rewards/RewardsManager.t.sol | 279 ++-- tests/forge/utils/DSTestPlus.sol | 75 +- 93 files changed, 5294 insertions(+), 4559 deletions(-) create mode 100644 src/PoolInfoUtilsMulticall.sol create mode 100644 tests/forge/invariants/ERC20Pool/SettleERC20PoolInvariants.t.sol create mode 100644 tests/forge/invariants/ERC20Pool/handlers/SettleERC20PoolHandler.sol diff --git a/.gitignore b/.gitignore index 784a5b2dc..b2563a5a2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ node_modules .env .env.prod .idea/ -.vscode/*.log +.vscode/ __pycache__/ reports/ .gas-snapshot diff --git a/README.md b/README.md index eb4ae39ab..c955f6026 100644 --- a/README.md +++ b/README.md @@ -157,7 +157,11 @@ The licensed work is under the [Business Service License](https://github.com/ajn Prior to the Change Date, Licensor intends to transfer ownership of the Licensed Work to a to-be-organized not-for-profit foundation or similar public benefit focused entity (the “Ajna Foundation”), whereupon the rights, duties and obligations of Licensor under the BUSL License shall, without further act or deed of the parties, be assigned to Ajna Foundation, which entity shall thereafter be, and assume all rights, duties and obligations of (but not the liabilities, if any, of), the Licensor under the Business Service License. -Licensor reserves the right to specify Additional Use Grants at their discretion and to facilitate changes enacted by the Grant Coordination process, provided always that Additional Use Grants shall not conflict with the Business License. +Licensor reserves the right to specify Additional Use Grants at their discretion and to facilitate changes enacted by the Grant Coordination process, provided always that Additional Use Grants shall not conflict with the Business License. Licensor grants third parties permission to deploy The Ajna Protocol to other public blockchains and scaling solutions, hereby referred to as the "target chain", so long as: +- No other functional and successful deployment of Ajna is available on the target chain. +- No modification to Solidity source files in the protocol is made, and no changes are made which conflict with the Business License. +- Prior to deployment, the canonical burn-wrapped AJNA token (bwAJNA) on Ethereum mainnet is bridged to the target chain. +- Upon deployment, the protocol is configured to use the bwAJNA token on the target chain. Prior to the Change Date, Licensor shall elect the Change License governing the Licensed Work after the Change Date, which license shall be an [Open Source Initiative](https://opensource.org/licenses) compliant license, provided always that the Change License shall be GPL Version 2.0 compatible. Once elected, Licensor may change its Change License designation at any time on or before the Change Date by updating this file in the master branch of [source control](https://github.com/ajna-finance/contracts/tree/master). diff --git a/docs/Functions.md b/docs/Functions.md index 115d20e1d..88fa2d25f 100644 --- a/docs/Functions.md +++ b/docs/Functions.md @@ -386,19 +386,12 @@ - update scaling array state - increment reserveAuction.totalInterestEarned accumulator - BorrowerActions.drawDebt(): - - SettlerActions._settleAuction(): - - _removeAuction(): - - decrement kicker locked accumulator, increment kicker claimable accumumlator - - decrement auctions count accumulator - - decrement auctions.totalBondEscrowed accumulator - - update auction queue state - Loans.update(): - _upsert(): - insert or update loan in loans array - remove(): - remove loan from loans array - update borrower in address => borrower mapping - - decrement poolBalances.t0DebtInAuction accumulator - increment poolBalances.pledgedCollateral accumulator - increment poolBalances.t0Debt accumulator - _updateInterestState(): @@ -416,8 +409,6 @@ emit events: - BorrowerActions.drawDebt(): - - SettlerActions._settleAuction(): - - AuctionNFTSettle or AuctionSettle - DrawDebt - PoolCommons.updateInterestRate(): - UpdateInterestRate @@ -435,12 +426,6 @@ - update scaling array state - increment reserveAuction.totalInterestEarned accumulator - BorrowerActions.repayDebt(): - - SettlerActions._settleAuction(): - - _removeAuction(): - - decrement kicker locked accumulator, increment kicker claimable accumumlator - - decrement auctions count accumulator - - decrement auctions.totalBondEscrowed accumulator - - update auction queue state - Loans.update(): - _upsert(): - insert or update loan in loans array @@ -448,7 +433,6 @@ - remove loan from loans array - update borrower in address => borrower mapping - decrement poolBalances.t0Debt accumulator - - decrement poolBalances.t0DebtInAuction accumulator - decrement poolBalances.pledgedCollateral accumulator - _updateInterestState(): - PoolCommons.updateInterestRate(): @@ -465,8 +449,6 @@ emit events: - BorrowerActions.repayDebt(): - - SettlerActions._settleAuction: - - AuctionNFTSettle or AuctionSettle - RepayDebt - PoolCommons.updateInterestRate(): - UpdateInterestRate @@ -534,8 +516,6 @@ - increment reserveAuction.totalInterestEarned accumulator - TakerActions.take(): - _take(): - - _prepareTake(): - - update liquidation.alreadyTaken state - _rewardTake(): - update liquidation bond size accumulator - update kicker's locked balance accumulator @@ -567,7 +547,6 @@ - insufficient collateral InsufficientCollateral() - _prepareTake(): - loan is not in auction NoAuction() - - in 1 hour cool down period TakeNotPastCooldown() - _takeLoan(): - borrower debt less than pool min debt AmountLTMinDebt() @@ -591,8 +570,6 @@ - increment reserveAuction.totalInterestEarned accumulator - TakerActions.bucketTake(): - _takeBucket(): - - _prepareTake(): - - update liquidation.alreadyTaken state - _rewardBucketTake(): - Buckets.addLenderLP: - increment taker lender.lps accumulator and lender.depositTime state @@ -630,7 +607,6 @@ - insufficient collateral InsufficientCollateral() - _prepareTake(): - loan is not in auction NoAuction() - - in 1 hour cool down period TakeNotPastCooldown() - _takeLoan(): - borrower debt less than pool min debt AmountLTMinDebt() diff --git a/docs/drawio/bucketTake.drawio b/docs/drawio/bucketTake.drawio index a9ed91da5..bed45923c 100644 --- a/docs/drawio/bucketTake.drawio +++ b/docs/drawio/bucketTake.drawio @@ -1,6 +1,6 @@ - + - + @@ -176,7 +176,7 @@ - + diff --git a/docs/drawio/drawDebt.drawio b/docs/drawio/drawDebt.drawio index e4f8da895..339be3a0a 100644 --- a/docs/drawio/drawDebt.drawio +++ b/docs/drawio/drawDebt.drawio @@ -1,244 +1,210 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/drawio/repayDebt.drawio b/docs/drawio/repayDebt.drawio index f35d240d5..34e3721e4 100644 --- a/docs/drawio/repayDebt.drawio +++ b/docs/drawio/repayDebt.drawio @@ -1,251 +1,217 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/drawio/take.drawio b/docs/drawio/take.drawio index 1cf7fec86..f3b5c4005 100644 --- a/docs/drawio/take.drawio +++ b/docs/drawio/take.drawio @@ -1,6 +1,6 @@ - + - + @@ -176,7 +176,7 @@ - + diff --git a/docs/html/bucketTake.html b/docs/html/bucketTake.html index 943234193..4d6447f66 100644 --- a/docs/html/bucketTake.html +++ b/docs/html/bucketTake.html @@ -5,7 +5,7 @@ bucketTake -
+
\ No newline at end of file diff --git a/docs/html/take.html b/docs/html/take.html index 29246f7c1..392e42e24 100644 --- a/docs/html/take.html +++ b/docs/html/take.html @@ -5,7 +5,7 @@ take -
+
\ No newline at end of file diff --git a/src/ERC20Pool.sol b/src/ERC20Pool.sol index 20ee2f00a..fc1e6a5bd 100644 --- a/src/ERC20Pool.sol +++ b/src/ERC20Pool.sol @@ -121,10 +121,9 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool { /** * @inheritdoc IERC20PoolBorrowerActions * @dev === Write state === - * @dev - decrement `poolBalances.t0DebtInAuction` accumulator * @dev - increment `poolBalances.pledgedCollateral` accumulator * @dev - increment `poolBalances.t0Debt` accumulator - * @dev - update `t0Debt2ToCollateral` ratio only if loan not in auction, debt and collateral pre action are considered 0 if auction settled + * @dev - update `t0Debt2ToCollateral` ratio * @dev === Emit events === * @dev - `DrawDebt` */ @@ -143,7 +142,6 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool { DrawDebtResult memory result = BorrowerActions.drawDebt( auctions, - buckets, deposits, loans, poolState, @@ -161,21 +159,13 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool { poolState.t0Debt = result.t0PoolDebt; poolState.collateral = result.poolCollateral; - // update t0 debt in auction in memory pool state struct and pool balances state - if (result.t0DebtInAuctionChange != 0) { - poolState.t0DebtInAuction -= result.t0DebtInAuctionChange; - poolBalances.t0DebtInAuction = poolState.t0DebtInAuction; - } - - // adjust t0Debt2ToCollateral ratio if loan not in auction - if (!result.inAuction) { - _updateT0Debt2ToCollateral( - result.settledAuction ? 0 : result.debtPreAction, // debt pre settle (for loan in auction) not taken into account - result.debtPostAction, - result.settledAuction ? 0 : result.collateralPreAction, // collateral pre settle (for loan in auction) not taken into account - result.collateralPostAction - ); - } + // adjust t0Debt2ToCollateral ratio + _updateT0Debt2ToCollateral( + result.debtPreAction, + result.debtPostAction, + result.collateralPreAction, + result.collateralPostAction + ); // update pool interest rate state _updateInterestState(poolState, result.newLup); @@ -201,9 +191,8 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool { * @inheritdoc IERC20PoolBorrowerActions * @dev === Write state === * @dev - decrement `poolBalances.t0Debt accumulator` - * @dev - decrement `poolBalances.t0DebtInAuction accumulator` * @dev - decrement `poolBalances.pledgedCollateral accumulator` - * @dev - update `t0Debt2ToCollateral` ratio only if loan not in auction, debt and collateral pre action are considered 0 if auction settled + * @dev - update `t0Debt2ToCollateral` ratio * @dev === Emit events === * @dev - `RepayDebt` */ @@ -213,7 +202,7 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool { uint256 collateralAmountToPull_, address collateralReceiver_, uint256 limitIndex_ - ) external nonReentrant { + ) external nonReentrant returns (uint256 amountRepaid_) { PoolState memory poolState = _accruePoolInterest(); // ensure accounting is performed using the appropriate token scale @@ -223,7 +212,6 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool { RepayDebtResult memory result = BorrowerActions.repayDebt( auctions, - buckets, deposits, loans, poolState, @@ -240,21 +228,13 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool { poolState.t0Debt = result.t0PoolDebt; poolState.collateral = result.poolCollateral; - // update t0 debt in auction in memory pool state struct and pool balances state - if (result.t0DebtInAuctionChange != 0) { - poolState.t0DebtInAuction -= result.t0DebtInAuctionChange; - poolBalances.t0DebtInAuction = poolState.t0DebtInAuction; - } - - // adjust t0Debt2ToCollateral ratio if loan not in auction - if (!result.inAuction) { - _updateT0Debt2ToCollateral( - result.settledAuction ? 0 : result.debtPreAction, // debt pre settle (for loan in auction) not taken into account - result.debtPostAction, - result.settledAuction ? 0 : result.collateralPreAction, // collateral pre settle (for loan in auction) not taken into account - result.collateralPostAction - ); - } + // adjust t0Debt2ToCollateral ratio + _updateT0Debt2ToCollateral( + result.debtPreAction, + result.debtPostAction, + result.collateralPreAction, + result.collateralPostAction + ); // update pool interest rate state _updateInterestState(poolState, result.newLup); @@ -273,6 +253,8 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool { // move collateral from pool to address specified as collateral receiver _transferCollateral(collateralReceiver_, collateralAmountToPull_); } + + amountRepaid_ = result.quoteTokenToRepay; } /*********************************/ @@ -396,7 +378,7 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool { uint256 maxAmount_, address callee_, bytes calldata data_ - ) external override nonReentrant { + ) external override nonReentrant returns (uint256 collateralTaken_) { PoolState memory poolState = _accruePoolInterest(); uint256 collateralTokenScale = _getArgUint256(COLLATERAL_SCALE); @@ -430,6 +412,8 @@ contract ERC20Pool is FlashloanablePool, IERC20Pool { } _transferQuoteTokenFrom(msg.sender, result.quoteTokenAmount); + + collateralTaken_ = result.collateralAmount; } /** diff --git a/src/ERC721Pool.sol b/src/ERC721Pool.sol index 668980fa5..75cab09a9 100644 --- a/src/ERC721Pool.sol +++ b/src/ERC721Pool.sol @@ -155,7 +155,6 @@ contract ERC721Pool is FlashloanablePool, IERC721Pool { DrawDebtResult memory result = BorrowerActions.drawDebt( auctions, - buckets, deposits, loans, poolState, @@ -173,21 +172,13 @@ contract ERC721Pool is FlashloanablePool, IERC721Pool { poolState.t0Debt = result.t0PoolDebt; poolState.collateral = result.poolCollateral; - // update t0 debt in auction in memory pool state struct and pool balances state - if (result.t0DebtInAuctionChange != 0) { - poolState.t0DebtInAuction -= result.t0DebtInAuctionChange; - poolBalances.t0DebtInAuction = poolState.t0DebtInAuction; - } - - // adjust t0Debt2ToCollateral ratio if loan not in auction - if (!result.inAuction) { - _updateT0Debt2ToCollateral( - result.settledAuction ? 0 : result.debtPreAction, // debt pre settle (for loan in auction) not taken into account - result.debtPostAction, - result.settledAuction ? 0 : result.collateralPreAction, // collateral pre settle (for loan in auction) not taken into account - result.collateralPostAction - ); - } + // adjust t0Debt2ToCollateral ratio + _updateT0Debt2ToCollateral( + result.debtPreAction, + result.debtPostAction, + result.collateralPreAction, + result.collateralPostAction + ); // update pool interest rate state _updateInterestState(poolState, result.newLup); @@ -200,8 +191,6 @@ contract ERC721Pool is FlashloanablePool, IERC721Pool { _transferFromSenderToPool(borrowerTokenIds[borrowerAddress_], tokenIdsToPledge_); } - if (result.settledAuction) _rebalanceTokens(borrowerAddress_, result.remainingCollateral); - // move borrowed amount from pool to sender if (amountToBorrow_ != 0) { // update pool balances t0 debt state @@ -229,7 +218,7 @@ contract ERC721Pool is FlashloanablePool, IERC721Pool { uint256 noOfNFTsToPull_, address collateralReceiver_, uint256 limitIndex_ - ) external nonReentrant { + ) external nonReentrant returns (uint256 amountRepaid_) { PoolState memory poolState = _accruePoolInterest(); // ensure accounting is performed using the appropriate token scale @@ -238,7 +227,6 @@ contract ERC721Pool is FlashloanablePool, IERC721Pool { RepayDebtResult memory result = BorrowerActions.repayDebt( auctions, - buckets, deposits, loans, poolState, @@ -255,23 +243,13 @@ contract ERC721Pool is FlashloanablePool, IERC721Pool { poolState.t0Debt = result.t0PoolDebt; poolState.collateral = result.poolCollateral; - // update t0 debt in auction in memory pool state struct and pool balances state - if (result.t0DebtInAuctionChange != 0) { - poolState.t0DebtInAuction -= result.t0DebtInAuctionChange; - poolBalances.t0DebtInAuction = poolState.t0DebtInAuction; - } - - if (result.settledAuction) _rebalanceTokens(borrowerAddress_, result.remainingCollateral); - - // adjust t0Debt2ToCollateral ratio if loan not in auction - if (!result.inAuction) { - _updateT0Debt2ToCollateral( - result.settledAuction ? 0 : result.debtPreAction, // debt pre settle (for loan in auction) not taken into account - result.debtPostAction, - result.settledAuction ? 0 : result.collateralPreAction, // collateral pre settle (for loan in auction) not taken into account - result.collateralPostAction - ); - } + // adjust t0Debt2ToCollateral ratio + _updateT0Debt2ToCollateral( + result.debtPreAction, + result.debtPostAction, + result.collateralPreAction, + result.collateralPostAction + ); // update pool interest rate state _updateInterestState(poolState, result.newLup); @@ -290,6 +268,8 @@ contract ERC721Pool is FlashloanablePool, IERC721Pool { // move collateral from pool to address specified as collateral receiver _transferFromPoolToAddress(collateralReceiver_, borrowerTokenIds[msg.sender], noOfNFTsToPull_); } + + amountRepaid_ = result.quoteTokenToRepay; } /*********************************/ @@ -452,7 +432,7 @@ contract ERC721Pool is FlashloanablePool, IERC721Pool { uint256 collateral_, address callee_, bytes calldata data_ - ) external override nonReentrant { + ) external override nonReentrant returns (uint256 collateralTaken_) { PoolState memory poolState = _accruePoolInterest(); TakeResult memory result = TakerActions.take( @@ -493,6 +473,8 @@ contract ERC721Pool is FlashloanablePool, IERC721Pool { // transfer from pool to borrower the excess of quote tokens after rounding collateral auctioned if (result.excessQuoteToken != 0) _transferQuoteToken(borrowerAddress_, result.excessQuoteToken); + + collateralTaken_ = result.collateralAmount / 1e18; } /** diff --git a/src/PoolInfoUtils.sol b/src/PoolInfoUtils.sol index 581f7baf3..beed3f53a 100644 --- a/src/PoolInfoUtils.sol +++ b/src/PoolInfoUtils.sol @@ -2,6 +2,8 @@ pragma solidity 0.8.18; +import { Math } from '@openzeppelin/contracts/utils/math/Math.sol'; + import { IPool, IERC20Token } from './interfaces/pool/IPool.sol'; import { @@ -56,8 +58,8 @@ contract PoolInfoUtils { ) { IPool pool = IPool(ajnaPool_); - uint256 kickMomp; - ( , , , kickTime_, kickMomp, neutralPrice_, , , , ) = pool.auctionInfo(borrower_); + uint256 referencePrice; + ( , , , kickTime_, referencePrice, neutralPrice_, , , ) = pool.auctionInfo(borrower_); if (kickTime_ != 0) { (debtToCover_, collateral_, ) = this.borrowerInfo(ajnaPool_, borrower_); @@ -65,7 +67,7 @@ contract PoolInfoUtils { uint256 lup_ = _priceAt(pool.depositIndex(poolDebt)); isCollateralized_ = _isCollateralized(debtToCover_, collateral_, lup_, pool.poolType()); - price_ = _auctionPrice(kickMomp, neutralPrice_, kickTime_); + price_ = _auctionPrice(referencePrice, kickTime_); } } @@ -98,7 +100,10 @@ contract PoolInfoUtils { uint256 pendingInflator = PoolCommons.pendingInflator(inflator, lastInflatorUpdate, interestRate); uint256 t0Debt; - (t0Debt, collateral_, t0Np_) = pool.borrowerInfo(borrower_); + uint256 npTpRatio; + (t0Debt, collateral_, npTpRatio) = pool.borrowerInfo(borrower_); + + t0Np_ = collateral_ == 0 ? 0 : Math.mulDiv(t0Debt, npTpRatio, collateral_); debt_ = Maths.ceilWmul(t0Debt, pendingInflator); } @@ -407,26 +412,6 @@ contract PoolInfoUtils { (, htp_, ) = IPool(ajnaPool_).loansInfo(); } - /** - * @notice Returns current `MOMP` for a given pool. - */ - function momp( - address ajnaPool_ - ) external view returns (uint256) { - IPool pool = IPool(ajnaPool_); - - ( , , uint256 noOfLoans) = pool.loansInfo(); - noOfLoans += pool.totalAuctionsInPool(); - if (noOfLoans == 0) { - // if there are no borrowers, return the HPB - return _priceAt(pool.depositIndex(1)); - } else { - // otherwise, calculate the MOMP - (uint256 debt, , , ) = pool.debtInfo(); - return _priceAt(pool.depositIndex(Maths.wdiv(debt, noOfLoans * 1e18))); - } - } - /** * @notice Calculates origination fee rate for a pool. * @notice Calculated as greater of the current annualized interest rate divided by `52` (one week of interest) or `5` bps. diff --git a/src/PoolInfoUtilsMulticall.sol b/src/PoolInfoUtilsMulticall.sol new file mode 100644 index 000000000..6d07f4cee --- /dev/null +++ b/src/PoolInfoUtilsMulticall.sol @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity 0.8.18; + +import { PoolInfoUtils } from "./PoolInfoUtils.sol"; + +contract PoolInfoUtilsMulticall { + + PoolInfoUtils public immutable poolInfoUtils; + + struct PoolPriceInfo { + uint256 hpb; + uint256 hpbIndex; + uint256 htp; + uint256 htpIndex; + uint256 lup; + uint256 lupIndex; + } + + struct PoolReservesInfo { + uint256 reserves; + uint256 claimableReserves; + uint256 claimableReservesRemaining; + uint256 auctionPrice; + uint256 timeRemaining; + } + + struct PoolUtilizationInfo { + uint256 poolMinDebtAmount; + uint256 poolCollateralization; + uint256 poolActualUtilization; + uint256 poolTargetUtilization; + } + + struct BucketInfo { + uint256 price; + uint256 quoteTokens; + uint256 collateral; + uint256 bucketLP; + uint256 scale; + uint256 exchangeRate; + } + + constructor(PoolInfoUtils poolInfoUtils_) { + poolInfoUtils = poolInfoUtils_; + } + + /** + * @notice Retrieves PoolPriceInfo, PoolReservesInfo, PoolUtilizationInfo and BucketInfo + * @param ajnaPool_ Address of `Ajna` pool + * @param bucketIndex_ The index of the bucket to retrieve + * @return poolPriceInfo_ Pool price info struct + * @return poolReservesInfo_ Pool reserves info struct + * @return poolUtilizationInfo_ Pool utilization info struct + * @return bucketInfo_ Bucket info struct + */ + function poolDetailsAndBucketInfo(address ajnaPool_, uint256 bucketIndex_) + external + view + returns( + PoolPriceInfo memory poolPriceInfo_, + PoolReservesInfo memory poolReservesInfo_, + PoolUtilizationInfo memory poolUtilizationInfo_, + BucketInfo memory bucketInfo_ + ) + { + ( + poolPriceInfo_.hpb, + poolPriceInfo_.hpbIndex, + poolPriceInfo_.htp, + poolPriceInfo_.htpIndex, + poolPriceInfo_.lup, + poolPriceInfo_.lupIndex + ) = poolInfoUtils.poolPricesInfo(ajnaPool_); + + ( + poolReservesInfo_.reserves, + poolReservesInfo_.claimableReserves, + poolReservesInfo_.claimableReservesRemaining, + poolReservesInfo_.auctionPrice, + poolReservesInfo_.timeRemaining + ) = poolInfoUtils.poolReservesInfo(ajnaPool_); + + ( + poolUtilizationInfo_.poolMinDebtAmount, + poolUtilizationInfo_.poolCollateralization, + poolUtilizationInfo_.poolActualUtilization, + poolUtilizationInfo_.poolTargetUtilization + ) = poolInfoUtils.poolUtilizationInfo(ajnaPool_); + + ( + bucketInfo_.price, + bucketInfo_.quoteTokens, + bucketInfo_.collateral, + bucketInfo_.bucketLP, + bucketInfo_.scale, + bucketInfo_.exchangeRate + ) = poolInfoUtils.bucketInfo(ajnaPool_, bucketIndex_); + } + + /** + * @notice Retrieves info of lenderInterestMargin, borrowFeeRate and depositFeeRate + * @param ajnaPool_ Address of `Ajna` pool + * @return lenderInterestMargin Lender interest margin in pool + * @return borrowFeeRate Borrow fee rate calculated from the pool interest ra + * @return depositFeeRate Deposit fee rate calculated from the pool interest rate + */ + function poolRatesAndFees(address ajnaPool_) + external + view + returns + ( + uint256 lenderInterestMargin, + uint256 borrowFeeRate, + uint256 depositFeeRate + ) + { + lenderInterestMargin = poolInfoUtils.lenderInterestMargin(ajnaPool_); + borrowFeeRate = poolInfoUtils.borrowFeeRate(ajnaPool_); + depositFeeRate = poolInfoUtils.unutilizedDepositFeeRate(ajnaPool_); + } + + /** + * @notice Aggregate results from multiple read-only function calls + * @param functionSignatures_ Array of signatures of read-only functions to be called + * @param args_ Array of serialized function arguments of all read-only functions to called + * @return results_ Array of result of all read-only function calls in bytes + */ + function multicall(string[] calldata functionSignatures_, string[] calldata args_) external returns (bytes[] memory results_) { + uint256 currentIndex = 0; + results_ = new bytes[](functionSignatures_.length); + for(uint256 i = 0; i < functionSignatures_.length; i++) { + string[] memory parameters = _parseFunctionSignature(functionSignatures_[i]); + uint256 noOfParams = parameters.length; + bytes memory callData; + if (noOfParams == 1) { + if (keccak256(bytes(parameters[0])) == keccak256(bytes("uint256"))) { + uint256 arg = _stringToUint(args_[currentIndex]); + callData = abi.encodeWithSignature(functionSignatures_[i], arg); + } + if (keccak256(bytes(parameters[0])) == keccak256(bytes("address"))) { + address arg = _stringToAddress(args_[currentIndex]); + callData = abi.encodeWithSignature(functionSignatures_[i], arg); + } + } + + if (noOfParams == 2) { + if (keccak256(bytes(parameters[1])) == keccak256(bytes("uint256"))) { + address arg1 = _stringToAddress(args_[currentIndex]); + uint256 arg2 = _stringToUint(args_[currentIndex + 1]); + callData = abi.encodeWithSignature(functionSignatures_[i], arg1, arg2); + } + if (keccak256(bytes(parameters[1])) == keccak256(bytes("address"))) { + address arg1 = _stringToAddress(args_[currentIndex]); + address arg2 = _stringToAddress(args_[currentIndex + 1]); + callData = abi.encodeWithSignature(functionSignatures_[i], arg1, arg2); + } + } + + if (noOfParams == 3) { + address arg1 = _stringToAddress(args_[currentIndex]); + uint256 arg2 = _stringToUint(args_[currentIndex + 1]); + uint256 arg3 = _stringToUint(args_[currentIndex + 2]); + callData = abi.encodeWithSignature(functionSignatures_[i], arg1, arg2, arg3); + } + + currentIndex += noOfParams; + (, results_[i]) = address(poolInfoUtils).call(callData); + } + } + + // Returns all function parameters + function _parseFunctionSignature(string memory signature_) internal pure returns (string[] memory parameters_) { + // Remove the function name and parentheses from the signature + string memory parametersString = _removeParentheses(signature_); + + parameters_ = _splitString(parametersString, ","); + } + + // Remove function name and Parentheses from signature + function _removeParentheses(string memory signature_) internal pure returns (string memory trimmedSignature_) { + // Remove function name + trimmedSignature_ = _trimFunctionName(signature_); + + // Check if the string starts with '(' and ends with ')' + if (bytes(trimmedSignature_).length >= 2 && bytes(trimmedSignature_)[0] == bytes("(")[0] && bytes(trimmedSignature_)[bytes(trimmedSignature_).length - 1] == bytes(")")[0]) { + // Remove the first and last characters + trimmedSignature_ = _substring(trimmedSignature_, 1, bytes(trimmedSignature_).length - 2); + } + } + + // Splits a string into an array of strings using a specified delimiter + function _splitString(string memory str_, string memory delimiter_) internal pure returns (string[] memory parts_) { + uint256 numDelimiters = _countOccurrences(str_, delimiter_) + 1; + parts_ = new string[](numDelimiters); + + uint256 currentIndex = 0; + for (uint256 i = 0; i < numDelimiters - 1; i++) { + uint256 delimiterIndex = uint256(_indexOf(str_, delimiter_, currentIndex)); + parts_[i] = _substring(str_, currentIndex, delimiterIndex - 1); + currentIndex = delimiterIndex + bytes(delimiter_).length; + } + parts_[numDelimiters - 1] = _substring(str_, currentIndex, bytes(str_).length - 1); + } + + // Removes the function name from a string + function _trimFunctionName(string memory str_) internal pure returns (string memory) { + uint256 start = 0; + uint256 end = bytes(str_).length - 1; + + while (start <= end && bytes(str_)[start] != bytes("(")[0]) { + start++; + } + + if (end >= start) { + return _substring(str_, start, end); + } else { + return ""; + } + } + + // Counts the occurrences of a pattern within a string + function _countOccurrences(string memory str_, string memory pattern_) internal pure returns (uint256 count_) { + uint256 lastIndex = 0; + while (_indexOf(str_, pattern_, lastIndex) != int256(-1)) { + lastIndex = uint256(_indexOf(str_, pattern_, lastIndex)) + bytes(pattern_).length; + count_++; + } + } + + // Finds the index of a pattern within a string + function _indexOf(string memory str_, string memory pattern_, uint256 startIndex_) internal pure returns (int256) { + bytes memory strBytes = bytes(str_); + bytes memory patternBytes = bytes(pattern_); + + for (uint256 i = startIndex_; i <= strBytes.length - patternBytes.length; i++) { + bool found = true; + for (uint256 j = 0; j < patternBytes.length; j++) { + if (strBytes[i + j] != patternBytes[j]) { + found = false; + break; + } + } + if (found) { + return int256(i); + } + } + return int256(-1); + } + + // Extracts a substring from a given string + function _substring(string memory str_, uint256 startIndex_, uint256 endIndex_) internal pure returns (string memory) { + require(startIndex_ <= endIndex_, "Invalid substring indices"); + bytes memory strBytes = bytes(str_); + bytes memory result = new bytes(endIndex_ - startIndex_ + 1); + + for (uint256 i = startIndex_; i <= endIndex_; i++) { + result[i - startIndex_] = strBytes[i]; + } + + return string(result); + } + + // Converts a string to an unsigned integer + function _stringToUint(string memory str_) internal pure returns (uint256 result_) { + bytes memory strBytes = bytes(str_); + for (uint256 i = 0; i < strBytes.length; i++) { + uint256 val = uint256(uint8(strBytes[i])); + if (val >= 48 && val <= 57) { + result_ = result_ * 10 + (val - 48); + } + } + } + + // Converts a hexadecimal character to its decimal value + function _hexCharToDecimal(uint8 character_) internal pure returns (uint8) { + if (bytes1(character_) >= bytes1('0') && bytes1(character_) <= bytes1('9')) { + return character_ - uint8(bytes1('0')); + } + if (bytes1(character_) >= bytes1('a') && bytes1(character_) <= bytes1('f')) { + return 10 + character_ - uint8(bytes1('a')); + } + if (bytes1(character_) >= bytes1('A') && bytes1(character_) <= bytes1('F')) { + return 10 + character_ - uint8(bytes1('A')); + } + return 0; + } + + // Converts a hexadecimal string to bytes + function _hexStringToBytes(string memory str_) internal pure returns (bytes memory bytesString_) { + bytes memory strBytes = bytes(str_); + require(strBytes.length % 2 == 0); // length must be even + bytesString_ = new bytes(strBytes.length / 2); + for (uint i = 1; i < strBytes.length / 2; ++i) { + bytesString_[i] = bytes1(_hexCharToDecimal(uint8(strBytes[2 * i])) * 16 + _hexCharToDecimal(uint8(strBytes[2 * i + 1]))); + } + } + + // Converts a hexadecimal string to an Ethereum address + function _stringToAddress(string calldata str_) internal pure returns (address tempAddress_) { + bytes memory strBytes = _hexStringToBytes(str_); + require(strBytes.length >= 1 + 20, "toAddress_outOfBounds"); + + assembly { + tempAddress_ := div(mload(add(add(strBytes, 0x20), 1)), 0x1000000000000000000000000) + } + } +} \ No newline at end of file diff --git a/src/PositionManager.sol b/src/PositionManager.sol index 2bc3ee1e9..531f2730c 100644 --- a/src/PositionManager.sol +++ b/src/PositionManager.sol @@ -5,7 +5,6 @@ pragma solidity 0.8.18; import { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.sol'; import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import { EnumerableSet } from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; -import { Multicall } from '@openzeppelin/contracts/utils/Multicall.sol'; import { ReentrancyGuard } from '@openzeppelin/contracts/security/ReentrancyGuard.sol'; import { SafeERC20 } from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; @@ -37,7 +36,7 @@ import { PositionNFTSVG } from './libraries/external/PositionNFTSVG.sol'; * - `redeem` positions for given buckets * - `burn` positions `NFT` */ -contract PositionManager is PermitERC721, IPositionManager, Multicall, ReentrancyGuard { +contract PositionManager is PermitERC721, IPositionManager, ReentrancyGuard { using EnumerableSet for EnumerableSet.UintSet; using SafeERC20 for ERC20; @@ -163,6 +162,7 @@ contract PositionManager is PermitERC721, IPositionManager, Multicall, Reentranc * @dev External calls to `Pool` contract: * @dev - `lenderInfo()`: get lender position in bucket * @dev - `transferLP()`: transfer `LP` ownership to `PositionManager` contract + * @dev - `lpAllowance()`: get owner LP allowance for lp transfer * @dev === Write state === * @dev `TokenInfo.positionIndexes`: add bucket index * @dev `TokenInfo.positions`: update `tokenId => bucket id` position @@ -269,6 +269,7 @@ contract PositionManager is PermitERC721, IPositionManager, Multicall, Reentranc * @dev External calls to `Pool` contract: * @dev `bucketInfo()`: get from bucket info * @dev `moveQuoteToken()`: move liquidity between buckets + * @dev `updateInterest()`: accrue pool interest * @dev === Write state === * @dev `TokenInfo.positionIndexes`: remove from bucket index * @dev `TokenInfo.positionIndexes`: add to bucket index diff --git a/src/RewardsManager.sol b/src/RewardsManager.sol index e91101960..892b20bdd 100644 --- a/src/RewardsManager.sol +++ b/src/RewardsManager.sol @@ -611,7 +611,7 @@ contract RewardsManager is IRewardsManager { ) = _getEpochInfo(pool_, curBurnEpoch); // Update exchange rates without reward if first epoch or if the epoch does not have burned tokens associated with it - if (curBurnEpoch == 0 || totalBurnedInEpoch == 0) { + if (totalBurnedInEpoch == 0) { uint256 noOfIndexes = indexes_.length; for (uint256 i = 0; i < noOfIndexes; ) { @@ -657,6 +657,9 @@ contract RewardsManager is IRewardsManager { // accumulate the full amount of additional rewards updateRewardsClaimed[curBurnEpoch] += updatedRewards_; + } else { + // block.timestamp is greater than curBurnTime + UPDATE_PERIOD do not emit UpdateExchangeRates + return 0; } } diff --git a/src/base/Pool.sol b/src/base/Pool.sol index 3643fd56c..0f7cf3504 100644 --- a/src/base/Pool.sol +++ b/src/base/Pool.sol @@ -306,20 +306,17 @@ abstract contract Pool is Clone, ReentrancyGuard, Multicall, IPool { ); // update in memory pool state struct - poolState.debt = result.poolDebt; - poolState.t0Debt = result.t0PoolDebt; poolState.t0DebtInAuction += result.t0KickedDebt; // adjust t0Debt2ToCollateral ratio _updateT0Debt2ToCollateral( - result.debtPreAction, + result.t0KickedDebt, 0, // debt post kick (for loan in auction) not taken into account result.collateralPreAction, 0 // collateral post kick (for loan in auction) not taken into account ); // update pool balances state - poolBalances.t0Debt = poolState.t0Debt; poolBalances.t0DebtInAuction = poolState.t0DebtInAuction; // update pool interest rate state _updateInterestState(poolState, result.lup); @@ -330,8 +327,6 @@ abstract contract Pool is Clone, ReentrancyGuard, Multicall, IPool { /** * @inheritdoc IPoolKickerActions * @dev === Write state === - * @dev increment `poolBalances.t0DebtInAuction` and `poolBalances.t0Debt` accumulators - * @dev update `t0Debt2ToCollateral` ratio, debt and collateral post action are considered 0 */ function lenderKick( uint256 index_, @@ -351,20 +346,17 @@ abstract contract Pool is Clone, ReentrancyGuard, Multicall, IPool { ); // update in memory pool state struct - poolState.debt = result.poolDebt; - poolState.t0Debt = result.t0PoolDebt; poolState.t0DebtInAuction += result.t0KickedDebt; // adjust t0Debt2ToCollateral ratio _updateT0Debt2ToCollateral( - result.debtPreAction, + result.t0KickedDebt, 0, // debt post kick (for loan in auction) not taken into account result.collateralPreAction, 0 // collateral post kick (for loan in auction) not taken into account ); // update pool balances state - poolBalances.t0Debt = poolState.t0Debt; poolBalances.t0DebtInAuction = poolState.t0DebtInAuction; // update pool interest rate state @@ -418,7 +410,7 @@ abstract contract Pool is Clone, ReentrancyGuard, Multicall, IPool { */ function kickReserveAuction() external override nonReentrant { // start a new claimable reserve auction, passing in relevant parameters such as the current pool size, debt, balance, and inflator value - uint256 kickerAward = KickerActions.kickReserveAuction( + KickerActions.kickReserveAuction( auctions, reserveAuction, KickReserveAuctionParams({ @@ -428,9 +420,6 @@ abstract contract Pool is Clone, ReentrancyGuard, Multicall, IPool { inflator: inflatorState.inflator }) ); - - // transfer kicker award to msg.sender - _transferQuoteToken(msg.sender, kickerAward); } /** @@ -601,7 +590,6 @@ abstract contract Pool is Clone, ReentrancyGuard, Multicall, IPool { // update in memory pool state struct poolState_.debt = result_.poolDebt; poolState_.t0Debt = result_.t0PoolDebt; - poolState_.t0DebtInAuction += result_.t0DebtPenalty; poolState_.t0DebtInAuction -= result_.t0DebtInAuctionChange; poolState_.collateral -= (result_.collateralAmount + result_.compensatedCollateral); // deduct collateral taken plus collateral compensated if NFT auction settled @@ -757,12 +745,11 @@ abstract contract Pool is Clone, ReentrancyGuard, Multicall, IPool { uint256 bondFactor_, uint256 bondSize_, uint256 kickTime_, - uint256 kickMomp_, + uint256 referencePrice_, uint256 neutralPrice_, address head_, address next_, - address prev_, - bool alreadyTaken_ + address prev_ ) { Liquidation storage liquidation = auctions.liquidations[borrower_]; return ( @@ -770,12 +757,11 @@ abstract contract Pool is Clone, ReentrancyGuard, Multicall, IPool { liquidation.bondFactor, liquidation.bondSize, liquidation.kickTime, - liquidation.kickMomp, + liquidation.referencePrice, liquidation.neutralPrice, auctions.head, liquidation.next, - liquidation.prev, - liquidation.alreadyTaken + liquidation.prev ); } @@ -787,7 +773,7 @@ abstract contract Pool is Clone, ReentrancyGuard, Multicall, IPool { return ( borrower.t0Debt, borrower.collateral, - borrower.t0Np + borrower.npTpRatio ); } diff --git a/src/interfaces/pool/commons/IPoolBorrowerActions.sol b/src/interfaces/pool/commons/IPoolBorrowerActions.sol index 87339159d..ccfaacd12 100644 --- a/src/interfaces/pool/commons/IPoolBorrowerActions.sol +++ b/src/interfaces/pool/commons/IPoolBorrowerActions.sol @@ -8,8 +8,8 @@ pragma solidity 0.8.18; interface IPoolBorrowerActions { /** - * @notice Called by fully colalteralized borrowers to restamp the `Neutral Price` of the loan (only if loan is fully collateralized and not in auction). - * The reason for stamping the neutral price on the loan is to provide some certainty to the borrower as to at what price they can expect to be liquidated. + * @notice Called by fully collateralized borrowers to restamp the `Np to Tp ratio` of the loan (only if loan is fully collateralized and not in auction). + * The reason for stamping the `Np to Tp ratio` on the loan is to provide some certainty to the borrower as to at what price they can expect to be liquidated. * This action can restamp only the loan of `msg.sender`. */ function stampLoan() external; diff --git a/src/interfaces/pool/commons/IPoolErrors.sol b/src/interfaces/pool/commons/IPoolErrors.sol index b5fddaff9..52f8cca27 100644 --- a/src/interfaces/pool/commons/IPoolErrors.sol +++ b/src/interfaces/pool/commons/IPoolErrors.sol @@ -25,6 +25,11 @@ interface IPoolErrors { */ error AuctionNotClearable(); + /** + * @notice Auction does not meet requirements to take liquidity. + */ + error AuctionNotTakeable(); + /** * @notice Head auction should be cleared prior of executing this action. */ @@ -195,11 +200,6 @@ interface IPoolErrors { */ error ReserveAuctionTooSoon(); - /** - * @notice Take was called before `1` hour had passed from kick time. - */ - error TakeNotPastCooldown(); - /** * @notice Current block timestamp has reached or exceeded a user-provided expiration. */ diff --git a/src/interfaces/pool/commons/IPoolEvents.sol b/src/interfaces/pool/commons/IPoolEvents.sol index 32b2c9466..ededcc548 100644 --- a/src/interfaces/pool/commons/IPoolEvents.sol +++ b/src/interfaces/pool/commons/IPoolEvents.sol @@ -340,8 +340,8 @@ interface IPoolEvents { ); /** - * @notice Emitted when a loan `Neutral Price` is restamped. - * @param borrower Identifies the loan to update the `Neutral Price`. + * @notice Emitted when a loan `Np to Tp ratio` is restamped. + * @param borrower Identifies the loan to update the `Np to Tp ratio`. */ event LoanStamped( address indexed borrower diff --git a/src/interfaces/pool/commons/IPoolInternals.sol b/src/interfaces/pool/commons/IPoolInternals.sol index f1b62ca89..468988855 100644 --- a/src/interfaces/pool/commons/IPoolInternals.sol +++ b/src/interfaces/pool/commons/IPoolInternals.sol @@ -13,9 +13,7 @@ pragma solidity 0.8.18; /// @dev Struct used to return result of `KickerAction.kick` action. struct KickResult { uint256 amountToCoverBond; // [WAD] amount of bond that needs to be covered - uint256 t0PoolDebt; // [WAD] t0 debt in pool after kick uint256 t0KickedDebt; // [WAD] new t0 debt after kick - uint256 debtPreAction; // [WAD] The amount of borrower t0 debt before kick uint256 collateralPreAction; // [WAD] The amount of borrower collateral before kick, same as the one after kick uint256 poolDebt; // [WAD] current debt in pool after kick uint256 lup; // [WAD] current LUP in pool after kick @@ -43,7 +41,6 @@ struct TakeResult { uint256 collateralAmount; // [WAD] amount of collateral taken uint256 compensatedCollateral; // [WAD] amount of borrower collateral that is compensated with LP uint256 quoteTokenAmount; // [WAD] amount of quote tokens paid by taker for taken collateral, used in take action - uint256 t0DebtPenalty; // [WAD] t0 penalty applied on first take uint256 excessQuoteToken; // [WAD] (NFT only) amount of quote tokens to be paid by taker to borrower for fractional collateral, used in take action uint256 remainingCollateral; // [WAD] amount of borrower collateral remaining after take uint256 poolDebt; // [WAD] current pool debt @@ -98,13 +95,10 @@ struct RemoveQuoteParams { /// @dev Struct used to return result of `BorrowerActions.drawDebt` action. struct DrawDebtResult { - bool inAuction; // true if loan still in auction after pledge more collateral, false otherwise uint256 newLup; // [WAD] new pool LUP after draw debt uint256 poolCollateral; // [WAD] total amount of collateral in pool after pledge collateral uint256 poolDebt; // [WAD] total accrued debt in pool after draw debt uint256 remainingCollateral; // [WAD] amount of borrower collateral after draw debt (for NFT can be diminished if auction settled) - bool settledAuction; // true if collateral pledged settles auction - uint256 t0DebtInAuctionChange; // [WAD] change of t0 pool debt in auction after pledge collateral uint256 t0PoolDebt; // [WAD] amount of t0 debt in pool after draw debt uint256 debtPreAction; // [WAD] The amount of borrower t0 debt before draw debt uint256 debtPostAction; // [WAD] The amount of borrower t0 debt after draw debt @@ -114,17 +108,14 @@ struct DrawDebtResult { /// @dev Struct used to return result of `BorrowerActions.repayDebt` action. struct RepayDebtResult { - bool inAuction; // true if loan still in auction after repay, false otherwise uint256 newLup; // [WAD] new pool LUP after draw debt uint256 poolCollateral; // [WAD] total amount of collateral in pool after pull collateral uint256 poolDebt; // [WAD] total accrued debt in pool after repay debt uint256 remainingCollateral; // [WAD] amount of borrower collateral after pull collateral - bool settledAuction; // true if repay debt settles auction - uint256 t0DebtInAuctionChange; // [WAD] change of t0 pool debt in auction after repay debt uint256 t0PoolDebt; // [WAD] amount of t0 debt in pool after repay uint256 quoteTokenToRepay; // [WAD] quote token amount to be transferred from sender to pool uint256 debtPreAction; // [WAD] The amount of borrower t0 debt before repay debt uint256 debtPostAction; // [WAD] The amount of borrower t0 debt after repay debt uint256 collateralPreAction; // [WAD] The amount of borrower collateral before repay debt uint256 collateralPostAction; // [WAD] The amount of borrower collateral after repay debt -} \ No newline at end of file +} diff --git a/src/interfaces/pool/commons/IPoolState.sol b/src/interfaces/pool/commons/IPoolState.sol index 930a99850..027e7670c 100644 --- a/src/interfaces/pool/commons/IPoolState.sol +++ b/src/interfaces/pool/commons/IPoolState.sol @@ -9,17 +9,16 @@ interface IPoolState { /** * @notice Returns details of an auction for a given borrower address. - * @param borrower_ Address of the borrower that is liquidated. - * @return kicker_ Address of the kicker that is kicking the auction. - * @return bondFactor_ The factor used for calculating bond size. - * @return bondSize_ The bond amount in quote token terms. - * @return kickTime_ Time the liquidation was initiated. - * @return kickMomp_ Price where the average loan utilizes deposit, at the time when the loan is liquidated (kicked). - * @return neutralPrice_ `Neutral Price` of auction. - * @return head_ Address of the head auction. - * @return next_ Address of the next auction in queue. - * @return prev_ Address of the prev auction in queue. - * @return alreadyTaken_ True if take has been called on auction + * @param borrower_ Address of the borrower that is liquidated. + * @return kicker_ Address of the kicker that is kicking the auction. + * @return bondFactor_ The factor used for calculating bond size. + * @return bondSize_ The bond amount in quote token terms. + * @return kickTime_ Time the liquidation was initiated. + * @return referencePrice_ Price used to determine auction start price. + * @return neutralPrice_ `Neutral Price` of auction. + * @return head_ Address of the head auction. + * @return next_ Address of the next auction in queue. + * @return prev_ Address of the prev auction in queue. */ function auctionInfo(address borrower_) external @@ -29,12 +28,11 @@ interface IPoolState { uint256 bondFactor_, uint256 bondSize_, uint256 kickTime_, - uint256 kickMomp_, + uint256 referencePrice_, uint256 neutralPrice_, address head_, address next_, - address prev_, - bool alreadyTaken_ + address prev_ ); /** @@ -60,7 +58,7 @@ interface IPoolState { * @param borrower_ Address of the borrower. * @return t0Debt_ Amount of debt borrower would have had if their loan was the first debt drawn from the pool. * @return collateral_ Amount of collateral that the borrower has deposited, in collateral token. - * @return t0Np_ t0 `Neutral Price` + * @return npTpRatio_ Np to Tp ratio of borrower at the time of last borrow or pull collateral. */ function borrowerInfo(address borrower_) external @@ -68,7 +66,7 @@ interface IPoolState { returns ( uint256 t0Debt_, uint256 collateral_, - uint256 t0Np_ + uint256 npTpRatio_ ); /** @@ -388,7 +386,7 @@ struct Loan { struct Borrower { uint256 t0Debt; // [WAD] Borrower debt time-adjusted as if it was incurred upon first loan of pool. uint256 collateral; // [WAD] Collateral deposited by borrower. - uint256 t0Np; // [WAD] Neutral Price time-adjusted as if it was incurred upon first loan of pool. + uint256 npTpRatio; // [WAD] Np to Tp ratio at the time of last borrow or pull collateral. } /**********************/ @@ -407,15 +405,14 @@ struct AuctionsState { /// @dev Struct holding liquidation state. struct Liquidation { - address kicker; // address that initiated liquidation - uint96 bondFactor; // [WAD] bond factor used to start liquidation - uint96 kickTime; // timestamp when liquidation was started - address prev; // previous liquidated borrower in auctions queue - uint96 kickMomp; // [WAD] Momp when liquidation was started - address next; // next liquidated borrower in auctions queue - uint160 bondSize; // [WAD] liquidation bond size - uint96 neutralPrice; // [WAD] Neutral Price when liquidation was started - bool alreadyTaken; // true if take has been called on auction + address kicker; // address that initiated liquidation + uint96 bondFactor; // [WAD] bond factor used to start liquidation + uint96 kickTime; // timestamp when liquidation was started + address prev; // previous liquidated borrower in auctions queue + uint96 referencePrice; // [WAD] used to calculate auction start price + address next; // next liquidated borrower in auctions queue + uint160 bondSize; // [WAD] liquidation bond size + uint96 neutralPrice; // [WAD] Neutral Price when liquidation was started } /// @dev Struct holding kicker state. diff --git a/src/interfaces/pool/commons/IPoolTakerActions.sol b/src/interfaces/pool/commons/IPoolTakerActions.sol index 5d97b5aac..8303392e1 100644 --- a/src/interfaces/pool/commons/IPoolTakerActions.sol +++ b/src/interfaces/pool/commons/IPoolTakerActions.sol @@ -27,13 +27,14 @@ interface IPoolTakerActions { * @param data_ If provided, take will assume the callee implements `IERC*Taker`. Take will send collateral to * callee before passing this data to `IERC*Taker.atomicSwapCallback`. If not provided, * the callback function will not be invoked. + * @return collateralTaken_ Amount of collateral taken from the auction (`WAD` precision for `ERC20` pools, max number of `NFT`s for `ERC721` pools). */ function take( address borrowerAddress_, uint256 maxAmount_, address callee_, bytes calldata data_ - ) external; + ) external returns (uint256 collateralTaken_); /***********************/ /*** Reserve Auction ***/ diff --git a/src/interfaces/pool/erc20/IERC20PoolBorrowerActions.sol b/src/interfaces/pool/erc20/IERC20PoolBorrowerActions.sol index 666cc95e1..e87e16f39 100644 --- a/src/interfaces/pool/erc20/IERC20PoolBorrowerActions.sol +++ b/src/interfaces/pool/erc20/IERC20PoolBorrowerActions.sol @@ -30,6 +30,7 @@ interface IERC20PoolBorrowerActions { * @param collateralAmountToPull_ The max amount of collateral to be puled from the pool (`WAD` precision). * @param recipient_ The address to receive amount of pulled collateral. * @param limitIndex_ Ensures `LUP` has not moved far from state when borrower pulls collateral. + * @return amountRepaid_ The amount of quote token repaid (`WAD` precision). */ function repayDebt( address borrowerAddress_, @@ -37,5 +38,5 @@ interface IERC20PoolBorrowerActions { uint256 collateralAmountToPull_, address recipient_, uint256 limitIndex_ - ) external; + ) external returns (uint256 amountRepaid_); } diff --git a/src/interfaces/pool/erc721/IERC721PoolBorrowerActions.sol b/src/interfaces/pool/erc721/IERC721PoolBorrowerActions.sol index fbaf4b59b..933b4d009 100644 --- a/src/interfaces/pool/erc721/IERC721PoolBorrowerActions.sol +++ b/src/interfaces/pool/erc721/IERC721PoolBorrowerActions.sol @@ -30,6 +30,7 @@ interface IERC721PoolBorrowerActions { * @param noOfNFTsToPull_ The integer number of `NFT` collateral to be puled from the pool. * @param recipient_ The address to receive amount of pulled collateral. * @param limitIndex_ Ensures `LUP` has not moved far from state when borrower pulls collateral. + * @return amountRepaid_ The amount of quote token repaid (`WAD` precision). */ function repayDebt( address borrowerAddress_, @@ -37,5 +38,5 @@ interface IERC721PoolBorrowerActions { uint256 noOfNFTsToPull_, address recipient_, uint256 limitIndex_ - ) external; + ) external returns (uint256 amountRepaid_); } diff --git a/src/libraries/external/BorrowerActions.sol b/src/libraries/external/BorrowerActions.sol index 5a69e1120..02ce36855 100644 --- a/src/libraries/external/BorrowerActions.sol +++ b/src/libraries/external/BorrowerActions.sol @@ -25,7 +25,6 @@ import { _revertOnMinDebt } from '../helpers/RevertsHelper.sol'; -import { Buckets } from '../internal/Buckets.sol'; import { Deposits } from '../internal/Deposits.sol'; import { Loans } from '../internal/Loans.sol'; import { Maths } from '../internal/Maths.sol'; @@ -51,7 +50,7 @@ library BorrowerActions { uint256 t0BorrowAmount; // [WAD] t0 amount to borrow uint256 t0DebtChange; // [WAD] additional t0 debt resulted from draw debt action bool pledge; // true if pledge action - bool stampT0Np; // true if loan's t0 neutral price should be restamped (when drawing debt or pledge settles auction) + bool stampNpTpRatio; // true if loan's Np to Tp ratio should be restamped (when drawing debt or pledge settles auction) } /// @dev Struct used for `repayDebt` function local vars. @@ -60,8 +59,7 @@ library BorrowerActions { uint256 compensatedCollateral; // [WAD] amount of borrower collateral that is compensated with LP (NFTs only) bool pull; // true if pull action bool repay; // true if repay action - bool stampT0Np; // true if loan's t0 neutral price should be restamped (when repay settles auction or pull collateral) - uint256 t0DebtInAuctionChange; // [WAD] t0 change amount of debt after repayment + bool stampNpTpRatio; // true if loan's Np to Tp ratio should be restamped (when repay settles auction or pull collateral) uint256 t0RepaidDebt; // [WAD] t0 debt repaid } @@ -93,10 +91,6 @@ library BorrowerActions { /** * @notice See `IERC20PoolBorrowerActions` and `IERC721PoolBorrowerActions` for descriptions * @dev === Write state === - * @dev - `SettlerActions._settleAuction` (`_removeAuction`): - * @dev decrement kicker locked accumulator, increment kicker claimable accumumlator - * @dev decrement auctions count accumulator - * @dev update auction queue state * @dev - `Loans.update` (`_upsert`): * @dev insert or update loan in loans array * @dev remove loan from loans array @@ -107,12 +101,10 @@ library BorrowerActions { * @dev borrower debt less than pool min debt `AmountLTMinDebt()` * @dev limit price reached `LimitIndexExceeded()` * @dev borrower cannot draw more debt `BorrowerUnderCollateralized()` - * @dev === Emit events === - * @dev - `SettlerActions._settleAuction`: `AuctionNFTSettle` or `AuctionSettle` + * @dev borrower cannot be in auction `AuctionActive()` */ function drawDebt( AuctionsState storage auctions_, - mapping(uint256 => Bucket) storage buckets_, DepositsState storage deposits_, LoansState storage loans_, PoolState calldata poolState_, @@ -127,6 +119,9 @@ library BorrowerActions { // revert if not enough pool balance to borrow if (amountToBorrow_ > maxAvailable_) revert InsufficientLiquidity(); + // revert if borrower is in auction + if(_inAuction(auctions_, borrowerAddress_)) revert AuctionActive(); + DrawDebtLocalVars memory vars; vars.pledge = collateralToPledge_ != 0; vars.borrow = amountToBorrow_ != 0; @@ -138,7 +133,6 @@ library BorrowerActions { vars.borrowerDebt = Maths.wmul(borrower.t0Debt, poolState_.inflator); - result_.inAuction = _inAuction(auctions_, borrowerAddress_); result_.debtPreAction = borrower.t0Debt; result_.collateralPreAction = borrower.collateral; result_.t0PoolDebt = poolState_.t0Debt; @@ -153,36 +147,6 @@ library BorrowerActions { result_.remainingCollateral += collateralToPledge_; result_.newLup = Deposits.getLup(deposits_, result_.poolDebt); - // if loan is auctioned and becomes collateralized by newly pledged collateral then settle auction - if ( - result_.inAuction && - _isCollateralized(vars.borrowerDebt, borrower.collateral, result_.newLup, poolState_.poolType) - ) { - // stamp borrower t0Np when exiting from auction - vars.stampT0Np = true; - - // borrower becomes re-collateralized, entire borrower debt is removed from pool auctions debt accumulator - result_.inAuction = false; - result_.settledAuction = true; - result_.t0DebtInAuctionChange = borrower.t0Debt; - - // settle auction and update borrower's collateral with value after settlement - ( - result_.remainingCollateral, - vars.compensatedCollateral - ) = SettlerActions._settleAuction( - auctions_, - buckets_, - deposits_, - borrowerAddress_, - borrower.collateral, - poolState_.poolType - ); - result_.poolCollateral -= vars.compensatedCollateral; - - borrower.collateral = result_.remainingCollateral; - } - // add new amount of collateral to pledge to pool balance result_.poolCollateral += collateralToPledge_; } @@ -191,9 +155,6 @@ library BorrowerActions { // only intended recipient can borrow quote if (borrowerAddress_ != msg.sender) revert BorrowerNotSender(); - // an auctioned borrower in not allowed to draw more debt (even if collateralized at the new LUP) if auction is not settled - if (result_.inAuction) revert AuctionActive(); - vars.t0BorrowAmount = Maths.ceilWdiv(amountToBorrow_, poolState_.inflator); // t0 debt change is t0 amount to borrow plus the origination fee @@ -225,22 +186,18 @@ library BorrowerActions { revert BorrowerUnderCollateralized(); } - // stamp borrower t0Np when draw debt - vars.stampT0Np = true; + // stamp borrower Np to Tp ratio when draw debt + vars.stampNpTpRatio = true; } // update loan state Loans.update( loans_, - auctions_, - deposits_, borrower, borrowerAddress_, - result_.poolDebt, poolState_.rate, - result_.newLup, - result_.inAuction, - vars.stampT0Np + false, // loan not in auction + vars.stampNpTpRatio ); result_.debtPostAction = borrower.t0Debt; @@ -250,10 +207,6 @@ library BorrowerActions { /** * @notice See `IERC20PoolBorrowerActions` and `IERC721PoolBorrowerActions` for descriptions * @dev === Write state === - * @dev - `SettlerActions._settleAuction` (`_removeAuction`): - * @dev decrement kicker locked accumulator, increment kicker claimable accumumlator - * @dev decrement auctions count accumulator - * @dev update auction queue state * @dev - `Loans.update` (`_upsert`): * @dev insert or update loan in loans array * @dev remove loan from loans array @@ -264,12 +217,10 @@ library BorrowerActions { * @dev borrower not sender `BorrowerNotSender()` * @dev not enough collateral to pull `InsufficientCollateral()` * @dev limit price reached `LimitIndexExceeded()` - * @dev === Emit events === - * @dev - `SettlerActions._settleAuction`: `AuctionNFTSettle` or `AuctionSettle` + * @dev borrower cannot be in auction `AuctionActive()` */ function repayDebt( AuctionsState storage auctions_, - mapping(uint256 => Bucket) storage buckets_, DepositsState storage deposits_, LoansState storage loans_, PoolState calldata poolState_, @@ -287,11 +238,12 @@ library BorrowerActions { // revert if no amount to pull or repay if (!vars.repay && !vars.pull) revert InvalidAmount(); + if(_inAuction(auctions_, borrowerAddress_)) revert AuctionActive(); + Borrower memory borrower = loans_.borrowers[borrowerAddress_]; vars.borrowerDebt = Maths.wmul(borrower.t0Debt, poolState_.inflator); - result_.inAuction = _inAuction(auctions_, borrowerAddress_); result_.debtPreAction = borrower.t0Debt; result_.collateralPreAction = borrower.collateral; result_.t0PoolDebt = poolState_.t0Debt; @@ -329,39 +281,6 @@ library BorrowerActions { ); result_.newLup = Deposits.getLup(deposits_, result_.poolDebt); - - // if loan is auctioned and becomes collateralized by repaying debt then settle auction - if (result_.inAuction) { - if (_isCollateralized(vars.borrowerDebt, borrower.collateral, result_.newLup, poolState_.poolType)) { - // stamp borrower t0Np when exiting from auction - vars.stampT0Np = true; - - // borrower becomes re-collateralized, entire borrower debt is removed from pool auctions debt accumulator - result_.inAuction = false; - result_.settledAuction = true; - result_.t0DebtInAuctionChange = borrower.t0Debt; - - // settle auction and update borrower's collateral with value after settlement - ( - result_.remainingCollateral, - vars.compensatedCollateral - ) = SettlerActions._settleAuction( - auctions_, - buckets_, - deposits_, - borrowerAddress_, - borrower.collateral, - poolState_.poolType - ); - result_.poolCollateral -= vars.compensatedCollateral; - - borrower.collateral = result_.remainingCollateral; - } else { - // partial repay, remove only the paid debt from pool auctions debt accumulator - result_.t0DebtInAuctionChange = vars.t0RepaidDebt; - } - } - borrower.t0Debt -= vars.t0RepaidDebt; } @@ -369,9 +288,6 @@ library BorrowerActions { // only intended recipient can pull collateral if (borrowerAddress_ != msg.sender) revert BorrowerNotSender(); - // an auctioned borrower in not allowed to pull collateral (even if collateralized at the new LUP) if auction is not settled - if (result_.inAuction) revert AuctionActive(); - // calculate LUP only if it wasn't calculated in repay action if (!vars.repay) result_.newLup = Deposits.getLup(deposits_, result_.poolDebt); @@ -382,8 +298,8 @@ library BorrowerActions { borrower.collateral - encumberedCollateral < collateralAmountToPull_ ) revert InsufficientCollateral(); - // stamp borrower t0Np when pull collateral action - vars.stampT0Np = true; + // stamp borrower Np to Tp ratio when pull collateral action + vars.stampNpTpRatio = true; borrower.collateral -= collateralAmountToPull_; @@ -396,15 +312,11 @@ library BorrowerActions { // update loan state Loans.update( loans_, - auctions_, - deposits_, borrower, borrowerAddress_, - result_.poolDebt, poolState_.rate, - result_.newLup, - result_.inAuction, - vars.stampT0Np + false, // loan not in auction + vars.stampNpTpRatio ); result_.debtPostAction = borrower.t0Debt; @@ -449,18 +361,14 @@ library BorrowerActions { ) ) revert BorrowerUnderCollateralized(); - // update loan state to stamp Neutral Price + // update loan state to stamp Np to Tp ratio Loans.update( loans_, - auctions_, - deposits_, borrower, msg.sender, - poolState_.debt, poolState_.rate, - newLup_, false, // loan not in auction - true // stamp Neutral Price of the loan + true // stamp Np to Tp ratio of the loan ); emit LoanStamped(msg.sender); diff --git a/src/libraries/external/KickerActions.sol b/src/libraries/external/KickerActions.sol index 909a7ebe0..39f9e47e0 100644 --- a/src/libraries/external/KickerActions.sol +++ b/src/libraries/external/KickerActions.sol @@ -25,8 +25,7 @@ import { } from '../../interfaces/pool/commons/IPoolInternals.sol'; import { - MAX_NEUTRAL_PRICE, - _auctionPrice, + MAX_INFLATED_PRICE, _bondParams, _bpf, _claimableReserves, @@ -59,12 +58,10 @@ library KickerActions { uint256 borrowerDebt; // [WAD] the accrued debt of kicked borrower uint256 borrowerCollateral; // [WAD] amount of kicked borrower collateral uint256 neutralPrice; // [WAD] neutral price recorded in kick action - uint256 noOfLoans; // number of loans and auctions in pool (used to calculate MOMP) - uint256 momp; // [WAD] MOMP of kicked auction + uint256 htp; // [WAD] highest threshold price in pool + uint256 referencePrice; // [WAD] used to calculate auction start price uint256 bondFactor; // [WAD] bond factor of kicked auction uint256 bondSize; // [WAD] bond size of kicked auction - uint256 t0KickPenalty; // [WAD] t0 debt added as kick penalty - uint256 kickPenalty; // [WAD] current debt added as kick penalty } /// @dev Struct used for `lenderKick` function local vars. @@ -200,13 +197,12 @@ library KickerActions { * @dev no reserves to claim `NoReserves()` * @dev === Emit events === * @dev - `KickReserveAuction` - * @return kickerAward_ The `LP`s awarded to reserve auction kicker. */ function kickReserveAuction( AuctionsState storage auctions_, ReserveAuctionState storage reserveAuction_, KickReserveAuctionParams calldata params_ - ) external returns (uint256 kickerAward_) { + ) external { // retrieve timestamp of latest burn event and last burn timestamp uint256 latestBurnEpoch = reserveAuction_.latestBurnEventEpoch; uint256 lastBurnTimestamp = reserveAuction_.burnEvents[latestBurnEpoch].timestamp; @@ -226,9 +222,7 @@ library KickerActions { params_.poolBalance ); - kickerAward_ = Maths.wmul(0.01 * 1e18, claimable); - - curUnclaimedAuctionReserve += claimable - kickerAward_; + curUnclaimedAuctionReserve += claimable; if (curUnclaimedAuctionReserve == 0) revert NoReserves(); @@ -293,9 +287,8 @@ library KickerActions { Borrower storage borrower = loans_.borrowers[borrowerAddress_]; - kickResult_.debtPreAction = borrower.t0Debt; + kickResult_.t0KickedDebt = borrower.t0Debt; kickResult_.collateralPreAction = borrower.collateral; - kickResult_.t0KickedDebt = kickResult_.debtPreAction ; // add amount to remove to pool debt in order to calculate proposed LUP // for regular kick this is the currrent LUP in pool @@ -312,28 +305,22 @@ library KickerActions { } // calculate auction params + // neutral price = Tp * Np to Tp ratio // neutral price is capped at 50 * max pool price vars.neutralPrice = Maths.min( - Maths.wmul(borrower.t0Np, poolState_.inflator), - MAX_NEUTRAL_PRICE + Math.mulDiv(vars.borrowerDebt, borrower.npTpRatio, vars.borrowerCollateral), + MAX_INFLATED_PRICE ); // check if NP is not less than price at the limit index provided by the kicker - done to prevent frontrunning kick auction call with a large amount of loan // which will make it harder for kicker to earn a reward and more likely that the kicker is penalized _revertIfPriceDroppedBelowLimit(vars.neutralPrice, limitIndex_); - vars.noOfLoans = Loans.noOfLoans(loans_) + auctions_.noOfAuctions; - - vars.momp = _priceAt( - Deposits.findIndexOfSum( - deposits_, - Maths.wdiv(poolState_.debt, vars.noOfLoans * 1e18) - ) - ); + vars.htp = Maths.wmul(Loans.getMax(loans_).thresholdPrice, poolState_.inflator); + vars.referencePrice = Maths.min(Maths.max(vars.htp, vars.neutralPrice), MAX_INFLATED_PRICE); (vars.bondFactor, vars.bondSize) = _bondParams( vars.borrowerDebt, - vars.borrowerCollateral, - vars.momp + borrower.npTpRatio ); // record liquidation info @@ -343,7 +330,7 @@ library KickerActions { borrowerAddress_, vars.bondSize, vars.bondFactor, - vars.momp, + vars.referencePrice, vars.neutralPrice ); @@ -353,23 +340,9 @@ library KickerActions { // remove kicked loan from heap Loans.remove(loans_, borrowerAddress_, loans_.indices[borrowerAddress_]); - // when loan is kicked, penalty of three months of interest is added - vars.t0KickPenalty = Maths.wdiv(Maths.wmul(kickResult_.t0KickedDebt, poolState_.rate), 4 * 1e18); - vars.kickPenalty = Maths.wmul(vars.t0KickPenalty, poolState_.inflator); - - kickResult_.t0PoolDebt = poolState_.t0Debt + vars.t0KickPenalty; - kickResult_.t0KickedDebt += vars.t0KickPenalty; - - // recalculate LUP with new pool debt (including kick penalty) - kickResult_.poolDebt = Maths.wmul(kickResult_.t0PoolDebt, poolState_.inflator); - kickResult_.lup = Deposits.getLup(deposits_, kickResult_.poolDebt); - - // update borrower debt with kicked debt penalty - borrower.t0Debt = kickResult_.t0KickedDebt; - emit Kick( borrowerAddress_, - vars.borrowerDebt + vars.kickPenalty, + vars.borrowerDebt, vars.borrowerCollateral, vars.bondSize ); @@ -417,7 +390,7 @@ library KickerActions { * @param borrowerAddress_ Address of the borrower that is kicked. * @param bondSize_ Bond size to cover newly kicked auction. * @param bondFactor_ Bond factor of the newly kicked auction. - * @param momp_ Current pool `MOMP`. + * @param referencePrice_ Used to calculate auction start price. * @param neutralPrice_ Current pool `Neutral Price`. */ function _recordAuction( @@ -426,16 +399,16 @@ library KickerActions { address borrowerAddress_, uint256 bondSize_, uint256 bondFactor_, - uint256 momp_, + uint256 referencePrice_, uint256 neutralPrice_ ) internal { // record liquidation info - liquidation_.kicker = msg.sender; - liquidation_.kickTime = uint96(block.timestamp); - liquidation_.kickMomp = uint96(momp_); // cannot exceed max price enforced by _priceAt() function - liquidation_.bondSize = SafeCast.toUint160(bondSize_); - liquidation_.bondFactor = SafeCast.toUint96(bondFactor_); - liquidation_.neutralPrice = SafeCast.toUint96(neutralPrice_); + liquidation_.kicker = msg.sender; + liquidation_.kickTime = uint96(block.timestamp); + liquidation_.referencePrice = SafeCast.toUint96(referencePrice_); + liquidation_.bondSize = SafeCast.toUint160(bondSize_); + liquidation_.bondFactor = SafeCast.toUint96(bondFactor_); + liquidation_.neutralPrice = SafeCast.toUint96(neutralPrice_); // increment number of active auctions ++auctions_.noOfAuctions; diff --git a/src/libraries/external/PoolCommons.sol b/src/libraries/external/PoolCommons.sol index 659a6beae..164dff91a 100644 --- a/src/libraries/external/PoolCommons.sol +++ b/src/libraries/external/PoolCommons.sol @@ -298,8 +298,8 @@ library PoolCommons { newInterestRate_ = Maths.wmul(poolState_.rate, DECREASE_COEFFICIENT); } - // bound rates between 10 bps and 50000% - newInterestRate_ = Maths.min(500 * 1e18, Maths.max(0.001 * 1e18, newInterestRate_)); + // bound rates between 10 bps and 400% + newInterestRate_ = Maths.min(4 * 1e18, Maths.max(0.001 * 1e18, newInterestRate_)); } /** diff --git a/src/libraries/external/SettlerActions.sol b/src/libraries/external/SettlerActions.sol index b42888023..6f065d85f 100644 --- a/src/libraries/external/SettlerActions.sol +++ b/src/libraries/external/SettlerActions.sol @@ -226,8 +226,7 @@ library SettlerActions { compensatedCollateral_ = borrowerCollateral_ - remainingCollateral_; uint256 auctionPrice = _auctionPrice( - auctions_.liquidations[borrowerAddress_].kickMomp, - auctions_.liquidations[borrowerAddress_].neutralPrice, + auctions_.liquidations[borrowerAddress_].referencePrice, auctions_.liquidations[borrowerAddress_].kickTime ); diff --git a/src/libraries/external/TakerActions.sol b/src/libraries/external/TakerActions.sol index f7131b744..04624aafa 100644 --- a/src/libraries/external/TakerActions.sol +++ b/src/libraries/external/TakerActions.sol @@ -25,10 +25,10 @@ import { import { _auctionPrice, _bpf, - _isCollateralized, _priceAt, _reserveAuctionPrice, - _roundToScale + _roundToScale, + _roundUpToScale } from '../helpers/PoolHelper.sol'; import { _revertOnMinDebt } from '../helpers/RevertsHelper.sol'; @@ -74,24 +74,26 @@ library TakerActions { /// @dev Struct used for `take` function local vars. struct TakeLocalVars { - uint256 auctionPrice; // [WAD] The price of auction. - uint256 bondChange; // [WAD] The change made on the bond size (beeing reward or penalty). - uint256 borrowerDebt; // [WAD] The accrued debt of auctioned borrower. - int256 bpf; // The bond penalty factor. - uint256 bucketPrice; // [WAD] The bucket price. - uint256 bucketScale; // [WAD] The bucket scale. - uint256 collateralAmount; // [WAD] The amount of collateral taken. - uint256 excessQuoteToken; // [WAD] Difference of quote token that borrower receives after take (for fractional NFT only) - uint256 factor; // The take factor, calculated based on bond penalty factor. - bool isRewarded; // True if kicker is rewarded (auction price lower than neutral price), false if penalized (auction price greater than neutral price). - address kicker; // Address of auction kicker. - uint256 quoteTokenAmount; // [WAD] Scaled quantity in Fenwick tree and before 1-bpf factor, paid for collateral - uint256 t0RepayAmount; // [WAD] The amount of debt (quote tokens) that is recovered / repayed by take t0 terms. - uint256 t0BorrowerDebt; // [WAD] Borrower's t0 debt. - uint256 t0DebtPenalty; // [WAD] Borrower's t0 penalty - 7% from current debt if intial take, 0 otherwise. - uint256 unscaledDeposit; // [WAD] Unscaled bucket quantity - uint256 unscaledQuoteTokenAmount; // [WAD] The unscaled token amount that taker should pay for collateral taken. - } + uint256 auctionPrice; // [WAD] The price of auction. + uint256 bondChange; // [WAD] The change made on the bond size (beeing reward or penalty). + uint256 borrowerDebt; // [WAD] The accrued debt of auctioned borrower. + int256 bpf; // The bond penalty factor. + uint256 bondFactor; // [WAD] The bond factor. + uint256 bucketPrice; // [WAD] The bucket price. + uint256 bucketScale; // [WAD] The bucket scale. + uint256 collateralAmount; // [WAD] The amount of collateral taken. + uint256 excessQuoteToken; // [WAD] Difference of quote token that borrower receives after take (for fractional NFT only) + uint256 factor; // The take factor, calculated based on bond penalty factor. + bool isRewarded; // True if kicker is rewarded (auction price lower than neutral price), false if penalized (auction price greater than neutral price). + address kicker; // Address of auction kicker. + uint256 quoteTokenAmount; // [WAD] Scaled quantity in Fenwick tree and before 1-bpf factor, paid for collateral + uint256 t0RepayAmount; // [WAD] The amount of debt (quote tokens) that is recovered / repayed by take t0 terms. + uint256 t0BorrowerDebt; // [WAD] Borrower's t0 debt. + uint256 unscaledDeposit; // [WAD] Unscaled bucket quantity + uint256 unscaledQuoteTokenAmount; // [WAD] The unscaled token amount that taker should pay for collateral taken. + uint256 depositCollateralConstraint; // [WAD] Constraint on bucket take from deposit present in bucket + uint256 debtCollateralConstraint; // [WAD] Constraint on take due to debt. + } /**************/ /*** Events ***/ @@ -108,6 +110,7 @@ library TakerActions { /**************/ // See `IPoolErrors` for descriptions + error AuctionNotTakeable(); error AuctionPriceGtBucketPrice(); error CollateralRoundingNeededButNotPossible(); error InsufficientLiquidity(); @@ -117,7 +120,6 @@ library TakerActions { error NoReserves(); error NoReservesAuction(); error ReserveAuctionTooSoon(); - error TakeNotPastCooldown(); /***************************/ /*** External Functions ***/ @@ -167,7 +169,6 @@ library TakerActions { borrower.collateral -= vars.collateralAmount; borrower.t0Debt = vars.t0BorrowerDebt - vars.t0RepayAmount; // update pool params after take - poolState_.t0Debt += vars.t0DebtPenalty; poolState_.t0Debt -= vars.t0RepayAmount; poolState_.debt = Maths.wmul(poolState_.t0Debt, poolState_.inflator); @@ -185,7 +186,6 @@ library TakerActions { result_.t0PoolDebt = poolState_.t0Debt; result_.poolDebt = poolState_.debt; result_.collateralAmount = vars.collateralAmount; - result_.t0DebtPenalty = vars.t0DebtPenalty; // if settled then debt in auction changed is the entire borrower debt, otherwise only repaid amount result_.t0DebtInAuctionChange = result_.settledAuction ? vars.t0BorrowerDebt : vars.t0RepayAmount; } @@ -241,7 +241,6 @@ library TakerActions { borrower.collateral -= vars.collateralAmount; borrower.t0Debt = vars.t0BorrowerDebt - vars.t0RepayAmount; // update pool params after take - poolState_.t0Debt += vars.t0DebtPenalty; poolState_.t0Debt -= vars.t0RepayAmount; poolState_.debt = Maths.wmul(poolState_.t0Debt, poolState_.inflator); @@ -259,7 +258,6 @@ library TakerActions { result_.t0PoolDebt = poolState_.t0Debt; result_.poolDebt = poolState_.debt; result_.collateralAmount = vars.collateralAmount; - result_.t0DebtPenalty = vars.t0DebtPenalty; result_.quoteTokenAmount = vars.quoteTokenAmount; result_.excessQuoteToken = vars.excessQuoteToken; // if settled then debt in auction changed is the entire borrower debt, otherwise only repaid amount @@ -341,6 +339,9 @@ library TakerActions { ) internal returns (TakeLocalVars memory vars_) { Liquidation storage liquidation = auctions_.liquidations[params_.borrower]; + // Auction may not be taken in the same block it was kicked + if (liquidation.kickTime == block.timestamp) revert AuctionNotTakeable(); + vars_ = _prepareTake( liquidation, borrower_.t0Debt, @@ -421,6 +422,9 @@ library TakerActions { ) internal returns (TakeLocalVars memory vars_) { Liquidation storage liquidation = auctions_.liquidations[params_.borrower]; + // Auction may not be taken in the same block it was kicked + if (liquidation.kickTime == block.timestamp) revert AuctionNotTakeable(); + vars_= _prepareTake( liquidation, borrower_.t0Debt, @@ -475,7 +479,7 @@ library TakerActions { /** * @notice Performs update of an auctioned loan that was taken (using bucket or regular take). - * @notice If borrower becomes recollateralized then auction is settled. Update loan's state. + * @notice If borrower's debt has been fully covered, then auction is settled. Update loan's state. * @dev === Reverts on === * @dev borrower debt less than pool min debt `AmountLTMinDebt()` * @param auctions_ Struct for pool auctions state. @@ -515,12 +519,10 @@ library TakerActions { poolState_.quoteTokenScale ); - // calculate new lup with repaid debt from take - newLup_ = Deposits.getLup(deposits_, poolState_.debt); - remainingCollateral_ = borrower_.collateral; - if (_isCollateralized(borrowerDebt, borrower_.collateral, newLup_, poolState_.poolType)) { + // if debt is fully repaid, settle the auction + if (borrower_.t0Debt == 0) { settledAuction_ = true; // settle auction and update borrower's collateral with value after settlement @@ -536,19 +538,18 @@ library TakerActions { borrower_.collateral = remainingCollateral_; } - // update loan state, stamp borrower t0Np only when exiting from auction + // update loan state, stamp borrower Np to Tp ratio only when exiting from auction Loans.update( loans_, - auctions_, - deposits_, borrower_, borrowerAddress_, - poolState_.debt, poolState_.rate, - newLup_, !settledAuction_, - settledAuction_ // stamp borrower t0Np if exiting from auction + settledAuction_ // stamp borrower Np to Tp ratio if exiting from auction ); + + // calculate new lup with repaid debt from take + newLup_ = Deposits.getLup(deposits_, poolState_.debt); } /** @@ -676,11 +677,8 @@ library TakerActions { /** * @notice Utility function to validate take and calculate take's parameters. - * @dev write state: - * - update liquidation.alreadyTaken state * @dev reverts on: * - loan is not in auction NoAuction() - * - in 1 hour cool down period TakeNotPastCooldown() * @param liquidation_ Liquidation struct holding auction details. * @param t0Debt_ Borrower t0 debt. * @param collateral_ Borrower collateral. @@ -688,31 +686,23 @@ library TakerActions { * @return vars The prepared vars for take action. */ function _prepareTake( - Liquidation storage liquidation_, + Liquidation memory liquidation_, uint256 t0Debt_, uint256 collateral_, uint256 inflator_ - ) internal returns (TakeLocalVars memory vars) { + ) internal view returns (TakeLocalVars memory vars) { uint256 kickTime = liquidation_.kickTime; if (kickTime == 0) revert NoAuction(); - if (block.timestamp - kickTime <= 1 hours) revert TakeNotPastCooldown(); vars.t0BorrowerDebt = t0Debt_; - // if first take borrower debt is increased by 7% penalty - if (!liquidation_.alreadyTaken) { - vars.t0DebtPenalty = Maths.wmul(t0Debt_, 0.07 * 1e18); - vars.t0BorrowerDebt += vars.t0DebtPenalty; - - liquidation_.alreadyTaken = true; - } - vars.borrowerDebt = Maths.wmul(vars.t0BorrowerDebt, inflator_); uint256 neutralPrice = liquidation_.neutralPrice; - vars.auctionPrice = _auctionPrice(liquidation_.kickMomp, neutralPrice, kickTime); + vars.auctionPrice = _auctionPrice(liquidation_.referencePrice, kickTime); + vars.bondFactor = liquidation_.bondFactor; vars.bpf = _bpf( vars.borrowerDebt, collateral_, @@ -740,39 +730,46 @@ library TakerActions { TakeLocalVars memory ) { // price is the current auction price, which is the price paid by the LENDER for collateral - // from the borrower point of view, the price is actually (1-bpf) * price, as the rewards to the - // bond holder are effectively paid for by the borrower. - uint256 borrowerPayoffFactor = (vars.isRewarded) ? Maths.WAD - uint256(vars.bpf) : Maths.WAD; - uint256 borrowerPrice = (vars.isRewarded) ? Maths.wmul(borrowerPayoffFactor, vars.auctionPrice) : vars.auctionPrice; + // from the borrower point of view, there is a take penalty of (1.25 * bondFactor - 0.25 * bpf) + // Therefore the price is actually price * (1.0 - 1.25 * bondFactor + 0.25 * bpf) + uint256 takePenaltyFactor = uint256(5 * int256(vars.bondFactor) - vars.bpf + 3) / 4; // Round up + uint256 borrowerPrice = Maths.floorWmul(vars.auctionPrice, Maths.WAD - takePenaltyFactor); + + // To determine the value of quote token removed from a bucket in a bucket take call, we need to account for whether the bond is + // rewarded or not. If the bond is rewarded, we need to remove the bond reward amount from the amount removed, else it's simply the + // collateral times auction price. + uint256 netRewardedPrice = (vars.isRewarded) ? Maths.wmul(Maths.WAD - uint256(vars.bpf), vars.auctionPrice) : vars.auctionPrice; + + // auctions may not be zero-bid; prevent divide-by-zero in constraint calculations + if (vars.auctionPrice == 0) revert InvalidAmount(); - // If there is no unscaled quote token bound, then we pass in max, but that cannot be scaled without an overflow. So we check in the line below. - vars.quoteTokenAmount = (vars.unscaledDeposit != type(uint256).max) ? Maths.wmul(vars.unscaledDeposit, vars.bucketScale) : type(uint256).max; + // Collateral taken in bucket takes is constrained by the deposit available at the price including the reward. This is moot in the case of takes. + vars.depositCollateralConstraint = (vars.unscaledDeposit != type(uint256).max) ? _roundToScale(Math.mulDiv(vars.unscaledDeposit, vars.bucketScale, netRewardedPrice), collateralScale_) : type(uint256).max; - uint256 borrowerCollateralValue = Maths.wmul(totalCollateral_, borrowerPrice); + // Collateral taken is also constained by the borrower's debt, at the price they receive. + vars.debtCollateralConstraint = borrowerPrice != 0 ? _roundUpToScale(Maths.ceilWdiv(vars.borrowerDebt, borrowerPrice), collateralScale_) : type(uint256).max; - if (vars.quoteTokenAmount <= vars.borrowerDebt && vars.quoteTokenAmount <= borrowerCollateralValue) { + if (vars.depositCollateralConstraint <= vars.debtCollateralConstraint && vars.depositCollateralConstraint <= totalCollateral_) { // quote token used to purchase is constraining factor - vars.collateralAmount = _roundToScale(Maths.wdiv(vars.quoteTokenAmount, borrowerPrice), collateralScale_); + vars.collateralAmount = vars.depositCollateralConstraint; vars.quoteTokenAmount = Maths.wmul(vars.collateralAmount, vars.auctionPrice); vars.t0RepayAmount = Math.mulDiv(vars.collateralAmount, borrowerPrice, inflator_); vars.unscaledQuoteTokenAmount = Maths.min( vars.unscaledDeposit, - Math.mulDiv(vars.collateralAmount, borrowerPrice, vars.bucketScale) + Math.mulDiv(vars.collateralAmount, netRewardedPrice, vars.bucketScale) ); - - } else if (vars.borrowerDebt <= borrowerCollateralValue) { + } else if (vars.debtCollateralConstraint <= totalCollateral_) { // borrower debt is constraining factor - vars.collateralAmount = _roundToScale(Maths.wdiv(vars.borrowerDebt, borrowerPrice), collateralScale_); + vars.collateralAmount = vars.debtCollateralConstraint; vars.t0RepayAmount = vars.t0BorrowerDebt; - vars.unscaledQuoteTokenAmount = Maths.wdiv(vars.borrowerDebt, vars.bucketScale); - - vars.quoteTokenAmount = (vars.isRewarded) ? Maths.wdiv(vars.borrowerDebt, borrowerPayoffFactor) : vars.borrowerDebt; + vars.unscaledQuoteTokenAmount = Math.mulDiv(vars.collateralAmount, netRewardedPrice, vars.bucketScale); + vars.quoteTokenAmount = Maths.wdiv(vars.borrowerDebt, Maths.WAD - takePenaltyFactor); } else { // collateral available is constraint vars.collateralAmount = totalCollateral_; vars.t0RepayAmount = Math.mulDiv(totalCollateral_, borrowerPrice, inflator_); - vars.unscaledQuoteTokenAmount = Math.mulDiv(totalCollateral_, borrowerPrice, vars.bucketScale); + vars.unscaledQuoteTokenAmount = Math.mulDiv(totalCollateral_, netRewardedPrice, vars.bucketScale); vars.quoteTokenAmount = Maths.wmul(vars.collateralAmount, vars.auctionPrice); } diff --git a/src/libraries/helpers/PoolHelper.sol b/src/libraries/helpers/PoolHelper.sol index afb6e633c..621001e82 100644 --- a/src/libraries/helpers/PoolHelper.sol +++ b/src/libraries/helpers/PoolHelper.sol @@ -25,7 +25,7 @@ import { Maths } from '../internal/Maths.sol'; uint256 constant MIN_PRICE = 99_836_282_890; uint256 constant MAX_PRICE = 1_004_968_987.606512354182109771 * 1e18; - uint256 constant MAX_NEUTRAL_PRICE = 50_248_449_380.325617709105488550 * 1e18; // 50 * MAX_PRICE + uint256 constant MAX_INFLATED_PRICE = 50_248_449_380.325617709105488550 * 1e18; // 50 * MAX_PRICE /// @dev deposit buffer (extra margin) used for calculating reserves uint256 constant DEPOSIT_BUFFER = 1.000000001 * 1e18; @@ -346,24 +346,27 @@ import { Maths } from '../internal/Maths.sol'; /** * @notice Calculates auction price. - * @param kickMomp_ `MOMP` recorded at the time of kick. - * @param neutralPrice_ `Neutral Price` of the auction. - * @param kickTime_ Time when auction was kicked. - * @return price_ Calculated auction price. + * @param referencePrice_ Recorded at kick, used to calculate start price. + * @param kickTime_ Time when auction was kicked. + * @return price_ Calculated auction price. */ function _auctionPrice( - uint256 kickMomp_, - uint256 neutralPrice_, + uint256 referencePrice_, uint256 kickTime_ ) view returns (uint256 price_) { - uint256 elapsedHours = Maths.wdiv((block.timestamp - kickTime_) * 1e18, 1 hours * 1e18); - - elapsedHours -= Maths.min(elapsedHours, 1e18); // price locked during cure period - - int256 timeAdjustment = PRBMathSD59x18.mul(-1 * 1e18, int256(elapsedHours)); - uint256 referencePrice = Maths.max(kickMomp_, neutralPrice_); - - price_ = 32 * Maths.wmul(referencePrice, uint256(PRBMathSD59x18.exp2(timeAdjustment))); + uint256 elapsedMinutes = Maths.wdiv((block.timestamp - kickTime_) * 1e18, 1 minutes * 1e18); + + int256 timeAdjustment; + if (elapsedMinutes < 120 * 1e18) { + timeAdjustment = PRBMathSD59x18.mul(-1 * 1e18, int256(elapsedMinutes / 20)); + price_ = 256 * Maths.wmul(referencePrice_, uint256(PRBMathSD59x18.exp2(timeAdjustment))); + } else if (elapsedMinutes < 840 * 1e18) { + timeAdjustment = PRBMathSD59x18.mul(-1 * 1e18, int256((elapsedMinutes - 120 * 1e18) / 120)); + price_ = 4 * Maths.wmul(referencePrice_, uint256(PRBMathSD59x18.exp2(timeAdjustment))); + } else { + timeAdjustment = PRBMathSD59x18.mul(-1 * 1e18, int256((elapsedMinutes - 840 * 1e18) / 60)); + price_ = Maths.wmul(referencePrice_, uint256(PRBMathSD59x18.exp2(timeAdjustment))) / 16; + } } /** @@ -409,29 +412,18 @@ import { Maths } from '../internal/Maths.sol'; /** * @notice Calculates bond parameters of an auction. - * @param borrowerDebt_ Borrower's debt before entering in liquidation. - * @param collateral_ Borrower's collateral before entering in liquidation. - * @param momp_ Current pool `momp`. + * @param borrowerDebt_ Borrower's debt before entering in liquidation. + * @param npTpRatio_ Borrower's Np to Tp ratio */ function _bondParams( uint256 borrowerDebt_, - uint256 collateral_, - uint256 momp_ + uint256 npTpRatio_ ) pure returns (uint256 bondFactor_, uint256 bondSize_) { - uint256 thresholdPrice = (borrowerDebt_ * Maths.WAD) / collateral_; - - // bondFactor = min(30%, max(1%, (MOMP - thresholdPrice) / MOMP)) - if (thresholdPrice >= momp_) { - bondFactor_ = 0.01 * 1e18; - } else { - bondFactor_ = Maths.min( - 0.3 * 1e18, - Maths.max( - 0.01 * 1e18, - 1e18 - Maths.wdiv(thresholdPrice, momp_) - ) - ); - } + // bondFactor = min((NP-to-TP-ratio - 1)/10, 0.03) + bondFactor_ = Maths.min( + 0.03 * 1e18, + (npTpRatio_ - 1e18) / 10 + ); bondSize_ = Maths.wmul(bondFactor_, borrowerDebt_); } diff --git a/src/libraries/internal/Deposits.sol b/src/libraries/internal/Deposits.sol index a0bb157c0..428997f05 100644 --- a/src/libraries/internal/Deposits.sol +++ b/src/libraries/internal/Deposits.sol @@ -71,7 +71,7 @@ library Deposits { /** * @notice Finds index and sum of first bucket that EXCEEDS the given sum - * @dev Used in `LUP` and `MOMP` calculation + * @dev Used in `LUP` calculation * @param deposits_ Struct for deposits state. * @param targetSum_ The sum to find index for. * @return sumIndex_ Smallest index where prefixsum greater than the sum. @@ -134,7 +134,7 @@ library Deposits { /** * @notice Finds index of passed sum. Helper function for `findIndexAndSumOfSum`. - * @dev Used in `LUP` and `MOMP` calculation + * @dev Used in `LUP` calculation * @param deposits_ Deposits state struct. * @param sum_ The sum to find index for. * @return sumIndex_ Smallest index where prefixsum greater than the sum. diff --git a/src/libraries/internal/Loans.sol b/src/libraries/internal/Loans.sol index c7f8e5f00..764b9ef20 100644 --- a/src/libraries/internal/Loans.sol +++ b/src/libraries/internal/Loans.sol @@ -2,6 +2,8 @@ pragma solidity 0.8.18; +import { PRBMathSD59x18 } from "@prb-math/contracts/PRBMathSD59x18.sol"; + import { AuctionsState, Borrower, @@ -61,27 +63,19 @@ library Loans { * @dev remove loan from `loans` array * @dev - update borrower in `address => borrower` mapping * @param loans_ Holds loans heap data. - * @param auctions_ Struct for pool auctions state. - * @param deposits_ Struct for pool deposits state. * @param borrower_ Borrower struct with borrower details. * @param borrowerAddress_ Borrower's address to update. - * @param poolDebt_ Pool's current debt. * @param poolRate_ Pool's current rate. - * @param lup_ Current LUP. * @param inAuction_ Whether the loan is in auction or not. - * @param t0NpUpdate_ Whether the neutral price of borrower should be updated or not. + * @param npTpRatioUpdate_ Whether the Np to Tp ratio of borrower should be updated or not. */ function update( LoansState storage loans_, - AuctionsState storage auctions_, - DepositsState storage deposits_, Borrower memory borrower_, address borrowerAddress_, - uint256 poolDebt_, uint256 poolRate_, - uint256 lup_, bool inAuction_, - bool t0NpUpdate_ + bool npTpRatioUpdate_ ) internal { bool activeBorrower = borrower_.t0Debt != 0 && borrower_.collateral != 0; @@ -105,16 +99,9 @@ library Loans { } } - // update t0 neutral price of borrower - if (t0NpUpdate_) { - if (t0ThresholdPrice != 0) { - uint256 loansInPool = loans_.loans.length - 1 + auctions_.noOfAuctions; - uint256 curMomp = _priceAt(Deposits.findIndexOfSum(deposits_, Maths.wdiv(poolDebt_, loansInPool * 1e18))); - - borrower_.t0Np = (1e18 + poolRate_) * curMomp * t0ThresholdPrice / lup_ / 1e18; - } else { - borrower_.t0Np = 0; - } + // update Np to Tp ratio of borrower + if (npTpRatioUpdate_) { + borrower_.npTpRatio = 1.04 * 1e18 + uint256(PRBMathSD59x18.sqrt(int256(poolRate_))) / 2; } // save borrower state diff --git a/tests/INVARIANTS.md b/tests/INVARIANTS.md index 67c2cced0..ee1a17b95 100644 --- a/tests/INVARIANTS.md +++ b/tests/INVARIANTS.md @@ -23,8 +23,8 @@ - **A3**: number of borrowers with debt (`LoansState.borrowers.length` with `t0Debt != 0`) = number of loans (`LoansState.loans.length -1`) + number of auctioned borrowers (`AuctionsState.noOfAuctions`) - **A4**: number of recorded auctions (`AuctionsState.noOfAuctions`) = length of auctioned borrowers (count of borrowers in `AuctionsState.liquidations` with `kickTime != 0`) - **A5**: for each `Liquidation` recorded in liquidation mapping (`AuctionsState.liquidations`) the kicker address (`Liquidation.kicker`) has a locked balance (`Kicker.locked`) equal or greater than liquidation bond size (`Liquidation.bondSize`) -- **A6**: if a `Liquidation` is not taken then the take flag (`Liquidation.alreadyTaken`) should be `False`, if already taken then the take flag should be `True` - **A7**: total bond escrowed accumulator (`AuctionsState.totalBondEscrowed`) should increase when auction is kicked with the difference needed to cover the bond and should decrease only when kicker bonds withdrawn (`Pool.withdrawBonds`). Claimable bonds should be available for withdrawal from pool at any time. +- **A8**: Upon a take/arbtake/deposittake the kicker reward <= borrower penalty ## Loans - **L1**: for each `Loan` in loans array (`LoansState.loans`) starting from index 1, the corresponding address (`Loan.borrower`) is not `0x`, the threshold price (`Loan.thresholdPrice`) is different than 0 and the id mapped in indices mapping (`LoansState.indices`) equals index of loan in loans array. @@ -70,12 +70,13 @@ - **RE4**: Reserves are unchanged by withdrawing deposit (quote token) from a bucket after the penalty period hes expired - **RE5**: Reserves are unchanged by adding collateral token into a bucket - **RE6**: Reserves are unchanged by removing collateral token from a bucket -- **RE7**: Reserves increase by 7% of the loan quantity upon the first take (including depositTake or arbTake) and increase/decrease by bond penalty/reward on take. -- **RE8**: Reserves are unchanged under takes/depositTakes/arbTakes after the first take but increase/decrease by bond penalty/reward on take. -- **RE9**: Reserves increase by 3 months of interest when a loan is kicked +- **RE7**: Reserves increase by bond penalty/reward plus borrower penalty on take above TP. +- **RE8**: Reserves increase by bond penalty/reward plus borrower penalty on bucket takes above TP. +- **RE9**: Reserves unchanges by takes and bucket takes below TP. - **RE10**: Reserves increase by origination fee: max(1 week interest, 0.05% of borrow amount), on draw debt - **RE11**: Reserves decrease by claimableReserves by kickReserveAuction - **RE12**: Reserves decrease by amount of reserve used to settle a auction +- **RE13**: Reserves are unchanged by kick ## Rewards - **RW1**: Staking rewards must be less than reward cap percentage multiplied by ajna burned (`newRewards < REWARD_CAP * totalBurnedInPeriod`) for any given time period (`epoch`) diff --git a/tests/brownie/conftest.py b/tests/brownie/conftest.py index 3f1a9d411..20c72aa62 100644 --- a/tests/brownie/conftest.py +++ b/tests/brownie/conftest.py @@ -112,7 +112,7 @@ def availableLiquidity(self): return quoteBalance - reserves; def borrowerInfo(self, borrower_address): - # returns (debt, collateral, mompFactor) + # returns (debt, collateral, t0NeutralPrice) return self.pool_info_utils.borrowerInfo(self.pool.address, borrower_address) def bucketInfo(self, index): diff --git a/tests/forge/interactions/BalancerUniswapExample.sol b/tests/forge/interactions/BalancerUniswapExample.sol index 0652466be..d5b3ca405 100644 --- a/tests/forge/interactions/BalancerUniswapExample.sol +++ b/tests/forge/interactions/BalancerUniswapExample.sol @@ -53,7 +53,7 @@ contract BalancerUniswapTaker { // take auction from Ajna pool, give USDC, receive WETH IAjnaPool(decoded.ajnaPool).take(decoded.borrower, decoded.maxAmount, address(this), new bytes(0)); - uint256 usdcBalanceAfterTake = 85496538; + uint256 usdcBalanceAfterTake = 81080126; assert(tokens[0].balanceOf(address(this)) == usdcBalanceAfterTake); // USDC balance after Ajna take assert(tokens[1].balanceOf(address(this)) == 2000000000000000000); // WETH balance after Ajna take diff --git a/tests/forge/interactions/ERC20TakeWithExternalLiquidity.t.sol b/tests/forge/interactions/ERC20TakeWithExternalLiquidity.t.sol index 8ce92718b..74d4644f9 100644 --- a/tests/forge/interactions/ERC20TakeWithExternalLiquidity.t.sol +++ b/tests/forge/interactions/ERC20TakeWithExternalLiquidity.t.sol @@ -105,7 +105,7 @@ contract ERC20TakeWithExternalLiquidityTest is Test { }) ); vm.expectEmit(true, true, false, true); - emit Take(_borrower, 14.503461444385064128 * 1e18, 2.0 * 1e18, 0.145034614443850641 * 1e18, true); + emit Take(_borrower, 18.919873153126569032 * 1e18, 2.0 * 1e18, 0.287210105092827748 * 1e18, true); taker.take(tokens, amounts, data); assertGt(usdc.balanceOf(address(this)), 0); // could vary @@ -126,7 +126,7 @@ contract ERC20TakeWithExternalLiquidityTest is Test { // call take using taker contract bytes memory data = abi.encode(address(_ajnaPool)); vm.expectEmit(true, true, false, true); - emit Take(_borrower, 14.503461444385064128 * 1e18, 2.0 * 1e18, 0.145034614443850641 * 1e18, true); + emit Take(_borrower, 18.919873153126569032 * 1e18, 2.0 * 1e18, 0.287210105092827748 * 1e18, true); _ajnaPool.take(_borrower, takeAmount, address(taker), data); // confirm we earned some quote token @@ -136,7 +136,7 @@ contract ERC20TakeWithExternalLiquidityTest is Test { function testTakeCalleeDiffersFromSender() external { // _lender is msg.sender, QT & CT balances pre take - assertEq(usdc.balanceOf(_lender), 119_999.999999926999804657 * 1e18); + assertEq(usdc.balanceOf(_lender), 119_999.999999926999703463 * 1e18); assertEq(weth.balanceOf(_lender), 0); // callee, _lender1 QT & CT balances pre take @@ -148,7 +148,7 @@ contract ERC20TakeWithExternalLiquidityTest is Test { _ajnaPool.take(_borrower, 1_001 * 1e18, _lender1, new bytes(0)); // _lender is has QT deducted from balance - assertEq(usdc.balanceOf(_lender), 119_999.999999926985301195 * 1e18); + assertEq(usdc.balanceOf(_lender), 119_999.999999926980783589 * 1e18); assertEq(weth.balanceOf(_lender), 0); // callee, _lender1 receives CT from take diff --git a/tests/forge/interactions/ERC721TakeWithExternalLiquidity.sol b/tests/forge/interactions/ERC721TakeWithExternalLiquidity.sol index bd6ba3eb5..cbf94628c 100644 --- a/tests/forge/interactions/ERC721TakeWithExternalLiquidity.sol +++ b/tests/forge/interactions/ERC721TakeWithExternalLiquidity.sol @@ -80,14 +80,14 @@ contract ERC721TakeWithExternalLiquidityTest is ERC721HelperContract { // call take using taker contract bytes memory data = abi.encode(address(_pool)); vm.expectEmit(true, true, false, true); - uint256 quoteTokenPaid = 529.576903317769475648 * 1e18; + uint256 quoteTokenPaid = 1_161.844718489711575688 * 1e18; uint256 collateralPurchased = 2 * 1e18; - uint256 bondChange = 5.295769033177694756 * 1e18; + uint256 bondChange = 17.637197723169355130 * 1e18; emit Take(_borrower, quoteTokenPaid, collateralPurchased, bondChange, true); _pool.take(_borrower, 2, address(taker), data); // confirm we earned some quote token - assertEq(_quote.balanceOf(address(taker)), 970.423096682230524352 * 1e18); + assertEq(_quote.balanceOf(address(taker)), 338.155281510288424312 * 1e18); } function testTakeNFTCalleeDiffersFromSender() external { @@ -103,21 +103,21 @@ contract ERC721TakeWithExternalLiquidityTest is ERC721HelperContract { _collateral.setApprovalForAll(address(marketPlace), true); // _lender is msg.sender, QT & CT balances pre take - assertEq(_quote.balanceOf(_lender), 49_979.825641778370686641 * 1e18); + assertEq(_quote.balanceOf(_lender), 49_969.374638518350819260 * 1e18); assertEq(_quote.balanceOf(address(taker)), 0); // call take using taker contract changePrank(_lender); bytes memory data = abi.encode(address(_pool)); vm.expectEmit(true, true, false, true); - uint256 quoteTokenPaid = 529.576903317769475648 * 1e18; + uint256 quoteTokenPaid = 1_161.844718489711575688 * 1e18; uint256 collateralPurchased = 2 * 1e18; - uint256 bondChange = 5.295769033177694756 * 1e18; + uint256 bondChange = 17.637197723169355130 * 1e18; emit Take(_borrower, quoteTokenPaid, collateralPurchased, bondChange, true); _pool.take(_borrower, 2, address(taker), data); // _lender is msg.sender, QT & CT balances post take - assertEq(_quote.balanceOf(_lender), 49_450.248738460601210993 * 1e18); + assertEq(_quote.balanceOf(_lender), 48_807.529920028639243572 * 1e18); assertEq(_quote.balanceOf(address(taker)), 1_500.0 * 1e18); // QT is increased as NFTTakeExample contract sells the NFT } } diff --git a/tests/forge/invariants/ERC20Pool/PanicExitERC20PoolInvariants.t.sol b/tests/forge/invariants/ERC20Pool/PanicExitERC20PoolInvariants.t.sol index 0fa61a418..b9df8f249 100644 --- a/tests/forge/invariants/ERC20Pool/PanicExitERC20PoolInvariants.t.sol +++ b/tests/forge/invariants/ERC20Pool/PanicExitERC20PoolInvariants.t.sol @@ -72,7 +72,6 @@ contract PanicExitERC20PoolInvariants is BasicERC20PoolInvariants, LiquidationIn _invariant_A2(); _invariant_A3_A4(); _invariant_A5(); - _invariant_A6(); _invariant_A7(); invariant_call_summary(); diff --git a/tests/forge/invariants/ERC20Pool/RealWorldScenarioInvariants.t.sol b/tests/forge/invariants/ERC20Pool/RealWorldScenarioInvariants.t.sol index 0c9f27076..c1a2195cf 100644 --- a/tests/forge/invariants/ERC20Pool/RealWorldScenarioInvariants.t.sol +++ b/tests/forge/invariants/ERC20Pool/RealWorldScenarioInvariants.t.sol @@ -66,7 +66,6 @@ contract RealWorldScenarioInvariants is ReserveInvariants, LiquidationERC20PoolI _invariant_A2(); _invariant_A3_A4(); _invariant_A5(); - _invariant_A6(); _invariant_A7(); invariant_reserves(); diff --git a/tests/forge/invariants/ERC20Pool/SettleERC20PoolInvariants.t.sol b/tests/forge/invariants/ERC20Pool/SettleERC20PoolInvariants.t.sol new file mode 100644 index 000000000..027f4c757 --- /dev/null +++ b/tests/forge/invariants/ERC20Pool/SettleERC20PoolInvariants.t.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity 0.8.18; + +import "@std/console.sol"; + +import { LiquidationInvariants } from '../base/LiquidationInvariants.t.sol'; +import { BaseInvariants } from '../base/BaseInvariants.sol'; +import { BasicInvariants } from '../base/BasicInvariants.t.sol'; +import { SettleERC20PoolHandler } from './handlers/SettleERC20PoolHandler.sol'; +import { BasicERC20PoolInvariants } from './BasicERC20PoolInvariants.t.sol'; + +contract SettleERC20PoolInvariants is BasicERC20PoolInvariants, LiquidationInvariants { + + SettleERC20PoolHandler internal _settleERC20PoolHandler; + + address[] internal _lenders; + address[] internal _borrowers; + + uint16 internal constant LENDERS = 2_000; + uint16 internal constant LOANS_COUNT = 8_000; + + function setUp() public override(BaseInvariants, BasicERC20PoolInvariants) virtual { + + super.setUp(); + + excludeContract(address(_basicERC20PoolHandler)); + + _settleERC20PoolHandler = new SettleERC20PoolHandler( + address(_erc20pool), + address(_ajna), + address(_poolInfo), + address(this) + ); + + _handler = address(_settleERC20PoolHandler); + } + + function invariant_all_erc20() public useCurrentTimestamp { + console.log("Quote precision: ", _quote.decimals()); + console.log("Collateral precision:", _collateral.decimals()); + console.log("Quote balance: ", _quote.balanceOf(address(_pool))); + console.log("Collateral balance: ", _collateral.balanceOf(address(_pool))); + + _invariant_B1(); + _invariant_B2_B3(); + _invariant_B4(); + _invariant_B5_B6_B7(); + + _invariant_QT1(); + _invariant_QT2(); + _invariant_QT3(); + + _invariant_R1_R2_R3_R4_R5_R6_R7_R8(); + + _invariant_L1_L2_L3(); + + _invariant_I1(); + _invariant_I2(); + _invariant_I3(); + _invariant_I4(); + + _invariant_F1(); + _invariant_F2(); + _invariant_F3(); + _invariant_F4(); + _invariant_F5(); + + invariant_collateral_CT1_CT7(); + + _invariant_A1(); + _invariant_A2(); + _invariant_A3_A4(); + _invariant_A5(); + _invariant_A7(); + + invariant_call_summary(); + } + + function invariant_call_summary() public virtual override(BasicInvariants, LiquidationInvariants) useCurrentTimestamp { + super.invariant_call_summary(); + } + +} \ No newline at end of file diff --git a/tests/forge/invariants/ERC20Pool/handlers/BasicERC20PoolHandler.sol b/tests/forge/invariants/ERC20Pool/handlers/BasicERC20PoolHandler.sol index 1fbce5195..8f5bac357 100644 --- a/tests/forge/invariants/ERC20Pool/handlers/BasicERC20PoolHandler.sol +++ b/tests/forge/invariants/ERC20Pool/handlers/BasicERC20PoolHandler.sol @@ -73,14 +73,15 @@ contract BasicERC20PoolHandler is UnboundedBasicERC20PoolHandler, BasicPoolHandl ) external useRandomActor(actorIndex_) useTimestamps skipTime(skippedTime_) writeLogs { numberOfCalls['BBasicHandler.pledgeCollateral']++; + // borrower cannot make any action when in auction + (uint256 kickTime,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor); + if (kickTime != 0) return; + // Prepare test phase uint256 boundedAmount = _prePledgeCollateral(amountToPledge_); // Action phase _pledgeCollateral(boundedAmount); - - // Cleanup phase - _auctionSettleStateReset(_actor); } function pullCollateral( @@ -90,6 +91,10 @@ contract BasicERC20PoolHandler is UnboundedBasicERC20PoolHandler, BasicPoolHandl ) external useRandomActor(actorIndex_) useTimestamps skipTime(skippedTime_) writeLogs { numberOfCalls['BBasicHandler.pullCollateral']++; + // borrower cannot make any action when in auction + (uint256 kickTime,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor); + if (kickTime != 0) return; + // Prepare test phase uint256 boundedAmount = _prePullCollateral(amountToPull_); @@ -104,14 +109,15 @@ contract BasicERC20PoolHandler is UnboundedBasicERC20PoolHandler, BasicPoolHandl ) external useRandomActor(actorIndex_) useTimestamps skipTime(skippedTime_) writeLogs { numberOfCalls['BBasicHandler.drawDebt']++; + // borrower cannot make any action when in auction + (uint256 kickTime,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor); + if (kickTime != 0) return; + // Prepare test phase uint256 boundedAmount = _preDrawDebt(amountToBorrow_); // Action phase _drawDebt(boundedAmount); - - // Cleanup phase - _auctionSettleStateReset(_actor); } function repayDebt( @@ -121,14 +127,15 @@ contract BasicERC20PoolHandler is UnboundedBasicERC20PoolHandler, BasicPoolHandl ) external useRandomActor(actorIndex_) useTimestamps skipTime(skippedTime_) writeLogs { numberOfCalls['BBasicHandler.repayDebt']++; + // borrower cannot make any action when in auction + (uint256 kickTime,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor); + if (kickTime != 0) return; + // Prepare test phase uint256 boundedAmount = _preRepayDebt(amountToRepay_); // Action phase _repayDebt(boundedAmount); - - // Cleanup phase - _auctionSettleStateReset(_actor); } /*******************************/ @@ -168,13 +175,17 @@ contract BasicERC20PoolHandler is UnboundedBasicERC20PoolHandler, BasicPoolHandl ) internal override returns (uint256 boundedAmount_) { boundedAmount_ = constrictToRange(amountToBorrow_, MIN_DEBT_AMOUNT, MAX_DEBT_AMOUNT); + // borrower cannot make any action when in auction + (uint256 kickTime, uint256 collateral,,,,) = _poolInfo.auctionStatus(address(_pool), _actor); + if (kickTime != 0) return boundedAmount_; + // Pre Condition // 1. borrower's debt should exceed minDebt // 2. pool needs sufficent quote token to draw debt // 3. drawDebt should not make borrower under collateralized // 1. borrower's debt should exceed minDebt - (uint256 debt, uint256 collateral, ) = _poolInfo.borrowerInfo(address(_pool), _actor); + (uint256 debt,, ) = _poolInfo.borrowerInfo(address(_pool), _actor); (uint256 minDebt, , , ) = _poolInfo.poolUtilizationInfo(address(_pool)); if (boundedAmount_ < minDebt && minDebt < MAX_DEBT_AMOUNT) boundedAmount_ = minDebt + 1; diff --git a/tests/forge/invariants/ERC20Pool/handlers/PanicExitERC20PoolHandler.sol b/tests/forge/invariants/ERC20Pool/handlers/PanicExitERC20PoolHandler.sol index ef5429ca7..9903290a0 100644 --- a/tests/forge/invariants/ERC20Pool/handlers/PanicExitERC20PoolHandler.sol +++ b/tests/forge/invariants/ERC20Pool/handlers/PanicExitERC20PoolHandler.sol @@ -60,7 +60,7 @@ contract PanicExitERC20PoolHandler is UnboundedLiquidationPoolHandler, Unbounded _actor = _borrowers[borrowerIndex_]; changePrank(_actor); - (,,, uint256 kickTime,,,,,,) = _pool.auctionInfo(_actor); + (,,, uint256 kickTime,,,,,) = _pool.auctionInfo(_actor); if (block.timestamp > kickTime + 72 hours) { numberOfCalls['BPanicExitPoolHandler.settleDebt']++; _settleAuction(_actor, numberOfBuckets); @@ -71,7 +71,6 @@ contract PanicExitERC20PoolHandler is UnboundedLiquidationPoolHandler, Unbounded (, uint256 collateral, ) = _poolInfo.borrowerInfo(address(_pool), _actor); _pullCollateral(collateral); - _auctionSettleStateReset(_actor); _resetSettledAuction(_actor, borrowerIndex_); } @@ -165,7 +164,7 @@ contract PanicExitERC20PoolHandler is UnboundedLiquidationPoolHandler, Unbounded function settleHeadAuction( uint256 skippedTime_ ) external useTimestamps skipTime(skippedTime_) writeLogs { - (, , , , , , address headAuction, , , ) = _pool.auctionInfo(address(0)); + (, , , , , , address headAuction, , ) = _pool.auctionInfo(address(0)); if (headAuction != address(0)) { _settleAuction(headAuction, 10); _resetSettledAuction(headAuction, 0); @@ -219,9 +218,8 @@ contract PanicExitERC20PoolHandler is UnboundedLiquidationPoolHandler, Unbounded } function _resetSettledAuction(address borrower_, uint256 borrowerIndex_) internal { - (,,, uint256 kickTime,,,,,,) = _pool.auctionInfo(borrower_); + (,,, uint256 kickTime,,,,,) = _pool.auctionInfo(borrower_); if (kickTime == 0) { - alreadyTaken[borrower_] = false; if (borrowerIndex_ != 0) _activeBorrowers.remove(borrowerIndex_); } } diff --git a/tests/forge/invariants/ERC20Pool/handlers/SettleERC20PoolHandler.sol b/tests/forge/invariants/ERC20Pool/handlers/SettleERC20PoolHandler.sol new file mode 100644 index 000000000..65ef26888 --- /dev/null +++ b/tests/forge/invariants/ERC20Pool/handlers/SettleERC20PoolHandler.sol @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity 0.8.18; + +import { Strings } from '@openzeppelin/contracts/utils/Strings.sol'; +import '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; + +import 'src/ERC20Pool.sol'; +import { _priceAt, MAX_FENWICK_INDEX } from 'src/libraries/helpers/PoolHelper.sol'; + +import { TokenWithNDecimals } from '../../../utils/Tokens.sol'; + +import { BaseERC20PoolHandler } from './unbounded/BaseERC20PoolHandler.sol'; +import { UnboundedBasicERC20PoolHandler } from './unbounded/UnboundedBasicERC20PoolHandler.sol'; +import { UnboundedLiquidationPoolHandler } from '../../base/handlers/unbounded/UnboundedLiquidationPoolHandler.sol'; + +contract SettleERC20PoolHandler is UnboundedLiquidationPoolHandler, UnboundedBasicERC20PoolHandler { + using EnumerableSet for EnumerableSet.UintSet; + + address[] internal _lenders; + address[] internal _borrowers; + + uint16 internal constant LENDERS = 100; + uint16 internal constant LOANS_COUNT = 100; + uint16 nonce; + uint256 numberOfBuckets; + + EnumerableSet.UintSet internal _activeBorrowers; + + constructor( + address pool_, + address ajna_, + address poolInfo_, + address testContract_ + ) BaseERC20PoolHandler(pool_, ajna_, poolInfo_, 0, testContract_) { + numberOfBuckets = buckets.length(); + setUp(); + } + + function setUp() internal useTimestamps { + vm.startPrank(address(this)); + + _setupLendersAndDeposits(LENDERS); + _setupBorrowersAndLoans(LOANS_COUNT); + + ( , , uint256 totalLoans) = _pool.loansInfo(); + require(totalLoans == LOANS_COUNT, "loans setup failed"); + + vm.warp(block.timestamp + 1_000 days); + } + + function settleDebt( + uint256 kickerIndex_, + uint256 borrowerIndex_, + uint256 skippedTime_ + ) external useTimestamps skipTime(skippedTime_) writeLogs { + numberOfCalls['SettlePoolHandler.settleDebt']++; + + borrowerIndex_ = constrictToRange(borrowerIndex_, 0, _activeBorrowers.values().length - 1); + address borrower = _borrowers[borrowerIndex_]; + + kickerIndex_ = constrictToRange(kickerIndex_, 0, LENDERS - 1); + address kicker = _lenders[kickerIndex_]; + + (,,, uint256 kickTime,,,,,) = _pool.auctionInfo(borrower); + + // Kick auction if not already kicked + if (kickTime == 0) { + changePrank(kicker); + _actor = kicker; + _kickAuction(borrower); + } + + (,,, kickTime,,,,,) = _pool.auctionInfo(borrower); + + if (kickTime == 0) return; + + // skip time to make auction settleable + if (block.timestamp < kickTime + 72 hours) { + skip(kickTime + 73 hours - block.timestamp); + } + + changePrank(borrower); + _actor = borrower; + _settle(borrower, numberOfBuckets); + + _resetSettledAuction(borrower, borrowerIndex_); + } + + function repayDebtByThirdParty( + uint256 actorIndex_, + uint256 kickerIndex_, + uint256 borrowerIndex_, + uint256 skippedTime_ + ) external useTimestamps skipTime(skippedTime_) writeLogs { + numberOfCalls['SettlePoolHandler.repayLoan']++; + + borrowerIndex_ = constrictToRange(borrowerIndex_, 0, _activeBorrowers.values().length - 1); + address borrower = _borrowers[borrowerIndex_]; + + kickerIndex_ = constrictToRange(kickerIndex_, 0, LENDERS - 1); + address kicker = _lenders[kickerIndex_]; + + actorIndex_ = constrictToRange(actorIndex_, 0, LENDERS - 1); + address payer = _lenders[actorIndex_]; + + (,,, uint256 kickTime,,,,,) = _pool.auctionInfo(borrower); + + // Kick auction if not already kicked + if (kickTime == 0) { + changePrank(kicker); + _actor = kicker; + _kickAuction(borrower); + } + + (,,, kickTime,,,,,) = _pool.auctionInfo(borrower); + + if (kickTime == 0) return; + + // skip time to make auction settleable + if (block.timestamp < kickTime + 72 hours) { + skip(kickTime + 73 hours - block.timestamp); + } + + // skip time to make auction settleable + if (block.timestamp < kickTime + 72 hours) { + skip(kickTime + 73 hours - block.timestamp); + } + + changePrank(payer); + _repayDebtByThirdParty(payer, borrower, type(uint256).max); + + _resetSettledAuction(borrower, borrowerIndex_); + } + + function _settle( + address borrower_, + uint256 maxDepth_ + ) internal updateLocalStateAndPoolInterest { + numberOfCalls['UBLiquidationHandler.settleAuction']++; + ( + uint256 borrowerT0Debt, + uint256 collateral, + ) = _pool.borrowerInfo(borrower_); + (uint256 reservesBeforeAction, , , , )= _poolInfo.poolReservesInfo(address(_pool)); + (uint256 inflator, ) = _pool.inflatorInfo(); + + _pool.settle(borrower_, maxDepth_); + // settle borrower debt with exchanging borrower collateral with quote tokens starting from hpb + while (maxDepth_ != 0 && borrowerT0Debt != 0 && collateral != 0) { + uint256 bucketIndex = fenwickIndexForSum(1); + uint256 maxSettleableDebt = Maths.floorWmul(collateral, _priceAt(bucketIndex)); + uint256 fenwickDeposit = fenwickDeposits[bucketIndex]; + uint256 borrowerDebt = Maths.wmul(borrowerT0Debt, inflator); + + if (fenwickDeposit == 0 && maxSettleableDebt != 0) { + collateral = 0; + // Deposits in the tree is zero, insert entire collateral into lowest bucket 7388 + // **B5**: when settle with collateral: record min bucket where collateral added + buckets.add(7388); + lenderDepositTime[borrower_][7388] = block.timestamp; + } else { + if (bucketIndex != MAX_FENWICK_INDEX) { + // enough deposit in bucket and collateral avail to settle entire debt + if (fenwickDeposit >= borrowerDebt && maxSettleableDebt >= borrowerDebt) { + fenwickDeposits[bucketIndex] -= borrowerDebt; + collateral -= Maths.ceilWdiv(borrowerDebt, _priceAt(bucketIndex)); + borrowerT0Debt = 0; + } + // enough collateral, therefore not enough deposit to settle entire debt, we settle only deposit amount + else if (maxSettleableDebt >= fenwickDeposit) { + fenwickDeposits[bucketIndex] = 0; + collateral -= Maths.ceilWdiv(fenwickDeposit, _priceAt(bucketIndex)); + borrowerT0Debt -= Maths.floorWdiv(fenwickDeposit, inflator); + } + // exchange all collateral with deposit + else { + fenwickDeposits[bucketIndex] -= maxSettleableDebt; + collateral = 0; + borrowerT0Debt -= Maths.floorWdiv(maxSettleableDebt, inflator); + } + } else { + collateral = 0; + // **B5**: when settle with collateral: record min bucket where collateral added. + // Lender doesn't get any LP when settle bad debt. + buckets.add(7388); + } + } + + maxDepth_ -= 1; + } + + // if collateral becomes 0 and still debt is left, settle debt by reserves and hpb making buckets bankrupt + if (borrowerT0Debt != 0 && collateral == 0) { + + (uint256 reservesAfterAction, , , , )= _poolInfo.poolReservesInfo(address(_pool)); + if (reservesBeforeAction > reservesAfterAction) { + // **RE12**: Reserves decrease by amount of reserve used to settle a auction + decreaseInReserves = reservesBeforeAction - reservesAfterAction; + } else { + // Reserves might increase upto 2 WAD due to rounding issue + increaseInReserves = reservesAfterAction - reservesBeforeAction; + } + borrowerT0Debt -= Maths.min(Maths.wdiv(decreaseInReserves, inflator), borrowerT0Debt); + + while (maxDepth_ != 0 && borrowerT0Debt != 0) { + uint256 bucketIndex = fenwickIndexForSum(1); + uint256 fenwickDeposit = fenwickDeposits[bucketIndex]; + uint256 borrowerDebt = Maths.wmul(borrowerT0Debt, inflator); + + if (bucketIndex != MAX_FENWICK_INDEX) { + // debt is greater than bucket deposit + if (borrowerDebt > fenwickDeposit) { + fenwickDeposits[bucketIndex] = 0; + borrowerT0Debt -= Maths.floorWdiv(fenwickDeposit, inflator); + } + // bucket deposit is greater than debt + else { + fenwickDeposits[bucketIndex] -= borrowerDebt; + borrowerT0Debt = 0; + } + } + + maxDepth_ -= 1; + } + } + // **CT2**: Keep track of bucketIndex when borrower is removed from auction to check collateral added into that bucket + (, , , uint256 kickTime, , , , , ) = _pool.auctionInfo(borrower_); + if (kickTime == 0 && collateral % 1e18 != 0 && _pool.poolType() == 1) { + buckets.add(7388); + lenderDepositTime[borrower_][7388] = block.timestamp; + } + } + + function _repayDebtByThirdParty( + address payer_, + address borrower_, + uint256 amountToRepay_ + ) internal updateLocalStateAndPoolInterest { + numberOfCalls['UBBasicHandler.repayDebt']++; + + (uint256 borrowerDebt, , ) = _poolInfo.borrowerInfo(address(_pool), borrower_); + + // ensure actor always has amount of quote to repay + _ensureQuoteAmount(payer_, borrowerDebt + 10 * 1e18); + + _erc20Pool.repayDebt(borrower_, amountToRepay_, 0, borrower_, 7388); + } + + function _setupLendersAndDeposits(uint256 count_) internal virtual { + uint256[] memory buckets = buckets.values(); + for (uint256 i; i < count_;) { + address lender = address(uint160(uint256(keccak256(abi.encodePacked(i, 'lender'))))); + + _actor = lender; + changePrank(_actor); + _addQuoteToken(100_000 * 1e18, buckets[_randomBucket()]); + + actors.push(lender); + _lenders.push(lender); + + unchecked { ++i; } + } + } + + function _setupBorrowersAndLoans(uint256 count_) internal { + for (uint256 i; i < count_;) { + address borrower = address(uint160(uint256(keccak256(abi.encodePacked(i, 'borrower'))))); + + _actor = borrower; + changePrank(_actor); + _drawDebt(_randomDebt() * 1e18); + + actors.push(borrower); + _activeBorrowers.add(i); + _borrowers.push(borrower); + + unchecked { ++i; } + } + } + + function _randomBucket() internal returns (uint256 randomBucket_) { + randomBucket_ = uint256( + keccak256(abi.encodePacked(block.timestamp, msg.sender, nonce)) + ) % numberOfBuckets; + ++ nonce; + } + + function _randomDebt() internal returns (uint256 randomDebt_) { + randomDebt_ = uint256( + keccak256(abi.encodePacked(block.timestamp, msg.sender, nonce)) + ) % 900 + 100; + ++ nonce; + } + + function _resetSettledAuction(address borrower_, uint256 borrowerIndex_) internal { + (,,, uint256 kickTime,,,,,) = _pool.auctionInfo(borrower_); + if (kickTime == 0) { + if (borrowerIndex_ != 0) _activeBorrowers.remove(borrowerIndex_); + } + } + +} \ No newline at end of file diff --git a/tests/forge/invariants/ERC20Pool/handlers/TradingERC20PoolHandler.sol b/tests/forge/invariants/ERC20Pool/handlers/TradingERC20PoolHandler.sol index 32416051a..32878fffe 100644 --- a/tests/forge/invariants/ERC20Pool/handlers/TradingERC20PoolHandler.sol +++ b/tests/forge/invariants/ERC20Pool/handlers/TradingERC20PoolHandler.sol @@ -171,9 +171,8 @@ contract TradingERC20PoolHandler is UnboundedLiquidationPoolHandler, UnboundedBa } function _resetSettledAuction(address borrower_, uint256 borrowerIndex_) internal { - (,,, uint256 kickTime,,,,,,) = _pool.auctionInfo(borrower_); + (,,, uint256 kickTime,,,,,) = _pool.auctionInfo(borrower_); if (kickTime == 0) { - alreadyTaken[borrower_] = false; if (borrowerIndex_ != 0) _activeBorrowers.remove(borrowerIndex_); } } diff --git a/tests/forge/invariants/ERC721Pool/PanicExitERC721PoolInvariants.t.sol b/tests/forge/invariants/ERC721Pool/PanicExitERC721PoolInvariants.t.sol index 882a16ad5..be00c021c 100644 --- a/tests/forge/invariants/ERC721Pool/PanicExitERC721PoolInvariants.t.sol +++ b/tests/forge/invariants/ERC721Pool/PanicExitERC721PoolInvariants.t.sol @@ -70,7 +70,6 @@ contract PanicExitERC721PoolInvariants is BasicERC721PoolInvariants, Liquidation _invariant_A2(); _invariant_A3_A4(); _invariant_A5(); - _invariant_A6(); _invariant_A7(); invariant_call_summary(); diff --git a/tests/forge/invariants/ERC721Pool/RealWorldScenarioInvariants.t.sol b/tests/forge/invariants/ERC721Pool/RealWorldScenarioInvariants.t.sol index 8ead081ac..7131ba3ee 100644 --- a/tests/forge/invariants/ERC721Pool/RealWorldScenarioInvariants.t.sol +++ b/tests/forge/invariants/ERC721Pool/RealWorldScenarioInvariants.t.sol @@ -64,7 +64,6 @@ contract RealWorldScenarioInvariants is ReserveInvariants, LiquidationERC721Pool _invariant_A2(); _invariant_A3_A4(); _invariant_A5(); - _invariant_A6(); _invariant_A7(); invariant_reserves(); diff --git a/tests/forge/invariants/ERC721Pool/handlers/BasicERC721PoolHandler.sol b/tests/forge/invariants/ERC721Pool/handlers/BasicERC721PoolHandler.sol index acbf9ea25..d207cd2d1 100644 --- a/tests/forge/invariants/ERC721Pool/handlers/BasicERC721PoolHandler.sol +++ b/tests/forge/invariants/ERC721Pool/handlers/BasicERC721PoolHandler.sol @@ -87,14 +87,15 @@ contract BasicERC721PoolHandler is UnboundedBasicERC721PoolHandler, BasicPoolHan ) external useRandomActor(actorIndex_) useTimestamps skipTime(skippedTime_) writeLogs { numberOfCalls['BBasicHandler.pledgeCollateral']++; + // borrower cannot make any action when in auction + (uint256 kickTime,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor); + if (kickTime != 0) return; + // Prepare test phase uint256 boundedAmount = _prePledgeCollateral(amountToPledge_); // Action phase _pledgeCollateral(boundedAmount); - - // Cleanup phase - _auctionSettleStateReset(_actor); } function pullCollateral( @@ -104,6 +105,10 @@ contract BasicERC721PoolHandler is UnboundedBasicERC721PoolHandler, BasicPoolHan ) external useRandomActor(actorIndex_) useTimestamps skipTime(skippedTime_) writeLogs { numberOfCalls['BBasicHandler.pullCollateral']++; + // borrower cannot make any action when in auction + (uint256 kickTime,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor); + if (kickTime != 0) return; + // Prepare test phase uint256 boundedAmount = _prePullCollateral(amountToPull_); @@ -118,14 +123,15 @@ contract BasicERC721PoolHandler is UnboundedBasicERC721PoolHandler, BasicPoolHan ) external useRandomActor(actorIndex_) useTimestamps skipTime(skippedTime_) writeLogs { numberOfCalls['BBasicHandler.drawDebt']++; + // borrower cannot make any action when in auction + (uint256 kickTime,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor); + if (kickTime != 0) return; + // Prepare test phase uint256 boundedAmount = _preDrawDebt(amountToBorrow_); // Action phase _drawDebt(boundedAmount); - - // Cleanup phase - _auctionSettleStateReset(_actor); } function repayDebt( @@ -135,14 +141,15 @@ contract BasicERC721PoolHandler is UnboundedBasicERC721PoolHandler, BasicPoolHan ) external useRandomActor(actorIndex_) useTimestamps skipTime(skippedTime_) writeLogs { numberOfCalls['BBasicHandler.repayDebt']++; + // borrower cannot make any action when in auction + (uint256 kickTime,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor); + if (kickTime != 0) return; + // Prepare test phase uint256 boundedAmount = _preRepayDebt(amountToRepay_); // Action phase _repayDebt(boundedAmount); - - // Cleanup phase - _auctionSettleStateReset(_actor); } /*******************************/ @@ -201,13 +208,17 @@ contract BasicERC721PoolHandler is UnboundedBasicERC721PoolHandler, BasicPoolHan ) internal override returns (uint256 boundedAmount_) { boundedAmount_ = constrictToRange(amountToBorrow_, MIN_DEBT_AMOUNT, MAX_DEBT_AMOUNT); + // borrower cannot make any action when in auction + (uint256 kickTime, uint256 collateral, uint256 debt,,,) = _poolInfo.auctionStatus(address(_pool), _actor); + if (kickTime != 0) return boundedAmount_; + // Pre Condition // 1. borrower's debt should exceed minDebt // 2. pool needs sufficent quote token to draw debt // 3. drawDebt should not make borrower under collateralized // 1. borrower's debt should exceed minDebt - (uint256 debt, uint256 collateral, ) = _poolInfo.borrowerInfo(address(_pool), _actor); + (debt, collateral, ) = _poolInfo.borrowerInfo(address(_pool), _actor); (uint256 minDebt, , , ) = _poolInfo.poolUtilizationInfo(address(_pool)); if (boundedAmount_ < minDebt && minDebt < MAX_DEBT_AMOUNT) boundedAmount_ = minDebt + 1; diff --git a/tests/forge/invariants/ERC721Pool/handlers/PanicExitERC721PoolHandler.sol b/tests/forge/invariants/ERC721Pool/handlers/PanicExitERC721PoolHandler.sol index f01bfe0b3..2051776b7 100644 --- a/tests/forge/invariants/ERC721Pool/handlers/PanicExitERC721PoolHandler.sol +++ b/tests/forge/invariants/ERC721Pool/handlers/PanicExitERC721PoolHandler.sol @@ -58,7 +58,7 @@ contract PanicExitERC721PoolHandler is UnboundedLiquidationPoolHandler, Unbounde _actor = _borrowers[borrowerIndex_]; changePrank(_actor); - (,,, uint256 kickTime,,,,,,) = _pool.auctionInfo(_actor); + (,,, uint256 kickTime,,,,,) = _pool.auctionInfo(_actor); if (block.timestamp > kickTime + 72 hours) { numberOfCalls['BPanicExitPoolHandler.settleDebt']++; _settleAuction(_actor, numberOfBuckets); @@ -69,7 +69,6 @@ contract PanicExitERC721PoolHandler is UnboundedLiquidationPoolHandler, Unbounde (, uint256 collateral, ) = _poolInfo.borrowerInfo(address(_pool), _actor); _pullCollateral(collateral); - _auctionSettleStateReset(_actor); _resetSettledAuction(_actor, borrowerIndex_); } @@ -163,7 +162,7 @@ contract PanicExitERC721PoolHandler is UnboundedLiquidationPoolHandler, Unbounde function settleHeadAuction( uint256 skippedTime_ ) external useTimestamps skipTime(skippedTime_) writeLogs { - (, , , , , , address headAuction, , , ) = _pool.auctionInfo(address(0)); + (, , , , , , address headAuction, , ) = _pool.auctionInfo(address(0)); if (headAuction != address(0)) { _settleAuction(headAuction, 10); _resetSettledAuction(headAuction, 0); @@ -217,9 +216,8 @@ contract PanicExitERC721PoolHandler is UnboundedLiquidationPoolHandler, Unbounde } function _resetSettledAuction(address borrower_, uint256 borrowerIndex_) internal { - (,,, uint256 kickTime,,,,,,) = _pool.auctionInfo(borrower_); + (,,, uint256 kickTime,,,,,) = _pool.auctionInfo(borrower_); if (kickTime == 0) { - alreadyTaken[borrower_] = false; if (borrowerIndex_ != 0) _activeBorrowers.remove(borrowerIndex_); } } diff --git a/tests/forge/invariants/PositionsAndRewards/handlers/BucketBankruptcyERC20PoolRewardsHandler.sol b/tests/forge/invariants/PositionsAndRewards/handlers/BucketBankruptcyERC20PoolRewardsHandler.sol index c1a9b2742..b1ab9eda6 100644 --- a/tests/forge/invariants/PositionsAndRewards/handlers/BucketBankruptcyERC20PoolRewardsHandler.sol +++ b/tests/forge/invariants/PositionsAndRewards/handlers/BucketBankruptcyERC20PoolRewardsHandler.sol @@ -69,7 +69,7 @@ contract BucketBankruptcyERC20PoolRewardsHandler is UnboundedBasicERC20PoolHandl ( , , uint256 totalLoans) = _pool.loansInfo(); require(totalLoans == LOANS_COUNT, "loans setup failed"); - vm.warp(block.timestamp + 100_000 days); + vm.warp(block.timestamp + 1_000 days); } function lenderKickAuction( @@ -154,7 +154,7 @@ contract BucketBankruptcyERC20PoolRewardsHandler is UnboundedBasicERC20PoolHandl ) external useTimestamps useRandomActor(takerIndex_) skipTime(skippedTime_) writeLogs { address borrower = _borrowers[constrictToRange(borrowerIndex_, 0, _borrowers.length - 1)]; - (, , , uint256 kickTime, , , , , , ) = _pool.auctionInfo(borrower); + (, , , uint256 kickTime, , , , , ) = _pool.auctionInfo(borrower); // Kick borrower if not already kicked if (kickTime == 0) { @@ -255,9 +255,8 @@ contract BucketBankruptcyERC20PoolRewardsHandler is UnboundedBasicERC20PoolHandl /*******************************/ function _resetSettledAuction(address borrower_, uint256 borrowerIndex_) internal { - (,,, uint256 kickTime,,,,,,) = _pool.auctionInfo(borrower_); + (,,, uint256 kickTime,,,,,) = _pool.auctionInfo(borrower_); if (kickTime == 0) { - alreadyTaken[borrower_] = false; if (borrowerIndex_ != 0) _activeBorrowers.remove(borrowerIndex_); } } diff --git a/tests/forge/invariants/base/BasicInvariants.t.sol b/tests/forge/invariants/base/BasicInvariants.t.sol index cacc1baba..ad199a7ea 100644 --- a/tests/forge/invariants/base/BasicInvariants.t.sol +++ b/tests/forge/invariants/base/BasicInvariants.t.sol @@ -321,7 +321,7 @@ abstract contract BasicInvariants is BaseInvariants { for (uint256 i = 0; i < actorCount; i++) { address borrower = IBaseHandler(_handler).actors(i); - (, , , uint256 kickTime, , , , , , ) = _pool.auctionInfo(borrower); + (, , , uint256 kickTime, , , , , ) = _pool.auctionInfo(borrower); if (kickTime == 0) { (uint256 borrowerT0Debt, uint256 borrowerCollateral, ) = _pool.borrowerInfo(borrower); diff --git a/tests/forge/invariants/base/LiquidationInvariants.t.sol b/tests/forge/invariants/base/LiquidationInvariants.t.sol index 19db71e26..4788bcd48 100644 --- a/tests/forge/invariants/base/LiquidationInvariants.t.sol +++ b/tests/forge/invariants/base/LiquidationInvariants.t.sol @@ -19,8 +19,8 @@ abstract contract LiquidationInvariants is BasicInvariants { _invariant_A2(); _invariant_A3_A4(); _invariant_A5(); - _invariant_A6(); _invariant_A7(); + _invariant_A8(); } /// @dev checks sum of all borrower's t0debt is equals to total pool t0debtInAuction @@ -30,7 +30,7 @@ abstract contract LiquidationInvariants is BasicInvariants { for (uint256 i = 0; i < actorCount; i++) { address borrower = IBaseHandler(_handler).actors(i); - (, , , uint256 kickTime, , , , , , ) = _pool.auctionInfo(borrower); + (, , , uint256 kickTime, , , , ,) = _pool.auctionInfo(borrower); if (kickTime != 0) { (uint256 t0debt, , ) = _pool.borrowerInfo(borrower); @@ -62,7 +62,7 @@ abstract contract LiquidationInvariants is BasicInvariants { uint256 lockedBonds; for (uint256 i = 0; i < actorCount; i++) { address borrower = IBaseHandler(_handler).actors(i); - (, , uint256 bond, , , , , , , ) = _pool.auctionInfo(borrower); + (, , uint256 bond, , , , , , ) = _pool.auctionInfo(borrower); lockedBonds += bond; } require(lockedBonds == kickerLockedBond, "A2: bonds in auctions != than kicker locked bonds"); @@ -94,7 +94,7 @@ abstract contract LiquidationInvariants is BasicInvariants { for (uint256 i = 0; i < actorCount; i++) { address borrower = IBaseHandler(_handler).actors(i); - (, , , uint256 kickTime, , , , , , ) = _pool.auctionInfo(borrower); + (, , , uint256 kickTime, , , , , ) = _pool.auctionInfo(borrower); if (kickTime != 0) borrowersKicked += 1; } @@ -108,28 +108,13 @@ abstract contract LiquidationInvariants is BasicInvariants { for (uint256 i = 0; i < actorCount; i++) { address borrower = IBaseHandler(_handler).actors(i); - (address kicker, , uint256 bondSize, , , , , , , ) = _pool.auctionInfo(borrower); + (address kicker, , uint256 bondSize, , , , , , ) = _pool.auctionInfo(borrower); (, uint256 lockedAmount) = _pool.kickerInfo(kicker); require(lockedAmount >= bondSize, "Auction Invariant A5"); } } - /// @dev if a Liquidation is not taken then the take flag (Liquidation.alreadyTaken) should be False, if already taken then the take flag should be True - function _invariant_A6() internal view { - uint256 actorCount = IBaseHandler(_handler).getActorsCount(); - - for (uint256 i = 0; i < actorCount; i++) { - address borrower = IBaseHandler(_handler).actors(i); - (, , , , , , , , , bool alreadyTaken) = _pool.auctionInfo(borrower); - - require( - alreadyTaken == IBaseHandler(_handler).alreadyTaken(borrower), - "Auction Invariant A6" - ); - } - } - /// @dev total bond escrowed should increase when auctioned kicked with the difference needed to cover the bond and should decrease only when kicker bonds withdrawned function _invariant_A7() internal view { uint256 previousTotalBondEscrowed = IBaseHandler(_handler).previousTotalBonds(); @@ -144,6 +129,17 @@ abstract contract LiquidationInvariants is BasicInvariants { "Auction Invariant A7" ); } + + /// @dev kicker reward should be less than or equals to kicker penalty on take. + function _invariant_A8() internal view { + uint256 borrowerPenalty = IBaseHandler(_handler).borrowerPenalty(); + uint256 kickerReward = IBaseHandler(_handler).kickerReward(); + + console.log("Borrower Penalty -->", borrowerPenalty); + console.log("Kicker Reward -->", kickerReward); + + require(kickerReward <= borrowerPenalty, "Auction Invariant A8"); + } function invariant_call_summary() public virtual override useCurrentTimestamp { console.log("\nCall Summary\n"); diff --git a/tests/forge/invariants/base/handlers/LiquidationPoolHandler.sol b/tests/forge/invariants/base/handlers/LiquidationPoolHandler.sol index db7e2551f..e2446cede 100644 --- a/tests/forge/invariants/base/handlers/LiquidationPoolHandler.sol +++ b/tests/forge/invariants/base/handlers/LiquidationPoolHandler.sol @@ -55,13 +55,13 @@ abstract contract LiquidationPoolHandler is UnboundedLiquidationPoolHandler, Bas address borrower; // try to take from head auction if any - (, , , , , , address headAuction, , , ) = _pool.auctionInfo(address(0)); + (, , , , , , address headAuction, , ) = _pool.auctionInfo(address(0)); if (headAuction != address(0)) { (, uint256 auctionedCollateral, ) = _poolInfo.borrowerInfo(address(_pool), headAuction); borrower = headAuction; amount_ = auctionedCollateral / 2; - (, , , uint256 kickTime, , , , , , ) = _pool.auctionInfo(borrower); + (, , , uint256 kickTime, , , , , ) = _pool.auctionInfo(borrower); // skip to make auction takeable if (block.timestamp - kickTime < 1 hours) { vm.warp(block.timestamp + 61 minutes); @@ -91,11 +91,11 @@ abstract contract LiquidationPoolHandler is UnboundedLiquidationPoolHandler, Bas address borrower; // try to take from head auction if any - (, , , , , , address headAuction, , , ) = _pool.auctionInfo(address(0)); + (, , , , , , address headAuction, , ) = _pool.auctionInfo(address(0)); if (headAuction != address(0)) { borrower = headAuction; - (, , , uint256 kickTime, , , , , , ) = _pool.auctionInfo(borrower); + (, , , uint256 kickTime, , , , , ) = _pool.auctionInfo(borrower); // skip to make auction takeable if (block.timestamp - kickTime < 1 hours) { vm.warp(block.timestamp + 61 minutes); @@ -126,7 +126,7 @@ abstract contract LiquidationPoolHandler is UnboundedLiquidationPoolHandler, Bas address borrower; // try to settle head auction if any - (, , , , , , address headAuction, , , ) = _pool.auctionInfo(address(0)); + (, , , , , , address headAuction, , ) = _pool.auctionInfo(address(0)); if (headAuction != address(0)) { borrower = headAuction; } else { @@ -139,8 +139,6 @@ abstract contract LiquidationPoolHandler is UnboundedLiquidationPoolHandler, Bas _settleAuction(borrower, LENDER_MAX_BUCKET_INDEX - LENDER_MIN_BUCKET_INDEX); - // Cleanup phase - _auctionSettleStateReset(borrower); } /*******************************/ @@ -152,7 +150,7 @@ abstract contract LiquidationPoolHandler is UnboundedLiquidationPoolHandler, Bas borrower_ = actors[borrowerIndex_]; amount_ = constrictToRange(amount_, MIN_QUOTE_AMOUNT, MAX_QUOTE_AMOUNT); - ( , , , uint256 kickTime, , , , , , ) = _pool.auctionInfo(borrower_); + ( , , , uint256 kickTime, , , , , ) = _pool.auctionInfo(borrower_); borrowerKicked_ = kickTime != 0; diff --git a/tests/forge/invariants/base/handlers/unbounded/BaseHandler.sol b/tests/forge/invariants/base/handlers/unbounded/BaseHandler.sol index 6838cc788..d4f3fe302 100644 --- a/tests/forge/invariants/base/handlers/unbounded/BaseHandler.sol +++ b/tests/forge/invariants/base/handlers/unbounded/BaseHandler.sol @@ -81,12 +81,15 @@ abstract contract BaseHandler is Test { uint256 public increaseInBonds; // amount of bond increase uint256 public decreaseInBonds; // amount of bond decrease + // Take penalty test state + uint256 public borrowerPenalty; // Borrower penalty on take + uint256 public kickerReward; // Kicker reward on take + // All Buckets used in invariant testing that also includes Buckets where collateral is added when a borrower is in auction and has partial NFT EnumerableSet.UintSet internal buckets; // auctions invariant test state bool public firstTake; // if take is called on auction first time - mapping(address => bool) public alreadyTaken; // mapping borrower address to true if auction taken atleast once string internal path = "logFile.txt"; bool internal logToFile; @@ -132,9 +135,9 @@ abstract contract BaseHandler is Test { address currentActor = _actor; // clear head auction if more than 72 hours passed - (, , , , , , address headAuction, , , ) = _pool.auctionInfo(address(0)); + (, , , , , , address headAuction, , ) = _pool.auctionInfo(address(0)); if (headAuction != address(0)) { - (, , , uint256 kickTime, , , , , , ) = _pool.auctionInfo(headAuction); + (, , , uint256 kickTime, , , , , ) = _pool.auctionInfo(headAuction); if (block.timestamp - kickTime > 72 hours) { (uint256 auctionedDebt, , ) = _poolInfo.borrowerInfo(address(_pool), headAuction); @@ -145,7 +148,6 @@ abstract contract BaseHandler is Test { _ensureQuoteAmount(headAuction, auctionedDebt); _repayBorrowerDebt(headAuction, auctionedDebt); - _auctionSettleStateReset(headAuction); } } @@ -299,6 +301,7 @@ abstract contract BaseHandler is Test { err == keccak256(abi.encodeWithSignature("InvalidIndex()")) || err == keccak256(abi.encodeWithSignature("InsufficientLP()")) || err == keccak256(abi.encodeWithSignature("AuctionNotCleared()")) || + err == keccak256(abi.encodeWithSignature("AuctionNotTakeable()")) || err == keccak256(abi.encodeWithSignature("TransferorNotApproved()")) || err == keccak256(abi.encodeWithSignature("TransferToSameOwner()")) || err == keccak256(abi.encodeWithSignature("NoAllowance()")) || @@ -311,7 +314,6 @@ abstract contract BaseHandler is Test { err == keccak256(abi.encodeWithSignature("LimitIndexExceeded()")) || err == keccak256(abi.encodeWithSignature("PriceBelowLUP()")) || err == keccak256(abi.encodeWithSignature("NoAuction()")) || - err == keccak256(abi.encodeWithSignature("TakeNotPastCooldown()")) || err == keccak256(abi.encodeWithSignature("AuctionPriceGtBucketPrice()")) || err == keccak256(abi.encodeWithSignature("AuctionNotClearable()")) || err == keccak256(abi.encodeWithSignature("ReserveAuctionTooSoon()")) || @@ -346,6 +348,10 @@ abstract contract BaseHandler is Test { // record reserves before each action (previousReserves, , , , ) = _poolInfo.poolReservesInfo(address(_pool)); + // reset penalties before each action + borrowerPenalty = 0; + kickerReward = 0; + // reset the bonds before each action increaseInBonds = 0; decreaseInBonds = 0; @@ -429,41 +435,11 @@ abstract contract BaseHandler is Test { /*** Auctions Helper Functions ***/ /*********************************/ - /** - * @dev Called by actions that can settle auctions in order to reset test state. - */ - function _auctionSettleStateReset(address actor_) internal { - (address kicker, , , , , , , , , ) = _pool.auctionInfo(actor_); - - // auction is settled if kicker is 0x - bool auctionSettled = kicker == address(0); - // reset alreadyTaken flag if auction is settled - if (auctionSettled) alreadyTaken[actor_] = false; - } - function _getKickerBond(address kicker_) internal view returns (uint256 bond_) { (uint256 claimableBond, uint256 lockedBond) = _pool.kickerInfo(kicker_); bond_ = claimableBond + lockedBond; } - function _updateCurrentTakeState(address borrower_, uint256 borrowert0Debt_, uint256 inflator_) internal { - if (!alreadyTaken[borrower_]) { - alreadyTaken[borrower_] = true; - - // **RE7**: Reserves increase by 7% of the loan quantity upon the first take. - increaseInReserves += Maths.wmul( - Maths.wmul(borrowert0Debt_, 0.07 * 1e18), - inflator_ - ); - - firstTake = true; - - } else firstTake = false; - - // reset taken flag in case auction was settled by take action - _auctionSettleStateReset(borrower_); - } - function _recordSettleBucket( address borrower_, uint256 borrowerCollateralBefore_, @@ -516,7 +492,7 @@ abstract contract BaseHandler is Test { ( , , , , , , - address headAuction, , , + address headAuction, , ) = _pool.auctionInfo(address(0)); printLog("Time = ", block.timestamp); @@ -619,21 +595,21 @@ abstract contract BaseHandler is Test { string memory data; address nextBorrower; uint256 kickTime; - uint256 kickMomp; + uint256 referencePrice; uint256 bondFactor; uint256 bondSize; uint256 neutralPrice; - (,,,,,, nextBorrower,,,) = _pool.auctionInfo(address(0)); + (,,,,,, nextBorrower,,) = _pool.auctionInfo(address(0)); while (nextBorrower != address(0)) { data = string(abi.encodePacked("Borrower ", Strings.toHexString(uint160(nextBorrower), 20), " Auction Details :")); printInNextLine(data); - (, bondFactor, bondSize, kickTime, kickMomp, neutralPrice,, nextBorrower,,) = _pool.auctionInfo(nextBorrower); + (, bondFactor, bondSize, kickTime, referencePrice, neutralPrice,, nextBorrower,) = _pool.auctionInfo(nextBorrower); - printLog("Bond Factor = ", bondFactor); - printLog("Bond Size = ", bondSize); - printLog("Kick Time = ", kickTime); - printLog("Kick Momp = ", kickMomp); - printLog("Neutral Price = ", neutralPrice); + printLog("Bond Factor = ", bondFactor); + printLog("Bond Size = ", bondSize); + printLog("Kick Time = ", kickTime); + printLog("Reference Price = ", referencePrice); + printLog("Neutral Price = ", neutralPrice); } printInNextLine("======================="); } diff --git a/tests/forge/invariants/base/handlers/unbounded/UnboundedLiquidationPoolHandler.sol b/tests/forge/invariants/base/handlers/unbounded/UnboundedLiquidationPoolHandler.sol index 2f5c135b5..6e4f6af74 100644 --- a/tests/forge/invariants/base/handlers/unbounded/UnboundedLiquidationPoolHandler.sol +++ b/tests/forge/invariants/base/handlers/unbounded/UnboundedLiquidationPoolHandler.sol @@ -3,10 +3,12 @@ pragma solidity 0.8.18; import '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; +import { Math } from '@openzeppelin/contracts/utils/math/Math.sol'; import { Maths } from 'src/libraries/internal/Maths.sol'; import { _priceAt, _indexOf, MIN_PRICE, MAX_PRICE } from 'src/libraries/helpers/PoolHelper.sol'; import { MAX_FENWICK_INDEX } from 'src/libraries/helpers/PoolHelper.sol'; +import { Buckets } from 'src/libraries/internal/Buckets.sol'; import { BaseHandler } from './BaseHandler.sol'; @@ -32,7 +34,6 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { numberOfCalls['UBLiquidationHandler.kickAuction']++; (uint256 borrowerDebt, , ) = _poolInfo.borrowerInfo(address(_pool), borrower_); - (uint256 interestRate, ) = _pool.interestRateInfo(); // ensure actor always has the amount to pay for bond _ensureQuoteAmount(_actor, borrowerDebt); @@ -42,9 +43,6 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { try _pool.kick(borrower_, 7388) { numberOfActions['kick']++; - // **RE9**: Reserves increase by 3 months of interest when a loan is kicked - increaseInReserves += Maths.wdiv(Maths.wmul(borrowerDebt, interestRate), 4 * 1e18); - uint256 kickerBondAfter = _getKickerBond(_actor); // **A7**: totalBondEscrowed should increase when auctioned kicked with the difference needed to cover the bond @@ -62,7 +60,6 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { (address maxBorrower, , ) = _pool.loansInfo(); (uint256 borrowerDebt, , ) = _poolInfo.borrowerInfo(address(_pool), maxBorrower); - (uint256 interestRate, ) = _pool.interestRateInfo(); ( , , , uint256 depositBeforeAction, ) = _pool.bucketInfo(bucketIndex_); fenwickDeposits[bucketIndex_] = depositBeforeAction; @@ -76,9 +73,6 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { ( , , , uint256 depositAfterAction, ) = _pool.bucketInfo(bucketIndex_); - // **RE9**: Reserves increase by 3 months of interest when a loan is kicked - increaseInReserves += Maths.wdiv(Maths.wmul(borrowerDebt, interestRate), 4 * 1e18); - uint256 kickerBondAfter = _getKickerBond(_actor); // **A7**: totalBondEscrowed should increase when auctioned kicked with the difference needed to cover the bond @@ -130,7 +124,7 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { ) internal updateLocalStateAndPoolInterest { numberOfCalls['UBLiquidationHandler.takeAuction']++; - (address kicker, , , , , , , , , ) = _pool.auctionInfo(borrower_); + (address kicker, , , , , , , , ) = _pool.auctionInfo(borrower_); ( uint256 borrowerDebtBeforeTake, @@ -147,17 +141,15 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { try _pool.take(borrower_, amount_, taker_, bytes("")) { numberOfActions['take']++; - (uint256 borrowerDebtAfterTake, , ) = _poolInfo.borrowerInfo(address(_pool), borrower_); + (uint256 borrowerDebtAfterTake, uint256 borrowerCollateralAfterTake, ) = _poolInfo.borrowerInfo(address(_pool), borrower_); uint256 totalBondAfterTake = _getKickerBond(kicker); uint256 totalBalanceAfterTake = _quote.balanceOf(address(_pool)) * _pool.quoteTokenScale(); - if (borrowerDebtBeforeTake > borrowerDebtAfterTake) { - // **RE7**: Reserves decrease with debt covered by take. - decreaseInReserves += borrowerDebtBeforeTake - borrowerDebtAfterTake; - } else { - // **RE7**: Reserves increase by take penalty on first take. - increaseInReserves += borrowerDebtAfterTake - borrowerDebtBeforeTake; - } + // **RE7**: Reserves decrease with debt covered by take. + decreaseInReserves += borrowerDebtBeforeTake - borrowerDebtAfterTake; + + // **A8**: kicker reward <= Borrower penalty + borrowerPenalty = Maths.wmul(borrowerCollateralBeforeTake - borrowerCollateralAfterTake, auctionPrice) - (borrowerDebtBeforeTake - borrowerDebtAfterTake); if (totalBondBeforeTake > totalBondAfterTake) { // **RE7**: Reserves increase by bond penalty on take. @@ -171,6 +163,9 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { // **A7**: Total Bond increase by bond penalty on take. increaseInBonds += totalBondAfterTake - totalBondBeforeTake; + + // **A8**: kicker reward <= Borrower penalty + kickerReward += totalBondAfterTake - totalBondBeforeTake; } // **RE7**: Reserves increase with the quote token paid by taker. @@ -185,16 +180,6 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { ); } - if (!alreadyTaken[borrower_]) { - alreadyTaken[borrower_] = true; - - firstTake = true; - - } else firstTake = false; - - // reset taken flag in case auction was settled by take action - _auctionSettleStateReset(borrower_); - } catch (bytes memory err) { _ensurePoolError(err); } @@ -208,12 +193,11 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { ) internal updateLocalStateAndPoolInterest { numberOfCalls['UBLiquidationHandler.bucketTake']++; - (uint256 borrowerT0Debt, , ) = _pool.borrowerInfo(borrower_); + ( uint256 borrowerDebtBeforeTake, uint256 borrowerCollateralBeforeTake,) = _poolInfo.borrowerInfo(address(_pool), borrower_); - (address kicker, , , , , , , , , ) = _pool.auctionInfo(borrower_); + (address kicker, , , , , , , , ) = _pool.auctionInfo(borrower_); ( , , , , uint256 auctionPrice, ) = _poolInfo.auctionStatus(address(_pool), borrower_); uint256 auctionBucketIndex = auctionPrice < MIN_PRICE ? 7388 : (auctionPrice > MAX_PRICE ? 0 : _indexOf(auctionPrice)); - ( , , , uint256 pendingInflator, ) = _poolInfo.poolLoansInfo(address(_pool)); LocalBucketTakeVars memory beforeBucketTakeVars = getBucketTakeInfo(bucketIndex_, kicker, _actor, auctionBucketIndex, borrower_); @@ -225,10 +209,37 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { // **B7**: when awarded bucket take LP : taker deposit time = timestamp of block when award happened if (afterBucketTakeVars.takerLps > beforeBucketTakeVars.takerLps) lenderDepositTime[taker_][bucketIndex_] = block.timestamp; + (uint256 borrowerDebtAfterTake, uint256 borrowerCollateralAfterTake, ) = _poolInfo.borrowerInfo(address(_pool), borrower_); + if (afterBucketTakeVars.kickerLps > beforeBucketTakeVars.kickerLps) { // **B7**: when awarded bucket take LP : kicker deposit time = timestamp of block when award happened lenderDepositTime[kicker][bucketIndex_] = block.timestamp; + + // when kicker and taker are same, kicker Reward = total Reward (lps) - taker Reward (Collateral Price * difference of bucket used and auction price) + if (!depositTake_ && kicker == _actor) { + uint256 totalReward = lpToQuoteToken(afterBucketTakeVars.kickerLps - beforeBucketTakeVars.kickerLps, bucketIndex_); + uint256 takerReward = Maths.wmul(borrowerCollateralBeforeTake - borrowerCollateralAfterTake, _priceAt(bucketIndex_) - auctionPrice); + + // **A8**: kicker reward <= Borrower penalty + kickerReward = totalReward - takerReward; + } else { + // **A8**: kicker reward <= Borrower penalty + kickerReward = lpToQuoteToken(afterBucketTakeVars.kickerLps - beforeBucketTakeVars.kickerLps, bucketIndex_); + } } + + // **A8**: kicker reward <= Borrower penalty + if (depositTake_) { + borrowerPenalty = Maths.wmul(borrowerCollateralBeforeTake - borrowerCollateralAfterTake, _priceAt(bucketIndex_)) - (borrowerDebtBeforeTake - borrowerDebtAfterTake); + } else { + borrowerPenalty = Maths.wmul(borrowerCollateralBeforeTake - borrowerCollateralAfterTake, auctionPrice) - (borrowerDebtBeforeTake - borrowerDebtAfterTake); + } + + // reserves are increased by take penalty of borrower (Deposit used from bucket - Borrower debt reduced) + increaseInReserves += borrowerPenalty; + + // reserves are decreased by kicker reward + decreaseInReserves += kickerReward; if (beforeBucketTakeVars.kickerBond > afterBucketTakeVars.kickerBond) { // **RE7**: Reserves increase by bond penalty on take. @@ -242,7 +253,7 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { exchangeRateShouldNotChange[bucketIndex_] = true; // **CT2**: Keep track of bucketIndex when borrower is removed from auction to check collateral added into that bucket - (, , , uint256 kickTime, , , , , , ) = _pool.auctionInfo(borrower_); + (, , , uint256 kickTime, , , , , ) = _pool.auctionInfo(borrower_); if (kickTime == 0 && _pool.poolType() == 1) { buckets.add(auctionBucketIndex); if (beforeBucketTakeVars.borrowerLps < afterBucketTakeVars.borrowerLps) { @@ -253,8 +264,6 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { // assign value to fenwick tree to mitigate rounding error that could be created in a _fenwickRemove call fenwickDeposits[bucketIndex_] = afterBucketTakeVars.deposit; - _updateCurrentTakeState(borrower_, borrowerT0Debt, pendingInflator); - } catch (bytes memory err) { _ensurePoolError(err); } @@ -358,7 +367,7 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { } } // **CT2**: Keep track of bucketIndex when borrower is removed from auction to check collateral added into that bucket - (, , , uint256 kickTime, , , , , , ) = _pool.auctionInfo(borrower_); + (, , , uint256 kickTime, , , , , ) = _pool.auctionInfo(borrower_); if (kickTime == 0 && collateral % 1e18 != 0 && _pool.poolType() == 1) { buckets.add(7388); lenderDepositTime[borrower_][7388] = block.timestamp; @@ -376,4 +385,18 @@ abstract contract UnboundedLiquidationPoolHandler is BaseHandler { (bucketTakeVars.borrowerLps, ) = _pool.lenderInfo(auctionBucketIndex_, borrower_); } + // Helper function to calculate quote tokens from lps in a bucket irrespective of deposit available. + function lpToQuoteToken(uint256 lps_, uint256 bucketIndex_) internal view returns(uint256 quoteTokens_) { + (uint256 bucketLP, uint256 bucketCollateral , , uint256 bucketDeposit, ) = _pool.bucketInfo(bucketIndex_); + + quoteTokens_ = Buckets.lpToQuoteTokens( + bucketCollateral, + bucketLP, + bucketDeposit, + lps_, + _priceAt(bucketIndex_), + Math.Rounding.Down + ); + } + } diff --git a/tests/forge/invariants/interfaces/IBaseHandler.sol b/tests/forge/invariants/interfaces/IBaseHandler.sol index 9f3d4c658..4f8e365bb 100644 --- a/tests/forge/invariants/interfaces/IBaseHandler.sol +++ b/tests/forge/invariants/interfaces/IBaseHandler.sol @@ -27,14 +27,14 @@ interface IBaseHandler { function previousReserves() external view returns(uint256); function increaseInReserves() external view returns(uint256); function decreaseInReserves() external view returns(uint256); + + function borrowerPenalty() external view returns(uint256); + function kickerReward() external view returns(uint256); function previousTotalBonds() external view returns(uint256); function increaseInBonds() external view returns(uint256); function decreaseInBonds() external view returns(uint256); - - function firstTake() external view returns(bool); - function alreadyTaken(address) external view returns(bool); - + function lenderDepositTime(address lender, uint256 bucketIndex) external view returns(uint256); function getBuckets() external view returns(uint256[] memory); diff --git a/tests/forge/regression/ERC20Pool/RegressionTestLiquidationERC20Pool.t.sol b/tests/forge/regression/ERC20Pool/RegressionTestLiquidationERC20Pool.t.sol index 1e9db81d5..50da1a654 100644 --- a/tests/forge/regression/ERC20Pool/RegressionTestLiquidationERC20Pool.t.sol +++ b/tests/forge/regression/ERC20Pool/RegressionTestLiquidationERC20Pool.t.sol @@ -512,6 +512,59 @@ contract RegressionTestLiquidationERC20Pool is LiquidationERC20PoolInvariants { invariant_auction(); } + + /* + Test was failing in bucket take due to incorrect borrower penalty calculations in invariants. + Fixed by calculating borrower penalty = borrower collateral taken * auction price - debt repaid. + */ + function test_regression_failure_A8_1() external { + _liquidationERC20PoolHandler.addCollateral(12589, 3027, 11546, 12397); + _liquidationERC20PoolHandler.kickAuction(5580373056879638310723579957702553697154185800606952317169116065283, 673628694582737773359188839547197377524455313247730645, 3238434615599720181679028733329070536752833214808374986356341951234757433, 1); + _liquidationERC20PoolHandler.bucketTake(3483959044, 7480, false, 6128, 931366652); + + invariant_auction(); + } + + /* + Test was failing in take due to collateral constraint being round down and less collateral was used to repay all borrower debt. + Fixed by rounding up to scale collateral constraint and compare it with total borrower collateral. + */ + function test_regression_failure_A8_2() external { + _liquidationERC20PoolHandler.lenderKickAuction(32707, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 115792089237316195423570985008687907853269984665640564039457584007913129639935); + _liquidationERC20PoolHandler.stampLoan(1, 115792089237316195423570985008687907853269984665640564039457584007913129639934); + _liquidationERC20PoolHandler.takeAuction(71607203288150432617752586299752325700809962217893299105344626635399670961037, 1407433933, 201963073509, 0); + + invariant_auction(); + } + + /* + Test was failing in take due to collateral constraint being round down while calculating through borrower debt and borrowerDebt. + Fixed by using CeilWdiv instead of wdiv while calculating collateral constraint to always round up. + */ + function test_regression_failure_A8_3() external { + _liquidationERC20PoolHandler.takeAuction(26177409091395859259214754727, 2228, 1235, 1028254131108805440); + invariant_auction(); + } + + /* + Test was failing in arb take due to incorrect kicker penalty calculation when kicker and taker are same and both gets lp as reward. + Fixed by calculating kicker penalty to be equals to total lp rewards - Taker reward (collateral taken * difference in bucket price and auction price). + */ + function test_regression_failure_A8_4() external { + _liquidationERC20PoolHandler.withdrawBonds(115792089237316195423570985008687907853269984665640564039457584007913129639934, 1106571879666471992422126415932998667, 1); + _liquidationERC20PoolHandler.takeAuction(1, 4357181303565761581481420624418625341908084, 115792089237316195423570985008687907853269984665640564039457584007913129639932, 1); + _liquidationERC20PoolHandler.pullCollateral(1649091324340025315995186327618864160776161241, 2181528126871, 1965741113938939463317126670739876832461939774927378255531235325395); + _liquidationERC20PoolHandler.drawDebt(68161, 14061, 973436887473582363402221359893); + _liquidationERC20PoolHandler.transferLps(115792089237316195423570985008687907853269984665640564039457584007913129639935, 213151482981712477628530516228567956560745791366283812631912364452304, 3, 0, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _liquidationERC20PoolHandler.drawDebt(0, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 1); + _liquidationERC20PoolHandler.takeAuction(2485, 5272, 1031840912, 18777070038542195298214975226471); + _liquidationERC20PoolHandler.removeQuoteToken(115792089237316195423570985008687907853269984665640564039457584007913129639933, 0, 25856141553490006665960451029957189196503921259365569544991571288943654, 265387129941213675242); + _liquidationERC20PoolHandler.removeCollateral(683263830118317396029527361129696006836175820138018328290112399795517091, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 1352261258086370231859932358250510979577984135169417106550, 45451622258719725310627650697080694167655914828437); + _liquidationERC20PoolHandler.moveQuoteToken(192523996731194721095627, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 2270685815936828125225767305289, 516849470254903023103, 4286673537243475793235534545886); + _liquidationERC20PoolHandler.addQuoteToken(128222088341180102397575833404514544302942993744794712, 108603807113347866118, 1, 115792089237316195423570985008687907853269984665640564039457584007913129639933); + _liquidationERC20PoolHandler.bucketTake(437995719506453073927178171450999258981540842, 1, false, 10505745254535225521787303755428772101316447294490000685852, 1); + invariant_auction(); + } } contract RegressionTestLiquidationWith10BucketsERC20Pool is LiquidationERC20PoolInvariants { @@ -2122,4 +2175,4 @@ contract RegressionTestLiquidationWith18QuotePrecision4CollateralPrecisionERC20P invariant_exchange_rate(); } -} \ No newline at end of file +} diff --git a/tests/forge/regression/ERC20Pool/RegressionTestReservesERC20Pool.t.sol b/tests/forge/regression/ERC20Pool/RegressionTestReservesERC20Pool.t.sol index 10c0cf95e..38238fc7f 100644 --- a/tests/forge/regression/ERC20Pool/RegressionTestReservesERC20Pool.t.sol +++ b/tests/forge/regression/ERC20Pool/RegressionTestReservesERC20Pool.t.sol @@ -1055,6 +1055,54 @@ contract RegressionTestReserveERC20Pool is ReserveERC20PoolInvariants { invariant_reserves(); } + /** + Test was failing due to borrower penalty not added in reserves calculations for reserves invariants. + Fixed by adding borrower penalty in increaseInReserves. + */ + function test_regression_rw_reserves_failure_2() external { + _reserveERC20PoolHandler.pullCollateral(467812928760450922852130520517, 0, 8875981380220900699974754772374433563827538899982250783154248); + _reserveERC20PoolHandler.stampLoan(40175363097800960342714213669375739863439895429878092142484989154449, 409061); + _reserveERC20PoolHandler.settleAuction(115792089237316195423570985008687907853269984665640564039457584007913129639932, 1, 0, 0); + _reserveERC20PoolHandler.lenderKickAuction(6739921392061593446919, 6665134088409172498708598665753565015506650372591945929089778543248096029475, 28995118252860325273433400612247); + _reserveERC20PoolHandler.bucketTake(115792089237316195423570985008687907853269984665640564039457584007913129639935, 115792089237316195423570985008687907853269984665640564039457584007913129639933, false, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 3); + invariant_reserves(); + } + + /** + Test was failing with underflow when debtCollateralConstraint is calculated with borrower price equals to 0. + Fixed by setting debtCollateralConstraint equals uint256 max value when borrower price equals 0 to trigger third case in `_calculateTakeFlowsAndBondChange`. + */ + function test_regression_rw_reserves_failure_3() external { + _reserveERC20PoolHandler.pullCollateral(689310072489575950194610941862218313559051158375867529942715794, 99036455857404432, 6869705889740062461982024); + _reserveERC20PoolHandler.settleAuction(115792089237316195423570985008687907853269984665640564039457584007913129639933, 6742192, 213010309037469, 559253357385477068169816814589744715662918367352352023924236308825157221); + _reserveERC20PoolHandler.bucketTake(1016146854898171779840580985646, 702533447184886148876700400367357570569398118557415200792466345280405503, false, 529372371950495425561109650, 2068665645832452894016891); + _reserveERC20PoolHandler.transferLps(22896729871095067, 33099474, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 3, 0); + _reserveERC20PoolHandler.addCollateral(1243, 20194462732101988290791998389, 1689661434, 2016395110395212283077154); + _reserveERC20PoolHandler.takeAuction(1053065795079038070957917, 7983715169874533544149183933, 10149841974673137113234915054, 14423198); + } + + /** + Test was failing in bucket take because of kicker reward not added into decrease in reserve. + Fixed by adding kicker reward in decrease in reserve. + */ + function test_regression_rw_reserves_failure_4() external { + _reserveERC20PoolHandler.lenderKickAuction(41448389421126432182726016581, 2602898649473330, 17196485686943506801781467688426213134395453464); + _reserveERC20PoolHandler.removeQuoteToken(6486, 9034, 4005, 10875025938101873); + _reserveERC20PoolHandler.kickReserveAuction(19936, 1602202823226609409493879949424965818777601); + _reserveERC20PoolHandler.settleAuction(43422653358836780601775799271338712538765906652243288953354029299518452019549, 2, 222121421529490670116623911755462896144535, 1); + _reserveERC20PoolHandler.lenderKickAuction(7275, 24173, 999999); + _reserveERC20PoolHandler.lenderKickAuction(8295, 33429, 8199); + _reserveERC20PoolHandler.pledgeCollateral(115792089237316195423570985008687907853269984665640564039457584007913129639932, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 64692573191385631161743023454013934845178776); + _reserveERC20PoolHandler.addQuoteToken(4, 0, 831011391, 15); + _reserveERC20PoolHandler.moveQuoteToken(8396, 21445, 1150130547533370594, 74603461372738258605591962, 32485); + _reserveERC20PoolHandler.removeCollateral(593804, 3, 1, 9704287815361877708977161768658767); + _reserveERC20PoolHandler.addCollateral(10494, 3176, 6582, 1000013632258236536); + _reserveERC20PoolHandler.bucketTake(34739, 9151, false, 14043, 17239); + _reserveERC20PoolHandler.moveQuoteToken(9754514353313, 109703, 3, 2240925396839878898078075591575488344995370, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _reserveERC20PoolHandler.bucketTake(1, 0, false, 115360980752823, 23554795443976594444786153429144989301756); + invariant_reserves(); + } + } contract RegressionTestReserveWith10BucketsERC20Pool is ReserveERC20PoolInvariants { @@ -1348,4 +1396,4 @@ contract RegressionTestReservesWith18QuotePrecision4CollateralPrecisionERC20Pool invariant_exchange_rate(); } -} \ No newline at end of file +} diff --git a/tests/forge/regression/ERC721Pool/RegressionTestReservesERC721Pool.t.sol b/tests/forge/regression/ERC721Pool/RegressionTestReservesERC721Pool.t.sol index 9aaa9abd1..3daac912b 100644 --- a/tests/forge/regression/ERC721Pool/RegressionTestReservesERC721Pool.t.sol +++ b/tests/forge/regression/ERC721Pool/RegressionTestReservesERC721Pool.t.sol @@ -1265,10 +1265,9 @@ contract RegressionTestReserveEvmRevertERC721Pool is ReserveERC721PoolInvariants /* Test failed because neutral price doesn't fit in uint96 type. pool inflator 1788146574311565067709708 - borrower t0NP 1226147737092460887612598 + borrower npTpRatio 1226147737092460887612598 borrower debt 4502726079310150309955771136797 borrower collateral 87000000000000000000 - momp 6822206200573474997951871 bond bondSize 45027260793101503099557711368 bond factor 10000000000000000 neutral price 2192531875681761460142783972780 diff --git a/tests/forge/regression/PositionAndRewards/RegressionTestBankBankruptcyERC20PoolRewards.sol b/tests/forge/regression/PositionAndRewards/RegressionTestBankBankruptcyERC20PoolRewards.sol index 1784d5640..c58332bf8 100644 --- a/tests/forge/regression/PositionAndRewards/RegressionTestBankBankruptcyERC20PoolRewards.sol +++ b/tests/forge/regression/PositionAndRewards/RegressionTestBankBankruptcyERC20PoolRewards.sol @@ -36,5 +36,395 @@ contract RegressionTestBankBankruptcyERC20PoolRewards is BucketBankruptcyERC20Po invariant_positions_PM1_PM2_PM3(); } + + // Test was failing because of `(((tu + mau102 - 1e18) / 1e9) ** 2)` becoming more than max limit of uint256 due to high debt + // Fixed with reducing time skipped in setup from 100000 days to 1000 days + function test_regression_arithmetic_overflow() external { + _bucketBankruptcyerc20poolrewardsHandler.stake(6896318739925897886189247783689616912, 1590163, 2, 5688123131144312514755107); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(17317, 82811632090972520860339125222186388174810191857321772017180113650309637681174, 36183411359542968180819498843191329944675962195184522815400173109497640045084, 36183411359542968180819498843191329944675962195184522815400173109497640045125, 19228192993203316367726728173133990710204659); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(886000000000000, 112677305303603608793464000990919617579761525091244043308691041092632466068329, 3966754565367876880350885451679960164951761383523769778082696271101602, 2039, 952915384615384615824); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(2849871794357244235869, 3966754565367876879428138587689740691886557263849923988907562808019157, 90722805810612960, 2407, 15129); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(177039972880383490828179033660932658535136887032468656, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 38713024359055902250662472670480188719905855, 1); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(1647740717046213962030928987916339867520444123409750393400408, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 92438060068404637120570616271893238026003952273845567189711565754357678, 2, 740729473877833425174185945952031582872090596768955274878); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(12280, 100059799535193028234836608013586712161184179292262900980302289180450773349084, 39906399523299059107967942071142446494738195742899699015085450065764556124872); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(563808366315521888139814758131568062747410028498, 717762288499217961103026455619904233444784602603, 639614423076923077217); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(179970444047069616, 3966754565367876879135983927223377519202887228228036839903452619493402, 4733); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(7077, 2849871794357244236815, 89565878125998494124776859909564617778044840185111596024548341691824014913081, 67510848143351065130353186739542299459422428500681234436222588824509516955128); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(345331730769230769391, 1153129030861181662264128353544855947712724763189, 13746, 10698843914281808001296099412637890910894001332208464018741338351061051465914, 100847138996028487776982507526530541183387119239170631100097115978417618128629); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.stake(36183411359542968180819498843191329944675962195184522815400173109497640045129, 48819922315949799267070624682529131378372410957, 4181, 112677305303603608793464000990919617579761525091244043308691041092632466068152); + _bucketBankruptcyerc20poolrewardsHandler.stake(2244, 995, 58606104743229720510079823024387185916963550951287480571399502469054769761605, 76550499216257555889321112575510855021078684718864441654047861970454785529430); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(37559901722735453672500465593449923350885790554902835, 551970007141884604422321369676694640861689485316027729520843135985700546, 47661766323110); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(283600966131550275, 4225, 3054); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(3305681070264227794977, 74106, 12559999863349, 3, 115792089237316195423570985008687907853269984665640564039457584007913129639933); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(537, 13076, 13358); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(923000000000000, 5118315719793605164353342667742056876611746894854750490526105565680017101203, 66382540837033874); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(3, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 10266341061973857960018410655132814, 1, 1); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(16522, 24995945723326373875772837096154005408860764913638412228031745013630478857018, 512011103318869781848676); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(2, 350590244621993631975269433997674629739798644299962688761173, 1344692490437700114798712237992600701, 11956262); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(73624586998592616701514720900276129068340183692521862970378800053138201630477, 68710165003106503923300701473932010517182965684103004549833568373358389724401, 71800436766229664078026657500885479541081649751618083508801195706457245577220); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(9453, 19205, 66868048033817959774686748497699809781406078236372444649234275513206538861672); + _bucketBankruptcyerc20poolrewardsHandler.stake(8925811310805445351997878058708827307181477404039834765939848102762107933524, 15396, 333333333333333335, 112677305303603608793464000990919617579761525091244043308691041092632466067970); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(49354806076664609737639320143283225715325929918170457855370734498987169336, 0, 0, 224207154149060304368571539032, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _bucketBankruptcyerc20poolrewardsHandler.stake(115792089237316195423570985008687907853269984665640564039457584007913129639934, 1238008048, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 2169063360537137360112800101939791654946494300546407780004241577631164); + _bucketBankruptcyerc20poolrewardsHandler.stake(115792089237316195423570985008687907853269984665640564039457584007913129639934, 2345851545937962757778643762496267029085540856037776148147808038944642, 5957091736115285211, 27985731991685908798232634683132989817806071982114803741897441260168560867); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(3, 1, 770986253285442867064880897583817379708, 92781664698833630287489852236611504234525413121274842462364219872); + _bucketBankruptcyerc20poolrewardsHandler.stake(1594, 107191883964854757344296271860238969622927688664914404668659378108385854836026, 3966754565367876873370423057737583368405849023294119111275034969686468, 19958575429898560154085169419221224945725333143564312471139253950974388039284); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(115792089237316195423570985008687907853269984665640564039457584007913129639932, 1, 2); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(77052356306827782713422247930543027861392973120644625016, 1798476982980588193703723436375810811222069733299353125141863312, 1098297152145905559672257161091692); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(2, 342041592964680825954896142059203952628580209831935619634002805536, 39846960399867003370202173839379955192, 822343706632112, 3); + _bucketBankruptcyerc20poolrewardsHandler.stake(7984294068074609994912921437324, 7838, 15189, 175000000000000); + _bucketBankruptcyerc20poolrewardsHandler.stake(24962334191555090884200901697709326249765046066909050188293351411730598993973, 2147483648, 393502552471956099440181996575832631444286908472, 14802); + _bucketBankruptcyerc20poolrewardsHandler.stake(7256, 929000000000000, 675412562135798344425486121401750, 13510); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(109677534373829370582420891034109789248617180581764663703953628089987520264326, 2573764082904, 2908); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(0, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 115792089237316195423570985008687907853269984665640564039457584007913129639933); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.stake(1587, 11728, 20371, 1761736553); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(2849871794357244224888, 21613,36183411359542968180819498843191329944675962195184522815400173109497640045063); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(115792089237316195423570985008687907853269984665640564039457584007913129639933, 7816592721461, 547796365072063422163463132831470635072549324118139340225274709, 23239411057593528819373457684352214287995257450694130149326937362); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(601672641157204830463731144581, 1, 10); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(0, 1, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 3844156373059697976150225328289758, 21067959307417482890549604370787421964344610209838270154238906991002); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(68710165003106503923300701473932010517182965684103004549833568373358389724401, 36183411359542968180819498843191329944675962195184522815400173109497640044952, 27681604022032244008232927876918610662012006233608617573888982434118344074872); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(115792089237316195423570985008687907853269984665640564039457584007913129639932, 546249949564771975556206661259711240, 2, 198775369677794427185735801472315926769782965724); + _bucketBankruptcyerc20poolrewardsHandler.stake(500000000000001, 112677305303603608793464000990919617579761525091244043308691041092632466068117, 7746, 917812924747606707090506589076440198415899010589); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(47390443050477, 2, 24907716377757111202952223651177368542, 99036046654470658779217472134, 223412317271864254); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(584150118814135535797598359987484192650707686887, 4759, 27314416541679884417682362568089041974037272849399973641581125802989563555875); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(2849871794357244244015, 264054995773979190, 447, 451433653846153846362, 9648); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(21050, 7775694,154085490025371729225110012928624230180770264485398324359658277233, 57927770334825); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(27314416541679884417682362568089041974037272849399973641581125802989563556154, 741712500000000000341, 102395000692947319608275989700597991885819255417485385121140134029182011063769, 12630); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(0, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 3, 440744070881956564449467649, 115792089237316195423570985008687907853269984665640564039457584007913129639934); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(10000000000000000000000000001, 740, 7258); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(88726916073212290156777326422200, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 34199279288); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(17214, 73384897344814417155958327430359004483378729061591027007351093540094357466111, 51206296630672440992795321509376579418034509656975184376065889683943438593770, 5884, 8262); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(2044562291296528291030625278429523218566755073094910438325803240354, 1, 15304323218114486738795227081682471, 19829306); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(115792089237316195423570985008687907853269984665640564039457584007913129639934, 124837474259495102675939548974323950, 329054301975170069286574921653462268546056642575848355092114042163); + _bucketBankruptcyerc20poolrewardsHandler.stake(199147622511101623, 789000000000001,231, 33101730025310197535578397667035503858659584593443933073973462411188265487645); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(32357, 162121775210335745176768462891133518974, 2); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(3, 235172445463430520134164649932838126511768787911883505, 2, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 1); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(115792089237316195423570985008687907853269984665640564039457584007913129639934, 0, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 8556272701020798093908796721428703862785571616320106889880411706632, 898342879931592588219); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(6871437890782, 22722437225746852199549, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(115792089237316195423570985008687907853269984665640564039457584007913129639932, 115792089237316195423570985008687907853269984665640564039457584007913129639932, 2, 49335930053431267338133128938678, 12312700374952538413699663457513300906362172890995955163025450435265437519460); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(115792089237316195423570985008687907853269984665640564039457584007913129639935, 115792089237316195423570985008687907853269984665640564039457584007913129639932, 867997253226679023134472172637178866960140585025356872075477020, 115792089237316195423570985008687907853269984665640564039457584007913129639935); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(14195, 4120126606, 892000000000001); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(53143361220254641097319023834726093633429636617299696, 0, 115792089237316195423570985008687907853269984665640564039457584007913129639932, 115792089237316195423570985008687907853269984665640564039457584007913129639932, 3008666890405061958087053360596855); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(2849871794357244241734, 7376, 4733); + _bucketBankruptcyerc20poolrewardsHandler.stake(491801577241747986710629564741072784295090200116, 4666, 336338206907638295, 3966754565367876869122227334475572820434993478726803479380549997488878); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(588, 9789, 5083); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(975573743, 2, 7486511129908263831530464268126, 115792089237316195423570985008687907853269984665640564039457584007913129639933); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(115792089237316195423570985008687907853269984665640564039457584007913129639932, 408377816173582479794442004131690473732206230537105633285620578233, 0); + _bucketBankruptcyerc20poolrewardsHandler.stake(115792089237316195423570985008687907853269984665640564039457584007913129639932, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 3193830813357417, 240); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(0, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 115792089237316195423570985008687907853269984665640564039457584007913129639933); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(234667819334761949964119092206494130890231852099316545331, 11931498178817218152978210620161711035796631751178664213653196, 6840034619969503616899963423366754377629584809987338693684203); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(0, 1, 2823373119980992364828421558687377775878598015914019948); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(63937, 16773945002237412540693101797847272493598737453594325081026067588528, 115792089237316195423570985008687907853269984665640564039457584007913129639934); + } + +} + + +contract RegressionTestBankBankruptcyERC20PoolRewardsWith12QuotePrecision is BucketBankruptcyERC20PoolRewardsInvariants { + + function setUp() public override { + // failures repoduces with Quote Precision 12 + vm.setEnv("QUOTE_PRECISION", "12"); + super.setUp(); + } + + // Test was failing because of `(((tu + mau102 - 1e18) / 1e9) ** 2)` becoming more than max limit of uint256 due to high debt + // Fixed with reducing time skipped in setup from 100000 days to 1000 days + function test_regression_arithmetic_overflow() external { + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(3966754565367876882011475305970374373581843216523327606696944469982560, 23951, 27342775513801048612025508136217148135354231891871249189205419889059958895920, 5764); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(115792089237316195423570985008687907853269984665640564039457584007913129639935, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 277955739357896056509186172170724926307041); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(115792089237316195423570985008687907853269984665640564039457584007913129639934, 1410631634716305975327239311667501746230064938363700, 165627380598340247145446842744163, 3, 115792089237316195423570985008687907853269984665640564039457584007913129639933); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(19, 2530080042266327931552762435318905970448414613174692360332206645244, 1); + _bucketBankruptcyerc20poolrewardsHandler.stake(8666801014510249463714719779804008890723512, 1,83443108184118454880135593969467466093223604269, 15883848302414522401895); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(12882, 7777, 6629, 97879245264338194306861131699634660522218295410970784557138028426270717400370, 8368); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(13483626428470537411264656142812, 3, 43261357659, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 1388408991433152321764177891234838153250463504820877); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(1, 2, 20563013357962289806221756347401611786110937543040356031901156, 447919006151828756764428252561915147896770196082188602773330761, 798396599462289786815989310634148690896897281016819117397861); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(92248702659654157400825310446726854110696903499169410212619700758795452822, 37604, 3); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(3966754565367876873053743387718720534708426719378234395015112294331820, 1891, 6354, 6407738580936730947617400026186481015907031668070029619638042254901247); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(155528622244088217616721520914751415058731841773, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 517704163087, 288990527056564619478); + _bucketBankruptcyerc20poolrewardsHandler.stake(0, 103562875210896097905879456787026624674683989786414355636238913207580190275, 4449509262329152679, 2); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(115792089237316195423570985008687907853269984665640564039457584007913129639932, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 0, 1); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(12789, 516496153846153846391, 1373, 2432); + _bucketBankruptcyerc20poolrewardsHandler.stake(17298, 2520288506, 3966754565367876862909903626043389090569250934025238262077644133072068, 70048973491614882813651882306278555733916041147); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(14730549569217254337324272971273439639, 10712676910574077307719914120290505539758384452430355043102986598551, 25861299350166086615951335); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(19490, 3145, 100958019455552403241513419952879830954846771871560814580751995001715468196982, 4320); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(18380078816620787637106444195826167006943,9105121993717164823200252859, 39582079114752207760062142810162); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(102938198731890455483, 3, 52050632211266); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(500, 924977286184975233873859450789056758036024240832241462431898388643636693224, 232003688276085664164189481417956820170145390, 504095117088782794907830496954549563124074003355); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(10009, 522, 229781691635202364607605263483, 13964, 6303); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(2585532, 30263717, 295729539); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(1984, 4652, 2725046678043704335544); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(349, 10557, 401731786528032649302150062457257044539448918705); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(94291391897249807881798731698058020996506531563934658123907732088334042997896, 1683, 922886538461538461965); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(115792089237316195423570985008687907853269984665640564039457584007913129639935, 3, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 5009532820319301678432792599939739); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(1368179552630450116, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 34412996693170762789699607283878930530798448071823276400203849362089566); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(30743674041281512912789390937090188969141866220723941124963519834291052939594, 3966754565367876873053743387718720534708426719378234395015112294331821, 3693, 199999999999999999999); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(2849871794357244233297, 5729, 9436, 3966754565367876848917250723019599313865029386375836114489444464347617); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(13336, 751722115384615384961, 79902525729132112172182628727403585636031841353378040928728196869469094823677); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(11848, 88935689212870099548894352559477176008817225920440919577532104643626259385686, 1626); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(58606104743229720510079823024387185916963550951287480571399502469054769761570, 15156, 216879045993470961471641212581); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(115792089237316195423570985008687907853269984665640564039457584007913129639934, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 883524181985928268306667951943684061963202522679192596148943284885177111); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(2924, 15953431440961698465116049405554517352474802910093790483384259164665308441857, 11379, 3966754565367876865848146090991267689838419410304387485907095558443874); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(30743674041281512912789390937090188969141866220723941124963519834291052939594, 24095571472578277997716226198122273937443180744573574132530939729041516935842, 3966754565367876862304666055471450811092813038866066209363567991707702, 938000000000000000001); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(194697860333279706454142791011527465766470841248150462925425546902865792, 10918718947124557284093286805184333760565060406738006519481479722466762779012, 168468217510963482200654846013032790275226); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(58347301615953207705596250146, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 3, 0, 115792089237316195423570985008687907853269984665640564039457584007913129639935); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(115792089237316195423570985008687907853269984665640564039457584007913129639935, 940844563678598855758006578093833226886661828778784869140315469182111914414, 319314552411346300225910579); + _bucketBankruptcyerc20poolrewardsHandler.stake(112677305303603608793464000990919617579761525091244043308691041092632466067904, 9141, 76550499216257555889321112575510855021078684718864441654047861970454785529449, 90156338318561149845207557102717525639219958457419849688382040762167829323088); + _bucketBankruptcyerc20poolrewardsHandler.stake(485466346153846154070, 4047, 41236831521177614171812965194954188943377267884762881554238952423602296083644, 748928859761915073403783232409846872252823377512); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(1842, 814000000000000000000, 7386, 8949, 41793232874593872983939891402504271449042722654854023829157932315219071622588); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(112677305303603608793464000990919617579761525091244043308691041092632466068159, 2849871794357244244502, 104081267022762746751665747606660, 71229933733954908637545747917262425351075939551041697044067017386326458518973); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(24517088812426303533366187430638951177066673723059003443596328868588485096503, 58606104743229720510079823024387185916963550951287480571399502469054769761351, 64416168674241980143640578666243527631773805575549605444878358964770079875198, 857, 1500); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(3626, 88054211744890545047854682720362692474121698843596563640244510813389729172929, 1428317552094315315517906204753391481814958706674); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(5152, 1112, 114255409676579882224300171557671234047763533365509370065937802142537610636077); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(115792089237316195423570985008687907853269984665640564039457584007913129639934, 418054629776517004596675, 3, 1, 35279645324127465272326759608); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(6728, 82093671015361185348901971732692156706718930259320396354351606002076191819315, 956999999999999999999); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(35118430032806250297491677757753828041611787435033927125054378068651577059830, 6369317236171228082814892, 7387); + _bucketBankruptcyerc20poolrewardsHandler.stake(11817, 9275, 5385, 1207369317); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(51953396903491667884348938599208174393962381719940333807794356892097124201559, 684, 10657, 76550499216257555889321112575510855021078684718864441654047861970454785529116); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(115792089237316195423570985008687907853269984665640564039457584007913129639934, 2, 1, 148281571130219420965533181191380429225208794627, 0); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(1, 4239153815896722593765078521373119840402276014176812838, 322); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.stake(5832, 114325486997113895, 25771513998157767631206, 58606104743229720510079823024387185916963550951287480571399502469054769761640); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(115792089237316195423570985008687907853269984665640564039457584007913129639932, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 1, 206482); + _bucketBankruptcyerc20poolrewardsHandler.stake(7927883901223247210108134121974524593936498558593831315905690, 1021983417944036249199635837038396943666727341096303405788220, 767087832347197496171017453170, 115792089237316195423570985008687907853269984665640564039457584007913129639934); + _bucketBankruptcyerc20poolrewardsHandler.stake(115792089237316195423570985008687907853269984665640564039457584007913129639933, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 1, 2874117576384309917899907813356673917244578826423882407945693049513858301); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(115792089237316195423570985008687907853269984665640564039457584007913129639932, 1, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 513981014459270617692452615619057434252871630198349563427); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(6300000000000042791841612, 19286837295908603553266787544912289890662357020459285979135247069961616838694, 6000000000000000001214045); + _bucketBankruptcyerc20poolrewardsHandler.stake(3, 582489990557683665156778587139, 3, 115792089237316195423570985008687907853269984665640564039457584007913129639934); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(3, 0, 35168320991909411639035941130092257126013094953); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(14813, 37985565034524940, 2145, 20082); + _bucketBankruptcyerc20poolrewardsHandler.stake(4709, 27314416541679884417682362568089041974037272849399973641581125802989563556408, 12840, 12086); + _bucketBankruptcyerc20poolrewardsHandler.stake(69038858858407874287609809184671540840387410961394619992844383524920134424318, 36183411359542968180819498843191329944675962195184522815400173109497640044724, 3966754565367876866196088114064796746224277022091850411132522280259220, 12791511181959941491752949292075057207018412420834161138452224935883231372655); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(18192533247055195113309035583539, 1, 328582664058452398603332112189467575863731833506487867823485836, 4602471638333068831301900889260476934074379204208975, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _bucketBankruptcyerc20poolrewardsHandler.stake(0, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 56337316561494319009393836013630587683761391839374494258944738437916245958839, 2640259112854475455524369794554852490061268235127682838018933103811); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(5492450293033381591765430790693418, 137254969503698002491565595388909, 0, 20988469343989249870821526948977277703231799942855); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(3349, 9610, 76550499216257555889321112575510855021078684718864441654047861970454785529360, 82356314548626890097785557483647633355000630013025733579942984190419831216102); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(115792089237316195423570985008687907853269984665640564039457584007913129639935, 2, 3, 114146396809673629522339599); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(115792089237316195423570985008687907853269984665640564039457584007913129639934, 126618531077782339112782240609126751547958141385, 115792089237316195423570985008687907853269984665640564039457584007913129639934); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(115792089237316195423570985008687907853269984665640564039457584007913129639934, 3, 115792089237316195423570985008687907853269984665640564039457584007913129639934); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(3, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 115792089237316195423570985008687907853269984665640564039457584007913129639933); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(115792089237316195423570985008687907853269984665640564039457584007913129639932, 0, 12162819707221123631400623212); + _bucketBankruptcyerc20poolrewardsHandler.stake(105121213529450126323853881532755536544144710500048612197500352815038325229734, 112677305303603608793464000990919617579761525091244043308691041092632466068251, 293033093642118704626758970120533267875914812703, 371788002); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(115792089237316195423570985008687907853269984665640564039457584007913129639933, 0, 20429554514719932257185316611193961084030832868502); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(676552018761914467, 115792089237316195423570985008687907853269984665640564039457584007913129639932, 59118278259681); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(2156, 7545246309671992862734104294126293323679086381417630106133956125163420559268, 4364969487729155111838774393422, 132396289780528671, 8264); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(112677305303603608793464000990919617579761525091244043308691041092632466068059, 2082, 14781); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(337194160126177136918766792240, 3, 1313730499206179905094243898173812338722150955516328682874207); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(115792089237316195423570985008687907853269984665640564039457584007913129639933, 2, 0); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(471865840740346309280830746508987758285335124696, 13021983620616879922120557237553195351332782342710477424375088385066717568307, 436588081726929394630979089567144071868327424332); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(17374180793863161866451563901603790046833465309545825925601, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 855794879660868210624); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(0, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 439349802057718495654968534586028); + } + // Test was failing because of interest accumalation to overflow uint256 max limit. + // Fixed by Reducing max interest rate from 50000% to 400%. + function test_regression_interest_accumalation_overflow() external { + _bucketBankruptcyerc20poolrewardsHandler.stake(320307692307692307841, 2490, 10917, 403196809217289663458043223580906563641609617294); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(15059177663891191985498469564581, 21691241494814563657, 5959198137984416944871985040941211962546971878394061014854717427126670802); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(1, 115792089237316195423570985008687907853269984665640564039457584007913129639932, 2, 306748590411024027068452057, 3); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(0, 3, 3, 44869774749435413944328478986895177316804030, 2); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(115792089237316195423570985008687907853269984665640564039457584007913129639933, 667409171832157313382210046675580725011953, 170966693897056629150807196294457349572402758607401923355019500107511084513); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(115792089237316195423570985008687907853269984665640564039457584007913129639932, 19549319890719740959827156450505379259184673736260904583824030491, 16629388526339); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(1, 57, 2126726397172127776919, 3); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(10662442004167, 0, 5497097760623451146595, 3162190482019759261701358441242229); + _bucketBankruptcyerc20poolrewardsHandler.stake(1, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 4633); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(195082403288206510116943243208164172979846145506483861331524728636984, 5999490491512003998567204139527071137962581199636349206, 1); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(193, 115638053, 82905768405815550325167864157103591796198207319836507298376269364238808467864); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.stake(115792089237316195423570985008687907853269984665640564039457584007913129639933, 728230189013838280072632353261014942101509879986, 1074852977686923754516502207503688995019457654331626079784, 8647989100256796072321456855285912878676340053147534437521304860653); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(3941357502157973923804, 2, 806977082765068646659096738618743289712629038, 95470398010431964952450128551272930452522452449699886025877059807238, 1); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(36183411359542968180819498843191329944675962195184522815400173109497640044908, 5526, 3966754565367876855970249316229461606728002012105551523079085776320493, 12000000000000000000786344314428468140209160332, 1514); + _bucketBankruptcyerc20poolrewardsHandler.stake(115792089237316195423570985008687907853269984665640564039457584007913129639935, 19347515940517406236500101946818541192254229344198927883872669126, 0, 115792089237316195423570985008687907853269984665640564039457584007913129639934); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(1236588951273351231845418839930179263983011495754, 38238240862444672488745854665, 105710195453976313965439090442863258002796095759252242871256962165021905861650, 447301751254033913445893214690834296930546521452); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(46514948025651225960345695072605648432715982671974779016300427285754698287368, 3286, 3218715805466846511984533600393324923883748231); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(3950340310148269005, 5673061940259815795875572950552217903, 0); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(201, 16652, 456263400021039761424850168808020383038614345114, 185177884615384615469); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(844186718371423468438148597031199325852724093549, 8971, 1238939858024599757491003772585973626666495470478); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(14560967560043099906703147047009467303604341499091340414611613631940255690293, 1721, 1330742788975674320956191865797062835971931496250, 8012); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(610999999999999999999, 18990, 2964); + _bucketBankruptcyerc20poolrewardsHandler.stake(1, 2202462407395028941916385359630457052998061369773792102517381208520162, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 115792089237316195423570985008687907853269984665640564039457584007913129639933); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(259629493051510264, 23614305666380977416230669400318875317806232271123308657121989217833132243233, 2497, 27835018298679073652989722292632508325056543016077421626954570959368347669748, 1606); + _bucketBankruptcyerc20poolrewardsHandler.stake(115792089237316195423570985008687907853269984665640564039457584007913129639934, 4650754146616051773693243800451532316887707892427, 2674637045933147252314476540226577815868397623, 1637859); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(32610811746778589434426055746005034344393175264036753585460265204263347653842, 16005, 105710195453976313965439090442863258002796095759252242871256962165021905861709); + _bucketBankruptcyerc20poolrewardsHandler.stake(27241022853949367504447088193, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 128000899661578863761148718566665636525956915466064429, 1336719368342255666688); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(41124169807925345164795, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 1313063028941469943130200174691186594877948408346228981); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(2166715437819344420775617703353734409787244706488647403995037751254234644362, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 7532212); + _bucketBankruptcyerc20poolrewardsHandler.stake(14552177917818508405730171864883921324, 0, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 84190559757713757784279975706433133519542327009581632460886117089373); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(37747710333430245980940452738832839721522435977096927851794211126014890045043, 105710195453976313965439090442863258002796095759252242871256962165021905861568, 4881, 3966754565367876869122194268884518216957992861677661334548387666061342); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(159533269946056829911817908703969087399676830547153393250667762079770747, 120375821746749532031, 553664897755275959629); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(2318, 371788003, 105710195453976313965439090442863258002796095759252242871256962165021905861824, 57957110594642022010328291066590663082489422500, 378363461538461538635); + _bucketBankruptcyerc20poolrewardsHandler.stake(1, 3108493389566117837926341948558162909763275523381432406469124236768340906924, 32229393624772079505360513009288184415901939, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(2836923789, 82757687462225415771947516030365134680378685014411112583900985134363263813950, 17992734256423583958967370161492784553176489409); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(1, 2, 1599018514952142375998297880); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(55687575924400638, 727999999999999999999, 15644); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(1, 2673041966562049323144905243406346442490148198615, 1285995676085316511341291864375645429377044076357986037173062379358204); + _bucketBankruptcyerc20poolrewardsHandler.stake(27836410677470140405893559165022839553284246026566794216457, 26100442293941930306313869947915225019447736484493936778052910988, 1100121169003966414850619669523011925033070895519974812092, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(751722115384615384963, 87573722621992251438460370142942144054516549109457068516979097052450755011736, 3966754565367876854520184869943068556144348793969914759895680118784807, 27984893582647316189577999054762964794852908603917399358854612125647292485578); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(15048, 20980142891430666358441099170678931589412918730, 26229794335232538522551515320652626439652093573752750988891734989405951307592); + _bucketBankruptcyerc20poolrewardsHandler.stake(115792089237316195423570985008687907853269984665640564039457584007913129639932, 1623645501211, 581895706741971570416382, 115792089237316195423570985008687907853269984665640564039457584007913129639933); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(16294, 37775847772112785254257, 20408); + _bucketBankruptcyerc20poolrewardsHandler.stake(233076476716696715, 19720626000000000000021835, 14786, 880); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(91, 48915418688551403693013933582174377748045,1, 0); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(8520254760456735866522434792660074894149362458110124278618188561008801076487, 4508341423132101367979353817313302855733981519104609141429822885854284517273, 1045732366170946687500335725634396288218029048535); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(5250764587436405674967118092556206155749365731, 141015099610895938496827107324000508240276523703380995216176939659, 0); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.stake(75715332515, 20249, 139492422255, 105710195453976313965439090442863258002796095759252242871256962165021905861575); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(5433, 21391, 754284941459726849420512743397530252182784738229, 23905); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(192677, 4773, 2683, 940037522744286018063446172177794105409762773472); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(1423000347840435497235966844164533984931800601575, 288276923076923077057, 17572, 4256931000379123634785033661970275022184774617022768398310874942392452426, 139403335757771137); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(2, 2587348281013517652545024121589073614070441106624530521348844741, 519685398); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(84919864282925853877573619845135091960602695946894030665170367426270992811938, 15050648105662257143935681434472465116789984907642743379717753234643085664126, 22213, 16413, 175589814974774645221481909980815519088940506341); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(3966754565367876881842889880294569887040448346346191805828869027190062, 4571, 5227); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(907000000000000000000, 2868991328, 99389371209329274803747059355072193342651880195070161537527945916651123372097); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(2784308567599248162087449504, 3589, 476777860815159664263285898208782485328810582592); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(0, 93446225603511499598845951183108384660272702, 2024254557338330727781790737102999642155730612363585, 191889378792020151); + _bucketBankruptcyerc20poolrewardsHandler.stake(36183411359542968180819498843191329944675962195184522815400173109497640044984, 50146794086275195190991942805708459010074680271220970599602693206755183387706, 2065, 32789382558206698454860319624949663673430750389618486004860947532855016388844); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(3, 29811238, 69968346427577179605244273168972327088469976079256197056454, 1497742154395667232899123570108019263133908353144179120765); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(3, 0, 87185381081925833627461609395751279524164897425148697297070669197775260); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(17279999, 3966754565367876867473138000603430830185306546546874883932992520117722, 776481524764705302352605934280580955971144914555, 962787287); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(19060901126391672628476228072540859898, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 1); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(26920601521589162671147619654088067061266745140905760588388649977853848299620, 1875, 27835018298679073652989722292632508325056543016077421626954570959368347669985); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(553591494574561111154252750468593088203, 26003311767849788325482998126201562168467079599, 3503171015763161693096394522251351236934013944546); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(36822330623891827054618617680243779734013976879104614005453233537599913890987, 2030, 351827466436279533, 36183411359542968180819498843191329944675962195184522815400173109497640045092, 431); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(4307769405459937793464500814388987723043870007160919438680139924065536869, 20774, 20905556733966496908705142171609168952816592958194260630754626678628699156025, 112677305303603608793464000990919617579761525091244043308691041092632466067909, 3966754565367876866027363177544639294642486780494516334079839883146086); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(5612107944, 2, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 3, 3758652); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(3, 13063704682547015731607989179567642095598985357156794100666758119236, 1663082272433979660889799306293339760568971320019141218266316592279716982939); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(698213858938870538487, 14890451379766624461267359941375, 48557935465010072094981800005966219309615168007618540929696328537074564550805); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(0, 0, 1, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(355000000000000000000, 49046620449355538574108822723048473721226797556007972061207479861126558122006, 13060); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(115792089237316195423570985008687907853269984665640564039457584007913129639932, 0, 1); + _bucketBankruptcyerc20poolrewardsHandler.stake(320307692307692307841, 2490, 10917, 403196809217289663458043223580906563641609617294); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(15059177663891191985498469564581, 21691241494814563657, 5959198137984416944871985040941211962546971878394061014854717427126670802); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(1, 115792089237316195423570985008687907853269984665640564039457584007913129639932, 2, 306748590411024027068452057, 3); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(0, 3, 3, 44869774749435413944328478986895177316804030, 2); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(115792089237316195423570985008687907853269984665640564039457584007913129639933, 667409171832157313382210046675580725011953, 170966693897056629150807196294457349572402758607401923355019500107511084513); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(115792089237316195423570985008687907853269984665640564039457584007913129639932, 19549319890719740959827156450505379259184673736260904583824030491, 16629388526339); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(1, 57, 2126726397172127776919, 3); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(10662442004167, 0, 5497097760623451146595, 3162190482019759261701358441242229); + _bucketBankruptcyerc20poolrewardsHandler.stake(1, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 4633); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(195082403288206510116943243208164172979846145506483861331524728636984, 5999490491512003998567204139527071137962581199636349206, 1); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(193, 115638053, 82905768405815550325167864157103591796198207319836507298376269364238808467864); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.stake(115792089237316195423570985008687907853269984665640564039457584007913129639933, 728230189013838280072632353261014942101509879986, 1074852977686923754516502207503688995019457654331626079784, 8647989100256796072321456855285912878676340053147534437521304860653); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(3941357502157973923804, 2, 806977082765068646659096738618743289712629038, 95470398010431964952450128551272930452522452449699886025877059807238, 1); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(36183411359542968180819498843191329944675962195184522815400173109497640044908, 5526, 3966754565367876855970249316229461606728002012105551523079085776320493, 12000000000000000000786344314428468140209160332, 1514); + _bucketBankruptcyerc20poolrewardsHandler.stake(115792089237316195423570985008687907853269984665640564039457584007913129639935, 19347515940517406236500101946818541192254229344198927883872669126, 0, 115792089237316195423570985008687907853269984665640564039457584007913129639934); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(1236588951273351231845418839930179263983011495754, 38238240862444672488745854665, 105710195453976313965439090442863258002796095759252242871256962165021905861650, 447301751254033913445893214690834296930546521452); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(46514948025651225960345695072605648432715982671974779016300427285754698287368, 3286, 3218715805466846511984533600393324923883748231); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(3950340310148269005, 5673061940259815795875572950552217903, 0); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(201, 16652, 456263400021039761424850168808020383038614345114, 185177884615384615469); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(844186718371423468438148597031199325852724093549, 8971, 1238939858024599757491003772585973626666495470478); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(14560967560043099906703147047009467303604341499091340414611613631940255690293, 1721, 1330742788975674320956191865797062835971931496250, 8012); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(610999999999999999999, 18990, 2964); + _bucketBankruptcyerc20poolrewardsHandler.stake(1, 2202462407395028941916385359630457052998061369773792102517381208520162, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 115792089237316195423570985008687907853269984665640564039457584007913129639933); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(259629493051510264, 23614305666380977416230669400318875317806232271123308657121989217833132243233, 2497, 27835018298679073652989722292632508325056543016077421626954570959368347669748, 1606); + _bucketBankruptcyerc20poolrewardsHandler.stake(115792089237316195423570985008687907853269984665640564039457584007913129639934, 4650754146616051773693243800451532316887707892427, 2674637045933147252314476540226577815868397623, 1637859); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(32610811746778589434426055746005034344393175264036753585460265204263347653842, 16005, 105710195453976313965439090442863258002796095759252242871256962165021905861709); + _bucketBankruptcyerc20poolrewardsHandler.stake(27241022853949367504447088193, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 128000899661578863761148718566665636525956915466064429, 1336719368342255666688); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(41124169807925345164795, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 1313063028941469943130200174691186594877948408346228981); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(2166715437819344420775617703353734409787244706488647403995037751254234644362, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 7532212); + _bucketBankruptcyerc20poolrewardsHandler.stake(14552177917818508405730171864883921324, 0, 115792089237316195423570985008687907853269984665640564039457584007913129639934, 84190559757713757784279975706433133519542327009581632460886117089373); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(37747710333430245980940452738832839721522435977096927851794211126014890045043, 105710195453976313965439090442863258002796095759252242871256962165021905861568, 4881, 3966754565367876869122194268884518216957992861677661334548387666061342); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(159533269946056829911817908703969087399676830547153393250667762079770747, 120375821746749532031, 553664897755275959629); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(2318, 371788003, 105710195453976313965439090442863258002796095759252242871256962165021905861824, 57957110594642022010328291066590663082489422500, 378363461538461538635); + _bucketBankruptcyerc20poolrewardsHandler.stake(1, 3108493389566117837926341948558162909763275523381432406469124236768340906924, 32229393624772079505360513009288184415901939, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(2836923789, 82757687462225415771947516030365134680378685014411112583900985134363263813950, 17992734256423583958967370161492784553176489409); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(1, 2, 1599018514952142375998297880); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(55687575924400638, 727999999999999999999, 15644); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(1, 2673041966562049323144905243406346442490148198615, 1285995676085316511341291864375645429377044076357986037173062379358204); + _bucketBankruptcyerc20poolrewardsHandler.stake(27836410677470140405893559165022839553284246026566794216457, 26100442293941930306313869947915225019447736484493936778052910988, 1100121169003966414850619669523011925033070895519974812092, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(751722115384615384963, 87573722621992251438460370142942144054516549109457068516979097052450755011736, 3966754565367876854520184869943068556144348793969914759895680118784807, 27984893582647316189577999054762964794852908603917399358854612125647292485578); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(15048, 20980142891430666358441099170678931589412918730, 26229794335232538522551515320652626439652093573752750988891734989405951307592); + _bucketBankruptcyerc20poolrewardsHandler.stake(115792089237316195423570985008687907853269984665640564039457584007913129639932, 1623645501211, 581895706741971570416382, 115792089237316195423570985008687907853269984665640564039457584007913129639933); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(16294, 37775847772112785254257, 20408); + _bucketBankruptcyerc20poolrewardsHandler.stake(233076476716696715, 19720626000000000000021835, 14786, 880); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(91, 48915418688551403693013933582174377748045,1, 0); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(8520254760456735866522434792660074894149362458110124278618188561008801076487, 4508341423132101367979353817313302855733981519104609141429822885854284517273, 1045732366170946687500335725634396288218029048535); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(5250764587436405674967118092556206155749365731, 141015099610895938496827107324000508240276523703380995216176939659, 0); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.stake(75715332515, 20249, 139492422255, 105710195453976313965439090442863258002796095759252242871256962165021905861575); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(5433, 21391, 754284941459726849420512743397530252182784738229, 23905); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(192677, 4773, 2683, 940037522744286018063446172177794105409762773472); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(1423000347840435497235966844164533984931800601575, 288276923076923077057, 17572, 4256931000379123634785033661970275022184774617022768398310874942392452426, 139403335757771137); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(2, 2587348281013517652545024121589073614070441106624530521348844741, 519685398); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(84919864282925853877573619845135091960602695946894030665170367426270992811938, 15050648105662257143935681434472465116789984907642743379717753234643085664126, 22213, 16413, 175589814974774645221481909980815519088940506341); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(3966754565367876881842889880294569887040448346346191805828869027190062, 4571, 5227); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(907000000000000000000, 2868991328, 99389371209329274803747059355072193342651880195070161537527945916651123372097); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(2784308567599248162087449504, 3589, 476777860815159664263285898208782485328810582592); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(0, 93446225603511499598845951183108384660272702, 2024254557338330727781790737102999642155730612363585, 191889378792020151); + _bucketBankruptcyerc20poolrewardsHandler.stake(36183411359542968180819498843191329944675962195184522815400173109497640044984, 50146794086275195190991942805708459010074680271220970599602693206755183387706, 2065, 32789382558206698454860319624949663673430750389618486004860947532855016388844); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(3, 29811238, 69968346427577179605244273168972327088469976079256197056454, 1497742154395667232899123570108019263133908353144179120765); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(3, 0, 87185381081925833627461609395751279524164897425148697297070669197775260); + _bucketBankruptcyerc20poolrewardsHandler.moveQuoteTokenToLowerBucket(17279999, 3966754565367876867473138000603430830185306546546874883932992520117722, 776481524764705302352605934280580955971144914555, 962787287); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(19060901126391672628476228072540859898, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 1); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(26920601521589162671147619654088067061266745140905760588388649977853848299620, 1875, 27835018298679073652989722292632508325056543016077421626954570959368347669985); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(553591494574561111154252750468593088203, 26003311767849788325482998126201562168467079599, 3503171015763161693096394522251351236934013944546); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(36822330623891827054618617680243779734013976879104614005453233537599913890987, 2030, 351827466436279533, 36183411359542968180819498843191329944675962195184522815400173109497640045092, 431); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(4307769405459937793464500814388987723043870007160919438680139924065536869, 20774, 20905556733966496908705142171609168952816592958194260630754626678628699156025, 112677305303603608793464000990919617579761525091244043308691041092632466067909, 3966754565367876866027363177544639294642486780494516334079839883146086); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(5612107944, 2, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 3, 3758652); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(3, 13063704682547015731607989179567642095598985357156794100666758119236, 1663082272433979660889799306293339760568971320019141218266316592279716982939); + _bucketBankruptcyerc20poolrewardsHandler.failed(); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(698213858938870538487, 14890451379766624461267359941375, 48557935465010072094981800005966219309615168007618540929696328537074564550805); + _bucketBankruptcyerc20poolrewardsHandler.moveStakedLiquidity(0, 0, 1, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _bucketBankruptcyerc20poolrewardsHandler.lenderKickAuction(355000000000000000000, 49046620449355538574108822723048473721226797556007972061207479861126558122006, 13060); + _bucketBankruptcyerc20poolrewardsHandler.takeOrSettleAuction(115792089237316195423570985008687907853269984665640564039457584007913129639932, 0, 1); + } } diff --git a/tests/forge/regression/PositionAndRewards/RegressionTestERC721PoolRewardsManager.t.sol b/tests/forge/regression/PositionAndRewards/RegressionTestERC721PoolRewardsManager.t.sol index 6274ecf03..23b988fbd 100644 --- a/tests/forge/regression/PositionAndRewards/RegressionTestERC721PoolRewardsManager.t.sol +++ b/tests/forge/regression/PositionAndRewards/RegressionTestERC721PoolRewardsManager.t.sol @@ -21,6 +21,7 @@ contract RegressionTestERC721PoolRewardsManager is ERC721PoolRewardsInvariants { _erc721poolrewardsHandler.kickAuction(18170, 652, 11342, 1168); _erc721poolrewardsHandler.pullCollateral(20130, 1209987167530552461153974115173428229758989546163, 150941); _erc721poolrewardsHandler.moveLiquidity(63198806135952229891699111929727509482991997027848329114178785250303971081388, 77371051183995213971267347974759461809434770063921461351617080426027329266071, 4805, 2289); + _erc721poolrewardsHandler.moveLiquidity(63198806135952229891699111929727509482991997027848329114178785250303971081388, 77371051183995213971267347974759461809434770063921461351617080426027329266071, 4805, 2289); _erc721poolrewardsHandler.moveQuoteToken(276169773153138481519606288636310061814657663456104947149, 1, 0, 108537837119796081908394324659000725292282331478997011952318493996290, 155532253556112179854090944828383440910501711771906801208685755840667262568); _erc721poolrewardsHandler.mergeCollateral(173, 22406963037383631220938302497939718111833223267188040374368716127276); _erc721poolrewardsHandler.burn(1328065707762407283002828802143541176473931677425004844, 1, 1, 37613208758526068006052551033711685); @@ -28,4 +29,49 @@ contract RegressionTestERC721PoolRewardsManager is ERC721PoolRewardsInvariants { _erc721poolrewardsHandler.takeAuction(148878580729371224992950595085688885987, 52018, 3863548495672151022795311051855, 1224829895266858456828928840866630331525272263026827096173292323394330361); _erc721poolrewardsHandler.claimRewards(339802229099465406190265268924204103831957337149846935, 1, 2641, 1084164255431, 3); } + + // issue in _preDrawDebt when borrower is in auction and tried to repayDebt and pull collateral, and check all debt is repaid. + // fix: return _preDrawDebt when borrower is in auction. + function test_regression_RW1_RW2() external { + _erc721poolrewardsHandler.stampLoan(3097, 99133); + _erc721poolrewardsHandler.kickAuction(31354931781638678607228669297131712859126084785867252355217498662940140921971, 1058, 11754, 12849); + _erc721poolrewardsHandler.takeReserves(115792089237316195423570985008687907853269984665640564039457584007913129639934, 33731052920955697617409005891040394080922214120333458396693390120882665651,1720188968454217720935353179268130063921306460048647700482); + _erc721poolrewardsHandler.pledgeCollateral(1757924641683012822782278927906643733124399771812893540782608051864, 146672722799504441441256193696, 115792089237316195423570985008687907853269984665640564039457584007913129639935); + _erc721poolrewardsHandler.mint(12138, 7557); + _erc721poolrewardsHandler.addQuoteToken(13384168457563664686794224199997478429074004894884217417626102307452469562, 399627080535825658763553985697630307858997509589356607284924675010621,15021260382761, 2149748001246586660242584607929003545953); + _erc721poolrewardsHandler.mint(115792089237316195423570985008687907853269984665640564039457584007913129639932, 115792089237316195423570985008687907853269984665640564039457584007913129639934); + _erc721poolrewardsHandler.settleAuction(1735287903719074628042764789671363295, 3, 23993967057076184216275526949268, 4106476); + _erc721poolrewardsHandler.drawDebt(77622297016072599381603815616169164633892036937355547901, 10261965, 115792089237316195423570985008687907853269984665640564039457584007913129639935); + _erc721poolrewardsHandler.stampLoan(115792089237316195423570985008687907853269984665640564039457584007913129639934, 15628038388); + _erc721poolrewardsHandler.redeemPositions(22801150734449629332972378409816953484259939113298558, 563212509531357473751756674, 236487328781308137707, 114005983); + _erc721poolrewardsHandler.unstake(115792089237316195423570985008687907853269984665640564039457584007913129639932, 209638772009545859528, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 1852809668170365878555741120106, 8537278537524035545583862060040379261058217549); + _erc721poolrewardsHandler.emergencyUnstake(5762, 4833, 23085, 23329, 10160); + _erc721poolrewardsHandler.lenderKickAuction(38567162678744729883825485304193880641, 1436018647533119237198979383384378157898748977466826312550, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _erc721poolrewardsHandler.mergeCollateral(115792089237316195423570985008687907853269984665640564039457584007913129639935, 40700253390048296022217103829550); + _erc721poolrewardsHandler.stake(115792089237316195423570985008687907853269984665640564039457584007913129639935, 13666289603396405051, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 105); + _erc721poolrewardsHandler.takeAuction(115792089237316195423570985008687907853269984665640564039457584007913129639935, 115792089237316195423570985008687907853269984665640564039457584007913129639932, 1, 28190); + _erc721poolrewardsHandler.kickReserveAuction(1886, 65412); + _erc721poolrewardsHandler.takeReserves(7740, 4448, 3713); + _erc721poolrewardsHandler.pullCollateral(115792089237316195423570985008687907853269984665640564039457584007913129639933, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 1); + _erc721poolrewardsHandler.repayDebt(110349606679412691172957834289542550319383271247755660854362242977991410020198, 6715, 4023); + _erc721poolrewardsHandler.mergeCollateral(0, 59747238056737534481206780725787707244999); + _erc721poolrewardsHandler.emergencyUnstake(0, 115792089237316195423570985008687907853269984665640564039457584007913129639932, 51729897709415, 23006395802429129288475054106, 1); + _erc721poolrewardsHandler.removeCollateral(115792089237316195423570985008687907853269984665640564039457584007913129639934, 1, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _erc721poolrewardsHandler.bucketTake(17736, 12855, false, 3289, 1123); + _erc721poolrewardsHandler.pledgeCollateral(115792089237316195423570985008687907853269984665640564039457584007913129639932, 115792089237316195423570985008687907853269984665640564039457584007913129639933, 1); + _erc721poolrewardsHandler.kickAuction(115792089237316195423570985008687907853269984665640564039457584007913129639935, 115792089237316195423570985008687907853269984665640564039457584007913129639935, 1347071909069112433439054986249189622, 115792089237316195423570985008687907853269984665640564039457584007913129639933); + _erc721poolrewardsHandler.lenderKickAuction(3, 1, 37246476355849); + _erc721poolrewardsHandler.failed(); + _erc721poolrewardsHandler.burn(143, 1108823922,48884, 5811); + _erc721poolrewardsHandler.memorializePositions(7222, 6164, 14919869490272923636577259832825010352693700464430964509126832818182799243080, 26284); + _erc721poolrewardsHandler.takeAuction(1110452889, 6058, 3016184996, 12922961544511690602711642372921216522520321844072048399134131509470247863750); + _erc721poolrewardsHandler.mergeCollateral(5967, 3326); + _erc721poolrewardsHandler.bucketTake(1, 1714375381109265815411514882158434660321706149315054174553444757, true, 2, 2); + _erc721poolrewardsHandler.unstake(3, 28372160064709526166669973508287087795611038423150717571367, 54636530394327258458081903942670329383, 3, 115792089237316195423570985008687907853269984665640564039457584007913129639932); + _erc721poolrewardsHandler.updateExchangeRate(36456, 17137, 1560275421, 17005); + _erc721poolrewardsHandler.stampLoan(3352512690189013572483301109122336596527121909930416357921778362671464454374, 5992531996617362563537972); + _erc721poolrewardsHandler.pledgeCollateral(174922928606654802364580162287611825, 4, 56551201532130900086); + _erc721poolrewardsHandler.emergencyUnstake(2247288760962719055600016280767970105290, 0, 2, 11596164422216101546875614140375574915418729056483, 61337865928763100451538345828); + _erc721poolrewardsHandler.emergencyUnstake(1023240505530161435702165, 18496758270674070880, 45978599603359075781444831263900707496437331655382222738127705004512629605795, 110349606679412691172957834289542550319383271247755660854362242977991410020756, 4078); + } } diff --git a/tests/forge/unit/Auctions.t.sol b/tests/forge/unit/Auctions.t.sol index 9ef451527..68e51296e 100644 --- a/tests/forge/unit/Auctions.t.sol +++ b/tests/forge/unit/Auctions.t.sol @@ -29,28 +29,44 @@ contract AuctionsTest is DSTestPlus { function testAuctionPrice() external { skip(6238); - uint256 momp = 8_678.5 * 1e18; - uint256 neutralPrice = 8_600.0 * 1e18; - uint256 kickTime = block.timestamp; + uint256 referencePrice = 8_678.5 * 1e18; + uint256 kickTime = block.timestamp; - assertEq(_auctionPrice(momp, neutralPrice, kickTime), 277_712 * 1e18); - skip(1444); // price should not change in the first hour - assertEq(_auctionPrice(momp, neutralPrice, kickTime), 277_712 * 1e18); - - skip(5756); // 2 hours - assertEq(_auctionPrice(momp, neutralPrice, kickTime), 138_856 * 1e18); - skip(2394); // 2 hours, 39 minutes, 54 seconds - assertEq(_auctionPrice(momp, neutralPrice, kickTime), 87_574.910740335995562528 * 1e18); - skip(2586); // 3 hours, 23 minutes - assertEq(_auctionPrice(momp, neutralPrice, kickTime), 53_227.960156860514117568 * 1e18); - skip(3); // 3 seconds later - assertEq(_auctionPrice(momp, neutralPrice, kickTime), 53_197.223359425583052544 * 1e18); - skip(20153); // 8 hours, 35 minutes, 53 seconds - assertEq(_auctionPrice(momp, neutralPrice, kickTime), 1_098.26293050754894624 * 1e18); - skip(97264); // 36 hours - assertEq(_auctionPrice(momp, neutralPrice, kickTime), 0.00000808248283696 * 1e18); - skip(129600); // 72 hours - assertEq(_auctionPrice(momp, neutralPrice, kickTime), 0); + assertEq(_auctionPrice(referencePrice, kickTime), 2_221_696 * 1e18); + skip(44 minutes); // 44 minutes + assertEq(_auctionPrice(referencePrice, kickTime), 483_524.676068186452113664 * 1e18); + skip(16 minutes); // 1 hour + assertEq(_auctionPrice(referencePrice, kickTime), 277_712 * 1e18); + skip(99 minutes); // 2 hours, 39 minutes + assertEq(_auctionPrice(referencePrice, kickTime), 27_712.130183984744559172 * 1e18); + skip(3); // 3 seconds later + assertEq(_auctionPrice(referencePrice, kickTime), 27_704.127762591858494776 * 1e18); + skip(57 + 80 minutes); // 4 hours + assertEq(_auctionPrice(referencePrice, kickTime), 17_357 * 1e18); + skip(1 hours); // 5 hours + assertEq(_auctionPrice(referencePrice, kickTime), 12_273.252401054905374068 * 1e18); + skip(1 hours); // 6 hours + assertEq(_auctionPrice(referencePrice, kickTime), 8_678.5 * 1e18); + skip(2 hours); // 8 hours + assertEq(_auctionPrice(referencePrice, kickTime), 4_339.25 * 1e18); + skip(2 hours); // 10 hours + assertEq(_auctionPrice(referencePrice, kickTime), 2_169.625 * 1e18); + skip(1 hours); // 11 hours + assertEq(_auctionPrice(referencePrice, kickTime), 1_534.15655013186316308 * 1e18); + skip(1 hours); // 12 hours + assertEq(_auctionPrice(referencePrice, kickTime), 1084.8125 * 1e18); + skip(1 hours); // 13 hours + assertEq(_auctionPrice(referencePrice, kickTime), 767.07827506593158154 * 1e18); + skip(2 hours); // 15 hours + assertEq(_auctionPrice(referencePrice, kickTime), 271.203125 * 1e18); + skip(3 hours); // 18 hours + assertEq(_auctionPrice(referencePrice, kickTime), 33.900390625 * 1e18); + skip(6 hours); // 24 hours + assertEq(_auctionPrice(referencePrice, kickTime), 0.529693603515625 * 1e18); + skip(12 hours); // 36 hours + assertEq(_auctionPrice(referencePrice, kickTime), 0.000129319727420501 * 1e18); + skip(36 hours); // 72 hours + assertEq(_auctionPrice(referencePrice, kickTime), 0.000000000000001627 * 1e18); } /** diff --git a/tests/forge/unit/ERC20Pool/ERC20DSTestPlus.sol b/tests/forge/unit/ERC20Pool/ERC20DSTestPlus.sol index 076816f82..26da8704a 100644 --- a/tests/forge/unit/ERC20Pool/ERC20DSTestPlus.sol +++ b/tests/forge/unit/ERC20Pool/ERC20DSTestPlus.sol @@ -34,6 +34,7 @@ abstract contract ERC20DSTestPlus is DSTestPlus, IERC20PoolEvents { address borrower ) internal { changePrank(borrower); + uint256 borrowerT0debt; uint256 borrowerCollateral; (borrowerT0debt, borrowerCollateral, ) = _pool.borrowerInfo(borrower); @@ -120,6 +121,32 @@ abstract contract ERC20DSTestPlus is DSTestPlus, IERC20PoolEvents { assertEq(collateralBalanceNormalized, bucketCollateral + pledgedCollateral); } + function redeemBankruptBucketCollateral( + EnumerableSet.UintSet storage buckets, + address lender + ) internal { + // skip some time to pass bucket bankruptcy block + skip(1 hours); + + for (uint256 i = 0; i < buckets.length(); i++) { + uint256 bucketIndex = buckets.at(i); + (, uint256 quoteTokens, uint256 collateral, uint256 bucketLps, ,) = _poolUtils.bucketInfo(address(_pool), bucketIndex); + if (bucketLps == 0 && quoteTokens == 0 && collateral != 0) { + changePrank(lender); + + // mint and approve collateral tokens + deal(_pool.collateralAddress(), lender, 1 * 1e18); + IERC20(_pool.collateralAddress()).approve(address(_pool), type(uint256).max); + + // add collateral to get some lps. + ERC20Pool(address(_pool)).addCollateral(1 * 1e18, bucketIndex, block.timestamp + 10 minutes); + + // remove all collateral + ERC20Pool(address(_pool)).removeCollateral(type(uint256).max, bucketIndex); + } + } + } + function validateEmpty( EnumerableSet.UintSet storage buckets ) internal { @@ -133,8 +160,9 @@ abstract contract ERC20DSTestPlus is DSTestPlus, IERC20PoolEvents { assertEq(collateral, 0); } ( , uint256 loansCount, , , ) = _poolUtils.poolLoansInfo(address(_pool)); - (uint256 debt, , ,) = _pool.debtInfo(); + (uint256 debt, , uint256 t0DebtInAuction ,) = _pool.debtInfo(); assertEq(debt, 0); + assertEq(t0DebtInAuction, 0); assertEq(loansCount, 0); assertEq(_pool.pledgedCollateral(), 0); } @@ -143,14 +171,34 @@ abstract contract ERC20DSTestPlus is DSTestPlus, IERC20PoolEvents { _; validateCollateral(bucketsUsed, borrowers); + // Skip time to make all auctioned borrowers settleable + skip(73 hours); + + // Settle any auctions and then repay debt for (uint i = 0; i < borrowers.length(); i++) { - repayDebt(borrowers.at(i)); + address borrower = borrowers.at(i); + (,,, uint256 kickTime,,,,,) = _pool.auctionInfo(borrower); + if (kickTime != 0) { + changePrank(borrower); + _pool.settle(borrower, bucketsUsed.length() + 1); + + // Settle again if not settled, this can happen when less reserves calculated with DEPOSIT_BUFFER and borrower is not fully settled + (,,, kickTime,,,,,) = _pool.auctionInfo(borrower); + if (kickTime != 0) { + _pool.settle(borrower, bucketsUsed.length() + 1); + } + } + repayDebt(borrower); } + // Lenders pull all liquidity and collateral from buckets for (uint i = 0; i < lenders.length(); i++) { redeemLendersLp(lenders.at(i), lendersDepositedIndex[lenders.at(i)]); } + // Redeem all collateral in bankrupt buckets + if (lenders.length() != 0) redeemBankruptBucketCollateral(bucketsUsed, lenders.at(0)); + validateEmpty(bucketsUsed); } @@ -581,6 +629,15 @@ abstract contract ERC20DSTestPlus is DSTestPlus, IERC20PoolEvents { ERC20Pool(address(_pool)).repayDebt(borrower, 0, amount, borrower, MAX_FENWICK_INDEX); } + function _assertRepayAuctionActiveRevert( + address from, + uint256 maxAmount + ) internal override { + changePrank(from); + vm.expectRevert(IPoolErrors.AuctionActive.selector); + ERC20Pool(address(_pool)).repayDebt(from, maxAmount, 0, from, MAX_FENWICK_INDEX); + } + function _assertRepayMinDebtRevert( address from, address borrower, diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolBorrow.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolBorrow.t.sol index 285405e3e..817847215 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolBorrow.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolBorrow.t.sol @@ -354,7 +354,7 @@ contract ERC20PoolBorrowTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 50 * 1e18, - borrowert0Np: 441.424038461538461742 * 1e18, + borrowert0Np: 484.222578900118175410 * 1e18, borrowerCollateralization: 7.082081907682151400 * 1e18 }); @@ -389,7 +389,7 @@ contract ERC20PoolBorrowTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 60 * 1e18, - borrowert0Np: 441.424038461538461742 * 1e18, + borrowert0Np: 403.518815750098479508 * 1e18, borrowerCollateralization: 8.488027144729466085 * 1e18 }); _assertLenderInterest(liquidityAdded, 44.110379805202100000 * 1e18); @@ -427,7 +427,7 @@ contract ERC20PoolBorrowTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 50 * 1e18, - borrowert0Np: 441.213836538461538664 * 1e18, + borrowert0Np: 483.986975517230275430 * 1e18, borrowerCollateralization: 7.063769822178689107 * 1e18 }); _assertLenderInterest(liquidityAdded, 69.130567554535450000 * 1e18); @@ -462,7 +462,7 @@ contract ERC20PoolBorrowTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 50 * 1e18, - borrowert0Np: 443.294835576923077127 * 1e18, + borrowert0Np: 486.269617724627962428 * 1e18, borrowerCollateralization: 7.053240081812639175 * 1e18 }); _assertLenderInterest(liquidityAdded, 96.693504733499050000 * 1e18); @@ -494,7 +494,7 @@ contract ERC20PoolBorrowTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 50 * 1e18, - borrowert0Np: 443.294835576923077127 * 1e18, + borrowert0Np: 486.269617724627962428 * 1e18, borrowerCollateralization: 7.041675495797803839 * 1e18 }); _assertLenderInterest(liquidityAdded, 127.061165904636850000 * 1e18); @@ -520,12 +520,11 @@ contract ERC20PoolBorrowTest is ERC20HelperContract { interestRateUpdate: _startTime + 50 days }) ); - assertEq(_poolUtils.momp(address(_pool)), 2_981.007422784467321543 * 1e18); _assertBorrower({ borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 50 * 1e18, - borrowert0Np: 443.294835576923077127 * 1e18, + borrowert0Np: 486.269617724627962428 * 1e18, borrowerCollateralization: 7.028976350457301320 * 1e18 }); } @@ -933,7 +932,7 @@ contract ERC20PoolBorrowTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 500.480769230769231 * 1e18, borrowerCollateral: 50 * 1e18, - borrowert0Np: 10.510096153846153851 * 1e18, + borrowert0Np: 11.529109021431385128 * 1e18, borrowerCollateralization: 300.799971477982403259 * 1e18 }); diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolCollateral.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolCollateral.t.sol index ce5ca5a32..45139395f 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolCollateral.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolCollateral.t.sol @@ -107,7 +107,7 @@ contract ERC20PoolCollateralTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 21_020.192307692307702000 * 1e18, borrowerCollateral: 100 * 1e18, - borrowert0Np: 220.712019230769230871 * 1e18, + borrowert0Np: 242.111289450059087705 * 1e18, borrowerCollateralization: 14.181637252165253251 * 1e18 }); @@ -146,7 +146,7 @@ contract ERC20PoolCollateralTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 21_049.006823139002918431 * 1e18, borrowerCollateral: 50 * 1e18, - borrowert0Np: 441.424038461538461742 * 1e18, + borrowert0Np: 484.222578900118175410 * 1e18, borrowerCollateralization: 7.081111825921092812 * 1e18 }); @@ -182,7 +182,7 @@ contract ERC20PoolCollateralTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 21_049.006823139002918431 * 1e18, borrowerCollateral: 7.061038044473493202 * 1e18, - borrowert0Np: 3_140.657612229160876676 * 1e18, + borrowert0Np: 3_445.079304012847629269 * 1e18, borrowerCollateralization: 1 * 1e18 }); @@ -250,7 +250,7 @@ contract ERC20PoolCollateralTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 21_020.192307692307702000 * 1e18, borrowerCollateral: 100 * 1e18, - borrowert0Np: 220.712019230769230871 * 1e18, + borrowert0Np: 242.111289450059087705 * 1e18, borrowerCollateralization: 14.181637252165253251 * 1e18 }); @@ -275,7 +275,7 @@ contract ERC20PoolCollateralTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 21_049.006823139002918431 * 1e18, borrowerCollateral: 50 * 1e18, - borrowert0Np: 441.424038461538461742 * 1e18, + borrowert0Np: 484.222578900118175410 * 1e18, borrowerCollateralization: 7.081111825921092812 * 1e18 }); @@ -297,7 +297,7 @@ contract ERC20PoolCollateralTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 21_049.006823139002918431 * 1e18, borrowerCollateral: 7.061038044473493202 * 1e18, - borrowert0Np: 3_140.657612229160876676 * 1e18, + borrowert0Np: 3_445.079304012847629269 * 1e18, borrowerCollateralization: 1 * 1e18 }); diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolInfoUtils.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolInfoUtils.t.sol index fac958abe..915805a0f 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolInfoUtils.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolInfoUtils.t.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.18; +import { Strings } from '@openzeppelin/contracts/utils/Strings.sol'; + import { ERC20HelperContract } from './ERC20DSTestPlus.sol'; import { Token } from '../../utils/Tokens.sol'; @@ -8,6 +10,7 @@ import 'src/libraries/helpers/PoolHelper.sol'; import 'src/interfaces/pool/erc20/IERC20Pool.sol'; import 'src/ERC20Pool.sol'; +import 'src/PoolInfoUtilsMulticall.sol'; contract ERC20PoolInfoUtilsTest is ERC20HelperContract { @@ -92,10 +95,10 @@ contract ERC20PoolInfoUtilsTest is ERC20HelperContract { } function testPoolInfoUtilsBorrowerInfo() external { - (uint256 debt, uint256 collateral, uint256 t0Np) = _poolUtils.borrowerInfo(address(_pool), _borrower); + (uint256 debt, uint256 collateral, uint256 npTpRatio) = _poolUtils.borrowerInfo(address(_pool), _borrower); assertEq(debt, 21_020.192307692307702000 * 1e18); assertEq(collateral, 100 * 1e18); - assertEq(t0Np, 220.712019230769230871 * 1e18); + assertEq(npTpRatio, 242.111289450059087705 * 1e18); } function testPoolInfoUtilsBucketInfo() external { @@ -205,22 +208,6 @@ contract ERC20PoolInfoUtilsTest is ERC20HelperContract { assertEq(lenderInterestMargin, 0.849999999999999999 * 1e18); } - function testMomp() external { - assertEq(_poolUtils.momp(address(_pool)), 2_981.007422784467321543 * 1e18); - - // ensure calculation does not revert on pools with no loans and no deposit - IERC20 otherCollateral = new Token("MompTestCollateral", "MTC"); - IERC20Pool emptyPool = ERC20Pool(_poolFactory.deployPool(address(otherCollateral), address(_quote), 0.05 * 10**18)); - assertEq(_poolUtils.momp(address(emptyPool)), MIN_PRICE); - - // should return HPB on pools with liquidity but no loans - changePrank(_lender); - uint256 hpbIndex = 369; - _quote.approve(address(emptyPool), type(uint256).max); - emptyPool.addQuoteToken(0.0213 * 1e18, hpbIndex, type(uint256).max, false); - assertEq(_poolUtils.momp(address(emptyPool)), _priceAt(hpbIndex)); - } - function testBorrowFeeRate() external { assertEq(_poolUtils.borrowFeeRate(address(_pool)), 0.000961538461538462 * 1e18); } @@ -277,4 +264,51 @@ contract ERC20PoolInfoUtilsTest is ERC20HelperContract { ), 20000000000000000000 ); } + + function testPoolInfoUtilsMulticallPoolAndBucketInfo() external { + PoolInfoUtilsMulticall poolUtilsMulticall = new PoolInfoUtilsMulticall(_poolUtils); + + PoolInfoUtilsMulticall.BucketInfo memory bucketInfo; + + (,,, bucketInfo) = poolUtilsMulticall.poolDetailsAndBucketInfo(address(_pool), high); + + assertEq(bucketInfo.bucketLP, 10_000 * 1e18); + } + + function testPoolInfoUtilsMulticall() external { + PoolInfoUtilsMulticall poolUtilsMulticall = new PoolInfoUtilsMulticall(_poolUtils); + + string[] memory functionSignatures = new string[](2); + functionSignatures[0] = "hpb(address)"; + functionSignatures[1] = "htp(address)"; + + string[] memory args = new string[](2); + args[0] = Strings.toHexString(address(_pool)); + args[1] = Strings.toHexString(address(_pool)); + + bytes[] memory result = poolUtilsMulticall.multicall(functionSignatures, args); + + assertEq(abi.decode(result[0], (uint256)), _poolUtils.hpb(address(_pool))); + assertEq(abi.decode(result[1], (uint256)), _poolUtils.htp(address(_pool))); + } + + function testPoolInfoMulticallBorrowerInfo() external { + PoolInfoUtilsMulticall poolUtilsMulticall = new PoolInfoUtilsMulticall(_poolUtils); + + string[] memory functionSignatures = new string[](2); + functionSignatures[0] = "borrowerInfo(address,address)"; + functionSignatures[1] = "htp(address)"; + + string[] memory args = new string[](3); + args[0] = Strings.toHexString(address(_pool)); + args[1] = Strings.toHexString(_borrower); + args[2] = Strings.toHexString(address(_pool)); + + bytes[] memory result = poolUtilsMulticall.multicall(functionSignatures, args); + + (uint256 debt,,) = abi.decode(result[0], (uint256, uint256, uint256)); + + assertEq(debt, 21_020.192307692307702000 * 1e18); + assertEq(abi.decode(result[1], (uint256)), _poolUtils.htp(address(_pool))); + } } diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolInterestRateAndEMAs.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolInterestRateAndEMAs.t.sol index 7905128c3..3971cd081 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolInterestRateAndEMAs.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolInterestRateAndEMAs.t.sol @@ -672,6 +672,7 @@ contract ERC20PoolInterestRateTestAndEMAs is ERC20HelperContract { depositEma: 19_999.990463256835940000 * 1e18 }); } + function testPoolLargeCollateralPostedTargetUtilization() external tearDown { // add initial quote to the pool @@ -1107,4 +1108,293 @@ contract ERC20PoolInterestRateTestAndEMAs is ERC20HelperContract { exchangeRate: 1.008406484270040092 * 1e18 }); } + + function testAccruePoolInterestRevertDueToExpLimit() external { + _mintQuoteAndApproveTokens(_lender, 1_000_000_000 * 1e18); + _mintCollateralAndApproveTokens(_borrower, 1_000_000_000 * 1e18); + + _addInitialLiquidity({ + from: _lender, + amount: 1_000_000_000 * 1e18, // 1 billion + index: _i1505_26 + }); + + // draw 80% of liquidity as debt + _drawDebt({ + from: _borrower, + borrower: _borrower, + amountToBorrow: 800_000_000 * 1e18, + limitIndex: _i1505_26, + collateralToPledge: 1_000_000_000 * 1e18, + newLup: _p1505_26 + }); + + _assertPool( + PoolParams({ + htp: 0.80076923076923077 * 1e18, + lup: _p1505_26, + poolSize: 1_000_000_000 * 1e18, + pledgedCollateral: 1_000_000_000 * 1e18, + encumberedCollateral: 531_979.357254329691641573 * 1e18, + poolDebt: 800_769_230.7692307696 * 1e18, + actualUtilization: 0, + targetUtilization: 1e18, + minDebtAmount: 80_076_923.07692307696 * 1e18, + loans: 1, + maxBorrower: _borrower, + interestRate: 0.05 * 1e18, + interestRateUpdate: _startTime + }) + ); + + // Update interest after 12 hours + uint i = 0; + while (i < 93) { + // trigger an interest accumulation + skip(12 hours); + + _updateInterest(); + + unchecked { ++i; } + } + + // confirm we hit 400% max rate + _assertPool( + PoolParams({ + htp: 0.897414066911426240 * 1e18, + lup: _p1505_26, + poolSize: 1_088_327_685.946146186000000000 * 1e18, + pledgedCollateral: 1_000_000_000 * 1e18, + encumberedCollateral: 596_183.944340533059305233 * 1e18, + poolDebt: 897_414_066.911426239994562461 * 1e18, + actualUtilization: 0.822492351372651041 * 1e18, + targetUtilization: 0.000573363809855153 * 1e18, + minDebtAmount: 89_741_406.691142623999456246 * 1e18, + loans: 1, + maxBorrower: _borrower, + interestRate: 4 * 1e18, + interestRateUpdate: _startTime + 1104 hours + }) + ); + + // wait 32 years + skip(365 days * 32); + + // Reverts with PRBMathUD60x18__ExpInputTooBig + vm.expectRevert(); + _updateInterest(); + } + + function testAccrueInterestNewInterestLimit() external { + _mintQuoteAndApproveTokens(_lender, 1_000_000_000 * 1e18); + _mintCollateralAndApproveTokens(_borrower, 1_000_000_000 * 1e18); + + _addInitialLiquidity({ + from: _lender, + amount: 1_000_000_000 * 1e18, // 1 billion + index: _i1505_26 + }); + + // draw 80% of liquidity as debt + _drawDebt({ + from: _borrower, + borrower: _borrower, + amountToBorrow: 800_000_000 * 1e18, + limitIndex: _i1505_26, + collateralToPledge: 1_000_000_000 * 1e18, + newLup: _p1505_26 + }); + + _assertPool( + PoolParams({ + htp: 0.80076923076923077 * 1e18, + lup: _p1505_26, + poolSize: 1_000_000_000 * 1e18, + pledgedCollateral: 1_000_000_000 * 1e18, + encumberedCollateral: 531_979.357254329691641573 * 1e18, + poolDebt: 800_769_230.7692307696 * 1e18, + actualUtilization: 0, + targetUtilization: 1e18, + minDebtAmount: 80_076_923.07692307696 * 1e18, + loans: 1, + maxBorrower: _borrower, + interestRate: 0.05 * 1e18, + interestRateUpdate: _startTime + }) + ); + + // update interest rate after each 14 hours + uint i = 0; + while (i < 171) { + // trigger an interest accumulation + skip(14 hours); + + _updateInterest(); + + unchecked { ++i; } + } + + // Pledge some collateral to avoid tu overflow in `(((tu + mau102 - 1e18) / 1e9) ** 2)` + _mintCollateralAndApproveTokens(_borrower, 1_000_000_000 * 1e24); + IERC20Pool(address(_pool)).drawDebt(_borrower, 0, 0, 1_000_000_000 * 1e24); + + skip(14 hours); + + // Update interest rate after each 13 hours + while (i < 11087) { + // trigger an interest accumulation + skip(13 hours); + + _updateInterest(); + + unchecked { ++i; } + } + + skip(13 hours); + + // Revert with Arithmetic overflow in `Maths.wmul(pendingFactor - Maths.WAD, poolState_.debt)` in accrue interest + vm.expectRevert(); + _updateInterest(); + } + + function testUpdateInterestZeroThresholdPrice() external { + _mintQuoteAndApproveTokens(_lender, 1_000_000_000 * 1e18); + _mintCollateralAndApproveTokens(_borrower, 1_000_000_000 * 1e18); + + _addInitialLiquidity({ + from: _lender, + amount: 1_000_000_000 * 1e18, // 1 billion + index: _i1505_26 + }); + + // draw 80% of liquidity as debt + _drawDebt({ + from: _borrower, + borrower: _borrower, + amountToBorrow: 800_000_000 * 1e18, + limitIndex: _i1505_26, + collateralToPledge: 1_000_000_000 * 1e18, + newLup: _p1505_26 + }); + + _assertPool( + PoolParams({ + htp: 0.80076923076923077 * 1e18, + lup: _p1505_26, + poolSize: 1_000_000_000 * 1e18, + pledgedCollateral: 1_000_000_000 * 1e18, + encumberedCollateral: 531_979.357254329691641573 * 1e18, + poolDebt: 800_769_230.7692307696 * 1e18, + actualUtilization: 0, + targetUtilization: 1e18, + minDebtAmount: 80_076_923.07692307696 * 1e18, + loans: 1, + maxBorrower: _borrower, + interestRate: 0.05 * 1e18, + interestRateUpdate: _startTime + }) + ); + + // update interest rate after each day + uint i = 0; + while (i < 104) { + // trigger an interest accumulation + skip(1 days); + + // check borrower collateralization and pledge more collateral if undercollateralized + (uint256 debt, uint256 collateralPledged, ) = _poolUtils.borrowerInfo(address(_pool), _borrower); + uint256 requiredCollateral = _requiredCollateral(debt, _lupIndex()); + + if (requiredCollateral > collateralPledged ) { + uint256 collateralToPledge = requiredCollateral - collateralPledged; + _mintCollateralAndApproveTokens(_borrower, collateralToPledge); + + // Pledge collateral reverts with `ZeroThresholdPrice()` + if (i == 103) { + vm.expectRevert(); + } + + changePrank(_borrower); + IERC20Pool(address(_pool)).drawDebt(_borrower, 0, 0, collateralToPledge); + } else { + _updateInterest(); + } + + unchecked { ++i; } + } + } + + function testUpdateInterestTuLimit() external { + _mintQuoteAndApproveTokens(_lender, 1_000_000_000 * 1e18); + _mintCollateralAndApproveTokens(_borrower, 1_000_000_000 * 1e18); + + _addInitialLiquidity({ + from: _lender, + amount: 1_000_000_000 * 1e18, // 1 billion + index: _i1505_26 + }); + + // draw 80% of liquidity as debt + _drawDebt({ + from: _borrower, + borrower: _borrower, + amountToBorrow: 800_000_000 * 1e18, + limitIndex: _i1505_26, + collateralToPledge: 1_000_000_000 * 1e18, + newLup: _p1505_26 + }); + + _assertPool( + PoolParams({ + htp: 0.80076923076923077 * 1e18, + lup: _p1505_26, + poolSize: 1_000_000_000 * 1e18, + pledgedCollateral: 1_000_000_000 * 1e18, + encumberedCollateral: 531_979.357254329691641573 * 1e18, + poolDebt: 800_769_230.7692307696 * 1e18, + actualUtilization: 0, + targetUtilization: 1e18, + minDebtAmount: 80_076_923.07692307696 * 1e18, + loans: 1, + maxBorrower: _borrower, + interestRate: 0.05 * 1e18, + interestRateUpdate: _startTime + }) + ); + + // update interest rate after each day + uint i = 0; + while (i < 4865) { + // trigger an interest accumulation + skip(1 days); + + // stop pledging more collateral to avoid t0Tp becoming 0, i = 103 is the limit where t0tp becomes 0 + if (i < 100) { + // check borrower collateralization and pledge more collateral if undercollateralized to avoid `(((tu + mau102 - 1e18) / 1e9) ** 2)` overflow + (uint256 debt, uint256 collateralPledged, ) = _poolUtils.borrowerInfo(address(_pool), _borrower); + (uint256 poolDebt,,,) = _pool.debtInfo(); + uint256 lupIndex = _pool.depositIndex(poolDebt); + uint256 requiredCollateral = _requiredCollateral(debt, lupIndex); + + if (requiredCollateral > collateralPledged) { + uint256 collateralToPledge = requiredCollateral - collateralPledged; + _mintCollateralAndApproveTokens(_borrower, collateralToPledge); + + changePrank(_borrower); + IERC20Pool(address(_pool)).drawDebt(_borrower, 0, 0, collateralToPledge); + } + + } else { + _updateInterest(); + } + + unchecked { ++i; } + } + + skip(1 days); + + // Revert with Arithmetic overflow in `(((tu + mau102 - 1e18) / 1e9) ** 2)` in update interest + vm.expectRevert(); + _updateInterest(); + } } diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsArbTake.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsArbTake.t.sol index 9df8a42bb..f3ab8cbcd 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsArbTake.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsArbTake.t.sol @@ -107,14 +107,14 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.268509615384615394 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 1.009034539679184679 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 7_987.673076923076926760 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 8.471136974495192174 * 1e18, + borrowert0Np: 9.200228999102245332 * 1e18, borrowerCollateralization: 1.217037273735858713 * 1e18 }); @@ -146,7 +146,7 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -158,17 +158,17 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.534277977147272574 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 0.995306391810796636 * 1e18 }); _kick({ from: _lender, borrower: _borrower, - debt: 19.778456451861613481 * 1e18, + debt: 19.534277977147272573 * 1e18, collateral: 2 * 1e18, - bond: 0.195342779771472726 * 1e18, - transferAmount: 0.195342779771472726 * 1e18 + bond: 0.296536979149981005 * 1e18, + transferAmount: 0.296536979149981005 * 1e18 }); _assertAuction( @@ -176,26 +176,25 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.195342779771472726 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.296536979149981005 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 328.175870016074179200 * 1e18, - debtInAuction: 19.778456451861613481 * 1e18, - thresholdPrice: 9.889228225930806740 * 1e18, - neutralPrice: 10.255495938002318100 * 1e18 + referencePrice: 11.249823884323541351 * 1e18, + totalBondEscrowed: 0.296536979149981005 * 1e18, + auctionPrice: 2_879.954914386826585856 * 1e18, + debtInAuction: 19.534277977147272574 * 1e18, + thresholdPrice: 9.767138988573636287 * 1e18, + neutralPrice: 11.249823884323541351 * 1e18 }) ); _assertKicker({ kicker: _lender, claimable: 0, - locked: 0.195342779771472726 * 1e18 + locked: 0.296536979149981005 * 1e18 }); } function testArbTakeCollateralRestrict() external tearDown { - skip(6.5 hours); _assertLenderLpBalance({ @@ -219,10 +218,10 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { }); _assertBorrower({ borrower: _borrower, - borrowerDebt: 19.779116873676490457 * 1e18, + borrowerDebt: 19.534930245606410328 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 0.982985835729561629 * 1e18 + borrowert0Np: 11.096767433127708186 * 1e18, + borrowerCollateralization: 0.995273158676181149 * 1e18 }); // add liquidity to accrue interest and update reserves before arb take @@ -231,7 +230,7 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { amount: 1 * 1e18, amountAdded: 0.999876712328767123 * 1e18, index: _i9_52, - lpAward: 0.999873539529846321 * 1e18, + lpAward: 0.999873539625283938 * 1e18, newLup: 9.721295865031779605 * 1e18 }); @@ -239,39 +238,39 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { index: _i9_91, lpBalance: 2_000 * 1e18, collateral: 0, - deposit: 2_010.436713885571218000 * 1e18, - exchangeRate: 1.005218356942785609 * 1e18 + deposit: 2_010.436713693675662000 * 1e18, + exchangeRate: 1.005218356846837831 * 1e18 }); _assertReserveAuction({ - reserves: 24.540827358578637024 * 1e18, + reserves: 24.296647707318004711 * 1e18, claimableReserves : 0, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 }); - + _assertAuction( AuctionParams({ borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.195342779771472726 * 1e18, // should be the same after arb take, kicker will be rewarded with LP - bondFactor: 0.01 * 1e18, + bondSize: 0.296536979149981005 * 1e18, // should be the same after arb take, kicker will be rewarded with LP + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 6.5 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 7.251730722192532064 * 1e18, - debtInAuction: 19.779116873676490457 * 1e18, - thresholdPrice: 9.889558436838245228 * 1e18, - neutralPrice: 10.255495938002318100 * 1e18 + referencePrice: 11.249823884323541351 * 1e18, + totalBondEscrowed: 0.296536979149981005 * 1e18, + auctionPrice: 9.459936576563284516 * 1e18, + debtInAuction: 19.534930245606410328 * 1e18, + thresholdPrice: 9.767465122803205164 * 1e18, + neutralPrice: 11.249823884323541351 * 1e18 }) ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 19.779116873676490457 * 1e18, + borrowerDebt: 19.534930245606410328 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 0.982985835729561629 * 1e18 + borrowert0Np: 11.096767433127708186 * 1e18, + borrowerCollateralization: 0.995273158676181149 * 1e18 }); // Amount is restricted by the collateral in the loan @@ -281,35 +280,35 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { kicker: _lender, index: _i9_91, collateralArbed: 2 * 1e18, - quoteTokenAmount: 14.503461444385064128 * 1e18, - bondChange: 0.145034614443850641 * 1e18, + quoteTokenAmount: 18.919873153126569032 * 1e18, + bondChange: 0.287210105092827748 * 1e18, isReward: true, - lpAwardTaker: 5.303234074136771188 * 1e18, - lpAwardKicker: 0.144281701027576469 * 1e18 + lpAwardTaker: 0.909749138101538138 * 1e18, + lpAwardKicker: 0.285719120762723106 * 1e18 }); _assertLenderLpBalance({ lender: _taker, index: _i9_91, - lpBalance: 5.303234074136771188 * 1e18, + lpBalance: 0.909749138101538138 * 1e18, depositTime: _startTime + 100 days + 6.5 hours }); _assertLenderLpBalance({ lender: _lender, index: _i9_91, - lpBalance: 2_000.144281701027576469 * 1e18, // rewarded with LP in bucket + lpBalance: 2_000.285719120762723106 * 1e18, // rewarded with LP in bucket depositTime: _startTime + 100 days + 6.5 hours }); _assertBucket({ index: _i9_91, - lpBalance: 2_005.447515775164347657 * 1e18, + lpBalance: 2_001.195468258864261244 * 1e18, collateral: 2 * 1e18, - deposit: 1_996.078287055630004514 * 1e18, - exchangeRate: 1.005218356942785610 * 1e18 + deposit: 1_991.804050645641920716 * 1e18, + exchangeRate: 1.005218356846837832 * 1e18 }); // reserves should remain the same after arb take _assertReserveAuction({ - reserves: 25.925365539735991348 * 1e18, + reserves: 24.296647707318004709 * 1e18, claimableReserves : 0, claimableReservesRemaining: 0, auctionPrice: 0, @@ -317,9 +316,9 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { }); _assertBorrower({ borrower: _borrower, - borrowerDebt: 6.805228224892631304 * 1e18, + borrowerDebt: 0.902267197572669045 * 1e18, borrowerCollateral: 0, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 0 }); _assertAuction( @@ -327,15 +326,15 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.195342779771472726 * 1e18, // bond size remains the same, kicker was rewarded with LP - bondFactor: 0.01 * 1e18, + bondSize: 0.296536979149981005 * 1e18, // bond size remains the same, kicker was rewarded with LP + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 6.5 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 7.251730722192532064 * 1e18, - debtInAuction: 6.805228224892631304 * 1e18, + referencePrice: 11.249823884323541351 * 1e18, + totalBondEscrowed: 0.296536979149981005 * 1e18, + auctionPrice: 9.459936576563284516 * 1e18, + debtInAuction: 0.902267197572669045 * 1e18, thresholdPrice: 0, - neutralPrice: 10.255495938002318100 * 1e18 + neutralPrice: 11.249823884323541351 * 1e18 }) ); @@ -348,7 +347,6 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { } function testArbTakeDebtRestrict() external tearDown { - skip(5 hours); _assertAuction( @@ -356,15 +354,15 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.195342779771472726 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.296536979149981005 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 5 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 20.510991876004636192 * 1e18, - debtInAuction: 19.778456451861613481 * 1e18, - thresholdPrice: 9.889482233342512890 * 1e18, - neutralPrice: 10.255495938002318100 * 1e18 + referencePrice: 11.249823884323541351 * 1e18, + totalBondEscrowed: 0.296536979149981005 * 1e18, + auctionPrice: 15.909653511519124956 * 1e18, + debtInAuction: 19.534277977147272574 * 1e18, + thresholdPrice: 9.767389860091370755 * 1e18, + neutralPrice: 11.249823884323541351 * 1e18 }) ); @@ -375,13 +373,13 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { lpAward: 25_000 * 1e18, newLup: 1_505.263728469068226832 * 1e18 }); - + _assertBorrower({ borrower: _borrower, - borrowerDebt: 19.778964466685025781 * 1e18, + borrowerDebt: 19.534779720182741511 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 152.208547722958917634 * 1e18 + borrowert0Np: 11.096767433127708186 * 1e18, + borrowerCollateralization: 154.111154569495900146 * 1e18 }); // Amount is restricted by the debt in the loan @@ -390,25 +388,25 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { borrower: _borrower, kicker: _lender, index: _i1505_26, - collateralArbed: 1.031812215971460994 * 1e18, - quoteTokenAmount: 21.163491979352977585 * 1e18, - bondChange: 0.195342779771472726 * 1e18, + collateralArbed: 1.256467421916368415 * 1e18, + quoteTokenAmount: 19.989961331201132696 * 1e18, + bondChange: 0.296536979149981005 * 1e18, isReward: false, - lpAwardTaker: 1_531.986011313779866429 * 1e18, + lpAwardTaker: 1_871.324874882549437558 * 1e18, lpAwardKicker: 0 }); _assertBorrower({ borrower: _borrower, borrowerDebt: 0, - borrowerCollateral: 0.968187784028539006 * 1e18, + borrowerCollateral: 0.743532578083631585 * 1e18, borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); _assertLenderLpBalance({ lender: _taker, index: _i1505_26, - lpBalance: 1_531.986011313779866429 * 1e18, + lpBalance: 1_871.324874882549437558 * 1e18, depositTime: block.timestamp }); _assertLenderLpBalance({ @@ -419,13 +417,13 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { }); _assertBucket({ index: _i1505_26, - lpBalance: 26_531.986011313779866429 * 1e18, - collateral: 1.031812215971460994 * 1e18, - deposit: 24_978.836508020647022415 * 1e18, - exchangeRate: 1 * 1e18 + lpBalance: 26_871.324874882549437558 * 1e18, + collateral: 1.256467421916368415 * 1e18, + deposit: 24_980.010038668798867303 * 1e18, + exchangeRate: 1.000000000000000000 * 1e18 }); _assertReserveAuction({ - reserves: 26.111547973458754924 * 1e18, + reserves: 25.039216891441214202 * 1e18, claimableReserves : 0, claimableReservesRemaining: 0, auctionPrice: 0, @@ -434,7 +432,6 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { } function testArbTakeDepositRestrict() external tearDown { - skip(5 hours); _assertAuction( @@ -442,15 +439,15 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.195342779771472726 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.296536979149981005 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 5 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 20.510991876004636192 * 1e18, - debtInAuction: 19.778456451861613481 * 1e18, - thresholdPrice: 9.889482233342512890 * 1e18, - neutralPrice: 10.255495938002318100 * 1e18 + referencePrice: 11.249823884323541351 * 1e18, + totalBondEscrowed: 0.296536979149981005 * 1e18, + auctionPrice: 15.909653511519124956 * 1e18, + debtInAuction: 19.534277977147272574 * 1e18, + thresholdPrice: 9.767389860091370755 * 1e18, + neutralPrice: 11.249823884323541351 * 1e18 }) ); @@ -464,10 +461,10 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { _assertBorrower({ borrower: _borrower, - borrowerDebt: 19.778964466685025781 * 1e18, + borrowerDebt: 19.534779720182741511 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 0.982993410135902682 * 1e18 + borrowert0Np: 11.096767433127708186 * 1e18, + borrowerCollateralization: 0.995280827762601466 * 1e18 }); // Amount is restricted by the deposit in the bucket @@ -476,48 +473,48 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { borrower: _borrower, kicker: _lender, index: _i1505_26, - collateralArbed: 0.731315193857015473 * 1e18, - quoteTokenAmount: 14.99999999999999999 * 1e18, - bondChange: 0.15 * 1e18, + collateralArbed: 0.942823801231088711 * 1e18, + quoteTokenAmount: 14.999999999999999998 * 1e18, + bondChange: 0.227705098312484220 * 1e18, isReward: false, - lpAwardTaker: 1_085.822235391290531090 * 1e18, + lpAwardTaker: 1_404.198470330488271279 * 1e18, lpAwardKicker: 0 }); _assertAuction( AuctionParams({ borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0.045342779771472726 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 4.858174346779663281 * 1e18, - neutralPrice: 0 + active: true, + kicker: _lender, + bondSize: 0.068831880837496785 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 5 hours, + referencePrice: 11.249823884323541351 * 1e18, + totalBondEscrowed: 0.068831880837496785 * 1e18, + auctionPrice: 15.909653511519124956 * 1e18, + debtInAuction: 4.876337367651467845 * 1e18, + thresholdPrice: 4.612606085276981381 * 1e18, + neutralPrice: 11.249823884323541351 * 1e18 }) ); _assertBucket({ index: _i1505_26, - lpBalance: 1_100.822235391290531090 * 1e18, - collateral: 0.731315193857015473 * 1e18, - deposit: 10, - exchangeRate: 1 * 1e18 + lpBalance: 1_419.198470330488271279 * 1e18, + collateral: 0.942823801231088711 * 1e18, + deposit: 0.000000000000000003 * 1e18, + exchangeRate: 1.000000000000000001 * 1e18 }); _assertBorrower({ borrower: _borrower, - borrowerDebt: 6.163491979352977596 * 1e18, - borrowerCollateral: 1.268684806142984527 * 1e18, - borrowert0Np: 5.057793757429320966 * 1e18, - borrowerCollateralization: 2.001018319047304749 * 1e18 + borrowerDebt: 4.876337367651467845 * 1e18, + borrowerCollateral: 1.057176198768911289 * 1e18, + borrowert0Np: 5.240398686048708221 * 1e18, + borrowerCollateralization: 2.107549546895251001 * 1e18 }); _assertLenderLpBalance({ lender: _taker, index: _i1505_26, - lpBalance: 1_085.822235391290531090 * 1e18, + lpBalance: 1_404.198470330488271279 * 1e18, depositTime: block.timestamp }); _assertLenderLpBalance({ @@ -529,7 +526,6 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { } function testArbTakeGTNeutralPrice() external tearDown { - skip(3 hours); _addLiquidity({ @@ -564,23 +560,23 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.195342779771472726 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.296536979149981005 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 3 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 82.043967504018544800 * 1e18, - debtInAuction: 19.778761259189860404 * 1e18, - thresholdPrice: 9.889380629594930202 * 1e18, - neutralPrice: 10.255495938002318100 * 1e18 + referencePrice: 11.249823884323541351 * 1e18, + totalBondEscrowed: 0.296536979149981005 * 1e18, + auctionPrice: 31.819307023038249912 * 1e18, + debtInAuction: 19.534579021422084350 * 1e18, + thresholdPrice: 9.767289510711042175 * 1e18, + neutralPrice: 11.249823884323541351 * 1e18 }) ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 19.778761259189860404 * 1e18, + borrowerDebt: 19.534579021422084350 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 0.983003509435146965 * 1e18 + borrowert0Np: 11.096767433127708186 * 1e18, + borrowerCollateralization: 0.995291053303086302 * 1e18 }); _arbTake({ @@ -588,18 +584,18 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { borrower: _borrower, kicker: _lender, index: _i10016, - collateralArbed: 0.257950403803869741 * 1e18, - quoteTokenAmount: 21.163274547333150632 * 1e18, - bondChange: 0.195342779771472726 * 1e18, + collateralArbed: 0.628227256535406044 * 1e18, + quoteTokenAmount: 19.989755955941097815 * 1e18, + bondChange: 0.296536979149981005 * 1e18, isReward: false, - lpAwardTaker: 2_562.597355112798042 * 1e18, + lpAwardTaker: 6_272.649557567888341455 * 1e18, lpAwardKicker: 0 }); _assertLenderLpBalance({ lender: _taker, index: _i10016, - lpBalance: 2_562.597355112798042 * 1e18, // arb taker was rewarded LPBs in arbed bucket + lpBalance: 6_272.649557567888341455 * 1e18, // arb taker was rewarded LPBs in arbed bucket depositTime: _startTime + 100 days + 3 hours }); _assertLenderLpBalance({ @@ -615,9 +611,9 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { }); _assertBucket({ index: _i10016, - lpBalance: 3_562.597355112798042 * 1e18, // LP balance in arbed bucket increased with LP awarded for arb taker - collateral: 0.257950403803869741 * 1e18, // arbed collateral added to the arbed bucket - deposit: 978.836725452666849368 * 1e18, // quote token amount is diminished in arbed bucket + lpBalance: 7_272.649557567888341455 * 1e18, // LP balance in arbed bucket increased with LP awarded for arb taker + collateral: 0.628227256535406044 * 1e18, // arbed collateral added to the arbed bucket + deposit: 980.010244044058902179 * 1e18, // quote token amount is diminished in arbed bucket exchangeRate: 1.000000000000000001 * 1e18 }); _assertAuction( @@ -628,7 +624,7 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -639,13 +635,19 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { _assertBorrower({ borrower: _borrower, borrowerDebt: 0, - borrowerCollateral: 1.742049596196130259 * 1e18, + borrowerCollateral: 1.371772743464593956 * 1e18, borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); } function testArbTakeReverts() external tearDown { + // should revert if taken from same block when kicked + _assertArbTakeAuctionNotTakeableRevert({ + from: _taker, + borrower: _borrower, + index: _i9_62 + }); // should revert if borrower not auctioned _assertArbTakeNoAuction({ @@ -654,13 +656,6 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { index: _i9_91 }); - // should revert if auction in grace period - _assertArbTakeAuctionInCooldownRevert({ - from: _lender, - borrower: _borrower, - index: _i9_91 - }); - skip(2.5 hours); _assertAuction( @@ -668,23 +663,29 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.195342779771472726 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.296536979149981005 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 2.5 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 116.027691555080513536 * 1e18, - debtInAuction: 19.778456451861613481 * 1e18, - thresholdPrice: 9.889355228821139433 * 1e18, - neutralPrice: 10.255495938002318100 * 1e18 + referencePrice: 11.249823884323541351 * 1e18, + totalBondEscrowed: 0.296536979149981005 * 1e18, + auctionPrice: 37.839746306253138192 * 1e18, + debtInAuction: 19.534277977147272574 * 1e18, + thresholdPrice: 9.767264423527051292 * 1e18, + neutralPrice: 11.249823884323541351 * 1e18 }) ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 19.778710457642278867 * 1e18, + borrowerDebt: 19.534528847054102585 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 0.983006034276170567 * 1e18 + borrowert0Np: 11.096767433127708186 * 1e18, + borrowerCollateralization: 0.995293609704622699 * 1e18 + }); + + // borrower cannot repay amidst auction + _assertRepayAuctionActiveRevert({ + from: _borrower, + maxAmount: 10 * 1e18 }); // should revert if bucket deposit is 0 @@ -714,5 +715,13 @@ contract ERC20PoolLiquidationsArbTakeTest is ERC20HelperContract { borrower: _borrower, index: _i9_91 }); + + // ensure zero bid reverts + skip(3 days); + _assertArbTakeZeroBidRevert({ + from: _taker, + borrower: _borrower, + index: _i9_52 + }); } } diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsDepositTake.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsDepositTake.t.sol index 209be726c..3a5f7a027 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsDepositTake.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsDepositTake.t.sol @@ -109,14 +109,14 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.268509615384615394 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 1.009034539679184679 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 7_987.673076923076926760 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 8.471136974495192174 * 1e18, + borrowert0Np: 9.200228999102245332 * 1e18, borrowerCollateralization: 1.217037273735858713 * 1e18 }); _assertReserveAuction({ @@ -147,7 +147,7 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -159,17 +159,17 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.939819504377940339 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 0.975063576969429891 * 1e18 }); _kick({ from: _lender, borrower: _borrower, - debt: 20.189067248182664594 * 1e18, + debt: 19.939819504377940339 * 1e18, collateral: 2 * 1e18, - bond: 0.199398195043779403 * 1e18, - transferAmount: 0.199398195043779403 * 1e18 + bond: 0.302693237371837952 * 1e18, + transferAmount: 0.302693237371837952 * 1e18 }); _assertAuction( @@ -177,21 +177,21 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.199398195043779403 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.302693237371837952 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.199398195043779403 * 1e18, - auctionPrice: 334.988967673549397664 * 1e18, - debtInAuction: 20.189067248182664594 * 1e18, - thresholdPrice: 10.094533624091332297 * 1e18, - neutralPrice: 10.468405239798418677 * 1e18 + referencePrice: 11.483375939048159968 * 1e18, + totalBondEscrowed: 0.302693237371837952 * 1e18, + auctionPrice: 2_939.744240396328951808 * 1e18, + debtInAuction: 19.939819504377940339 * 1e18, + thresholdPrice: 9.969909752188970169 * 1e18, + neutralPrice: 11.483375939048159968 * 1e18 }) ); _assertKicker({ kicker: _lender, claimable: 0, - locked: 0.199398195043779403 * 1e18 + locked: 0.302693237371837952 * 1e18 }); } @@ -219,10 +219,10 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { }); _assertBorrower({ borrower: _borrower, - borrowerDebt: 20.189741380689676443 * 1e18, + borrowerDebt: 19.940485314261408832 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 0.962993599742653326 * 1e18 + borrowert0Np: 11.096767433127708186 * 1e18, + borrowerCollateralization: 0.975031019739436493 * 1e18 }); // add liquidity to accrue interest and update reserves before deposit take @@ -231,7 +231,7 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { amount: 1 * 1e18, amountAdded: 0.999876712328767123 * 1e18, index: _i9_52, - lpAward: 0.999873479995558788 * 1e18, + lpAward: 0.999873480092787187 * 1e18, newLup: 9.721295865031779605 * 1e18 }); @@ -239,12 +239,12 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { index: _i9_91, lpBalance: 2_000 * 1e18, collateral: 0, - deposit: 2_026.352751434705402000 * 1e18, - exchangeRate: 1.013176375717352701 * 1e18 + deposit: 2_026.352751237661440000 * 1e18, + exchangeRate: 1.013176375618830720 * 1e18 }); _assertReserveAuction({ - reserves: 49.824849391649864824 * 1e18, - claimableReserves : 8.392639704106692236 * 1e18, + reserves: 49.575600446873147197 * 1e18, + claimableReserves : 8.144637039662123068 * 1e18, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 @@ -255,23 +255,23 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.199398195043779403 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.302693237371837952 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 6.5 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.199398195043779403 * 1e18, - auctionPrice: 7.402280333270247968 * 1e18, - debtInAuction: 20.189741380689676443 * 1e18, - thresholdPrice: 10.094870690344838221 * 1e18, - neutralPrice: 10.468405239798418677 * 1e18 + referencePrice: 11.483375939048159968 * 1e18, + totalBondEscrowed: 0.302693237371837952 * 1e18, + auctionPrice: 9.656329662156355672 * 1e18, + debtInAuction: 19.940485314261408832 * 1e18, + thresholdPrice: 9.970242657130704416 * 1e18, + neutralPrice: 11.483375939048159968 * 1e18 }) ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 20.189741380689676443 * 1e18, + borrowerDebt: 19.940485314261408832 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 0.962993599742653326 * 1e18 + borrowert0Np: 11.096767433127708186 * 1e18, + borrowerCollateralization: 0.975031019739436493 * 1e18 }); // Amount is restricted by the collateral in the loan @@ -282,10 +282,10 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { index: _i9_91, collateralArbed: 2 * 1e18, quoteTokenAmount: 19.834369686871824148 * 1e18, - bondChange: 0.198343696868718241 * 1e18, + bondChange: 0.301092473301020371 * 1e18, isReward: true, lpAwardTaker: 0, - lpAwardKicker: 0.195764233772511956 * 1e18 + lpAwardKicker: 0.297176760677150868 * 1e18 }); _assertLenderLpBalance({ @@ -297,20 +297,20 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { _assertLenderLpBalance({ lender: _lender, index: _i9_91, - lpBalance: 2_000.195764233772511956 * 1e18, + lpBalance: 2_000.297176760677150868 * 1e18, depositTime: _startTime + 250 days + 6.5 hours }); _assertBucket({ index: _i9_91, - lpBalance: 2_000.195764233772511956 * 1e18, + lpBalance: 2_000.297176760677150868 * 1e18, collateral: 2 * 1e18, - deposit: 2_006.716725444702296094 * 1e18, - exchangeRate: 1.013176375717352702 * 1e18 + deposit: 2_006.819474024090636225 * 1e18, + exchangeRate: 1.013176375618830721 * 1e18 }); // reserves should remain the same after deposit take _assertReserveAuction({ - reserves: 51.238131288298142183 * 1e18, - claimableReserves : 9.897035340857769728 * 1e18, + reserves: 49.575600446873147192 * 1e18, + claimableReserves : 8.242303445263254296 * 1e18, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 @@ -320,22 +320,22 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.199398195043779403 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.302693237371837952 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 6.5 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.199398195043779403 * 1e18, - auctionPrice: 7.402280333270247968 * 1e18, - debtInAuction: 1.966997287334847889 * 1e18, + referencePrice: 11.483375939048159968 * 1e18, + totalBondEscrowed: 0.302693237371837952 * 1e18, + auctionPrice: 9.656329662156355672 * 1e18, + debtInAuction: 0.407208100690605057 * 1e18, thresholdPrice: 0, - neutralPrice: 10.468405239798418677 * 1e18 + neutralPrice: 11.483375939048159968 * 1e18 }) ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 1.966997287334847889 * 1e18, + borrowerDebt: 0.407208100690605057 * 1e18, borrowerCollateral: 0, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 0 }); @@ -348,7 +348,6 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { } function testDepositTakeDebtRestrict() external tearDown { - skip(5 hours); _assertAuction( @@ -356,15 +355,15 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.199398195043779403 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.302693237371837952 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 5 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.199398195043779403 * 1e18, - auctionPrice: 20.936810479596837344 * 1e18, - debtInAuction: 20.189067248182664594 * 1e18, - thresholdPrice: 10.094792904825850360 * 1e18, - neutralPrice: 10.468405239798418677 * 1e18 + referencePrice: 11.483375939048159968 * 1e18, + totalBondEscrowed: 0.302693237371837952 * 1e18, + auctionPrice: 16.239945994830783896 * 1e18, + debtInAuction: 19.939819504377940339 * 1e18, + thresholdPrice: 9.970165831926765787 * 1e18, + neutralPrice: 11.483375939048159968 * 1e18 }) ); @@ -378,10 +377,10 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { _assertBorrower({ borrower: _borrower, - borrowerDebt: 20.189585809651700720 * 1e18, + borrowerDebt: 19.940331663853531575 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 149.112888462473727465 * 1e18 + borrowert0Np: 11.096767433127708186 * 1e18, + borrowerCollateralization: 150.976799568254654687 * 1e18 }); _assertBucket({ index: _i1505_26, @@ -397,9 +396,9 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { borrower: _borrower, kicker: _lender, index: _i1505_26, - collateralArbed: 0.014351542794629452 * 1e18, - quoteTokenAmount: 21.602856816327319770 * 1e18, - bondChange: 0.199398195043779403 * 1e18, + collateralArbed: 0.013555739562620698 * 1e18, + quoteTokenAmount: 20.404963076186087933 * 1e18, + bondChange: 0.302693237371837952 * 1e18, isReward: false, lpAwardTaker: 0, lpAwardKicker: 0 @@ -408,7 +407,7 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { _assertBorrower({ borrower: _borrower, borrowerDebt: 0, - borrowerCollateral: 1.985648457205370548 * 1e18, + borrowerCollateral: 1.986444260437379302 * 1e18, borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); @@ -427,13 +426,13 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { _assertBucket({ index: _i1505_26, lpBalance: 25_000 * 1e18, - collateral: 0.014351542794629452 * 1e18, - deposit: 24_978.397143183672680230 * 1e18, + collateral: 0.013555739562620698 * 1e18, + deposit: 24_979.595036923813911959 * 1e18, exchangeRate: 1.000000000000000001 * 1e18 }); _assertReserveAuction({ - reserves: 51.428181523373734114 * 1e18, - claimableReserves : 10.097214040782253165 * 1e18, + reserves: 50.333588303732929197 * 1e18, + claimableReserves : 9.002620819943559986 * 1e18, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 @@ -441,7 +440,6 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { } function testDepositTakeDepositRestrict() external tearDown { - skip(5 hours); _assertAuction( @@ -449,15 +447,15 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.199398195043779403 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.302693237371837952 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 5 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.199398195043779403 * 1e18, - auctionPrice: 20.936810479596837344 * 1e18, - debtInAuction: 20.189067248182664594 * 1e18, - thresholdPrice: 10.094792904825850360 * 1e18, - neutralPrice: 10.468405239798418677 * 1e18 + referencePrice: 11.483375939048159968 * 1e18, + totalBondEscrowed: 0.302693237371837952 * 1e18, + auctionPrice: 16.239945994830783896 * 1e18, + debtInAuction: 19.939819504377940339 * 1e18, + thresholdPrice: 9.970165831926765787 * 1e18, + neutralPrice: 11.483375939048159968 * 1e18 }) ); @@ -471,10 +469,10 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { _assertBorrower({ borrower: _borrower, - borrowerDebt: 20.189585809651700720 * 1e18, + borrowerDebt: 19.940331663853531575 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 0.963001020098637267 * 1e18 + borrowert0Np: 11.096767433127708186 * 1e18, + borrowerCollateralization: 0.975038532849870233 * 1e18 }); // Amount is restricted by the deposit in the bucket in the loan @@ -485,7 +483,7 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { index: _i1505_26, collateralArbed: 0.009965031187761219 * 1e18, quoteTokenAmount: 14.999999999999999995 * 1e18, - bondChange: 0.15 * 1e18, + bondChange: 0.227705098312484220 * 1e18, isReward: false, lpAwardTaker: 0, lpAwardKicker: 0 @@ -494,32 +492,32 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { _assertAuction( AuctionParams({ borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0.049398195043779403 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 3.317960196583009907 * 1e18, - neutralPrice: 0 + active: true, + kicker: _lender, + bondSize: 0.074988139059353732 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 5 hours, + referencePrice: 11.483375939048159968 * 1e18, + totalBondEscrowed: 0.074988139059353732 * 1e18, + auctionPrice: 16.239945994830783896 * 1e18, + debtInAuction: 5.281889311322257910 * 1e18, + thresholdPrice: 2.654169094563588010 * 1e18, + neutralPrice: 11.483375939048159968 * 1e18 }) ); _assertBucket({ index: _i1505_26, lpBalance: 15 * 1e18, collateral: 0.009965031187761219 * 1e18, - deposit: 5, + deposit: 0.000000000000000005 * 1e18, exchangeRate: 1.000000000000000001 * 1e18 }); _assertBorrower({ borrower: _borrower, - borrowerDebt: 6.602856816327319776 * 1e18, + borrowerDebt: 5.281889311322257910 * 1e18, borrowerCollateral: 1.990034968812238781 * 1e18, - borrowert0Np: 3.384038787324199951 * 1e18, - borrowerCollateralization: 2.929901291475172996 * 1e18 + borrowert0Np: 2.954082977863112822 * 1e18, + borrowerCollateralization: 3.662651292618643252 * 1e18 }); _assertLenderLpBalance({ lender: _taker, @@ -536,7 +534,6 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { } function testDepositTakeGTNeutralPrice() external tearDown { - skip(3 hours); _addLiquidity({ @@ -571,23 +568,23 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.199398195043779403 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.302693237371837952 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 3 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.199398195043779403 * 1e18, - auctionPrice: 83.747241918387349408 * 1e18, - debtInAuction: 20.189378383465778991 * 1e18, - thresholdPrice: 10.094689191732889495 * 1e18, - neutralPrice: 10.468405239798418677 * 1e18 + referencePrice: 11.483375939048159968 * 1e18, + totalBondEscrowed: 0.302693237371837952 * 1e18, + auctionPrice: 32.479891989661567792 * 1e18, + debtInAuction: 19.940126798484719991 * 1e18, + thresholdPrice: 9.970063399242359995 * 1e18, + neutralPrice: 11.483375939048159968 * 1e18 }) ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 20.189378383465778991 * 1e18, + borrowerDebt: 19.940126798484719991 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 0.963010913995558897 * 1e18 + borrowert0Np: 11.096767433127708186 * 1e18, + borrowerCollateralization: 0.975048550420503383 * 1e18 }); _depositTake({ @@ -595,9 +592,9 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { borrower: _borrower, kicker: _lender, index: _i10016, - collateralArbed: 0.002156704581707556 * 1e18, - quoteTokenAmount: 21.602634870308383520 * 1e18, - bondChange: 0.199398195043779403 * 1e18, + collateralArbed: 0.002037113782225481 * 1e18, + quoteTokenAmount: 20.404753437231397559 * 1e18, + bondChange: 0.302693237371837952 * 1e18, isReward: false, lpAwardTaker: 0, lpAwardKicker: 0 @@ -624,9 +621,9 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { _assertBucket({ index: _i10016, lpBalance: 1_000 * 1e18, // LP balance in arbed bucket increased with LP awarded for deposit taker - collateral: 0.002156704581707556 * 1e18, // arbed collateral added to the arbed bucket - deposit: 978.397365129691616480 * 1e18, // quote token amount is diminished in arbed bucket - exchangeRate: 1 * 1e18 + collateral: 0.002037113782225481 * 1e18, // arbed collateral added to the arbed bucket + deposit: 979.595246562768594325 * 1e18, // quote token amount is diminished in arbed bucket + exchangeRate: 1.000000000000000001 * 1e18 }); _assertAuction( AuctionParams({ @@ -636,7 +633,7 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -647,19 +644,18 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { _assertBorrower({ borrower: _borrower, borrowerDebt: 0, - borrowerCollateral: 1.997843295418292444 * 1e18, + borrowerCollateral: 1.997962886217774519 * 1e18, borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); } function testDepositTakeReverts() external tearDown { - - // should revert if auction in grace period - _assertDepositTakeAuctionInCooldownRevert({ - from: _lender, + // should revert if taken from same block when kicked + _assertDepositTakeAuctionNotTakeableRevert({ + from: _taker, borrower: _borrower, - index: _i9_91 + index: _i9_72 }); skip(2.5 hours); @@ -669,15 +665,15 @@ contract ERC20PoolLiquidationsDepositTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.199398195043779403 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.302693237371837952 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 2.5 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.199398195043779403 * 1e18, - auctionPrice: 118.436485332323967968 * 1e18, - debtInAuction: 20.189067248182664594 * 1e18, - thresholdPrice: 10.094663263626140338 * 1e18, - neutralPrice: 10.468405239798418677 * 1e18 + referencePrice: 11.483375939048159968 * 1e18, + totalBondEscrowed: 0.302693237371837952 * 1e18, + auctionPrice: 38.625318648625422832 * 1e18, + debtInAuction: 19.939819504377940339 * 1e18, + thresholdPrice: 9.970037791235694161 * 1e18, + neutralPrice: 11.483375939048159968 * 1e18 }) ); @@ -733,6 +729,7 @@ contract ERC20PoolLiquidationsDepositTakeRegressionTest is ERC20HelperContract { _mintQuoteAndApproveTokens(actor4, type(uint256).max); _mintCollateralAndApproveTokens(actor4, type(uint256).max); + assertEq(_priceAt(2572), 2_697.999235705754194133 * 1e18); _addInitialLiquidity({ from: actor2, amount: 1_791_670_358_647.909977170293982862 * 1e18, @@ -764,17 +761,17 @@ contract ERC20PoolLiquidationsDepositTakeRegressionTest is ERC20HelperContract { borrower: actor2, active: true, kicker: actor1, - bondSize: 9_090_645_929.673616432967467261 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 13_799_909_500.935435603423349661 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime + 100 days, - kickMomp: 2_697.999235705754194133 * 1e18, - totalBondEscrowed: 9_090_645_929.673616432967467261 * 1e18, + referencePrice: 3_137.845063437099084063 * 1e18, + totalBondEscrowed: 13_799_909_500.935435603423349661 * 1e18, auctionPrice: 0, - debtInAuction: 930_695_454_793.486423224879367583 * 1e18, - thresholdPrice: 2_789.112230632554291586 * 1e18, - neutralPrice: 2_860.503207254858101199 * 1e18 + debtInAuction: 920_341_611_662.285708998644615657 * 1e18, + thresholdPrice: 2_758.083788017359002804 * 1e18, + neutralPrice: 3_137.845063437099084063 * 1e18 // was 2_860.503207254858101199 }) - ); + ); // assert kicker balances in bucket before bucket take auction with auction price zero _assertLenderLpBalance({ @@ -784,15 +781,31 @@ contract ERC20PoolLiquidationsDepositTakeRegressionTest is ERC20HelperContract { depositTime: 0 }); - ERC20Pool(address(_pool)).bucketTake(actor2, false, 2572); + ERC20Pool(address(_pool)).bucketTake(actor2, true, 2572); - // assert kicker balances in bucket after take - // deposit time should remain the same since auction price was zero / kicker reward is zero + // ensure some debt was covered by the take + _assertAuction( + AuctionParams({ + borrower: actor2, + active: true, + kicker: actor1, + bondSize: 13_799_909_500.935435603423349661 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: _startTime + 100 days, + referencePrice: 3_137.845063437099084063 * 1e18, + totalBondEscrowed: 13_799_909_500.935435603423349661 * 1e18, + auctionPrice: 0, + debtInAuction: 33_716_280_531.11637887639485531 * 1e18, + thresholdPrice: 0, + neutralPrice: 3_137.845063437099084063 * 1e18 // was 2_860.503207254858101199 + }) + ); + // ensure kicker was rewarded since bucket price taken was below the neutral price _assertLenderLpBalance({ lender: actor1, - index: 2572, - lpBalance: 0, - depositTime: 0 + index: 2572, // 2697.99923570534 + lpBalance: 13512526017.591065704389485704 * 1e18, + depositTime: _startTime + 200 days }); } @@ -833,7 +846,7 @@ contract ERC20PoolLiquidationsDepositTakeRegressionTest is ERC20HelperContract { changePrank(actor2); _pool.updateInterest(); _pool.kick(actor0, 7388); - skip(5 days); + skip(70 hours); changePrank(actor3); _pool.updateInterest(); @@ -857,8 +870,11 @@ contract ERC20PoolLiquidationsDepositTakeRegressionTest is ERC20HelperContract { _pool.updateInterest(); // bucket take with bucket 2571 should revert as deposit of 3 cannot cover at least one unit of collateral - vm.expectRevert(IPoolErrors.InsufficientLiquidity.selector); - _pool.bucketTake(actor0, true, 2571); + _assertDepositTakeZeroBidRevert({ + from: actor2, + borrower: actor0, + index: 2571 + }); // assert bucket after take _assertBucket({ diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsKick.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsKick.t.sol index aee3f5358..689ff75c1 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsKick.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsKick.t.sol @@ -111,14 +111,14 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.268509615384615394 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 1.009034539679184679 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 7_987.673076923076926760 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 8.471136974495192174 * 1e18, + borrowert0Np: 9.200228999102245332 * 1e18, borrowerCollateralization: 1.217037273735858713 * 1e18 }); _assertReserveAuction({ @@ -145,7 +145,7 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -157,7 +157,7 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.534277977147272574 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 0.995306391810796636 * 1e18 }); @@ -170,10 +170,10 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { _kick({ from: _lender, borrower: _borrower, - debt: 19.778456451861613481 * 1e18, + debt: 19.534277977147272573 * 1e18, collateral: 2 * 1e18, - bond: 0.195342779771472726 * 1e18, - transferAmount: 0.195342779771472726 * 1e18 + bond: 0.296536979149981005 * 1e18, + transferAmount: 0.296536979149981005 * 1e18 }); /******************************/ @@ -186,11 +186,11 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { lup: 9.721295865031779605 * 1e18, poolSize: 73_093.873009488594544000 * 1e18, pledgedCollateral: 1_002 * 1e18, - encumberedCollateral: 835.035237319063220562 * 1e18, - poolDebt: 8_117.624599705640061722 * 1e18, + encumberedCollateral: 835.010119425512354679 * 1e18, + poolDebt: 8_117.380421230925720814 * 1e18, actualUtilization: 0.109684131322444679 * 1e18, targetUtilization: 0.822075127292417292 * 1e18, - minDebtAmount: 811.762459970564006172 * 1e18, + minDebtAmount: 811.738042123092572081* 1e18, loans: 1, maxBorrower: address(_borrower2), interestRate: 0.045 * 1e18, @@ -199,45 +199,44 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 19.778456451861613481 * 1e18, + borrowerDebt: 19.534277977147272574 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 0.983018658578564579 * 1e18 + borrowert0Np: 11.096767433127708186 * 1e18, + borrowerCollateralization: 0.995306391810796636 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 8_097.846143253778448241 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 8.471136974495192174 * 1e18, + borrowert0Np: 9.200228999102245332 * 1e18, borrowerCollateralization: 1.200479200648987171 * 1e18 }); - assertEq(_quote.balanceOf(_lender), 46_999.804657220228527274 * 1e18); + assertEq(_quote.balanceOf(_lender), 46_999.703463020850018995 * 1e18); _assertAuction( AuctionParams({ borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.195342779771472726 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.296536979149981005 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 328.175870016074179200 * 1e18, - debtInAuction: 19.778456451861613481 * 1e18, - thresholdPrice: 9.889228225930806740 * 1e18, - neutralPrice: 10.255495938002318100 * 1e18 + referencePrice: 11.249823884323541351 * 1e18, + totalBondEscrowed: 0.296536979149981005 * 1e18, + auctionPrice: 2_879.954914386826585856 * 1e18, + debtInAuction: 19.534277977147272574 * 1e18, + thresholdPrice: 9.767138988573636287 * 1e18, + neutralPrice: 11.249823884323541351 * 1e18 }) ); - assertEq(_poolUtils.momp(address(_pool)), 9.818751856078723036 * 1e18); _assertKicker({ kicker: _lender, claimable: 0, - locked: 0.195342779771472726 * 1e18 + locked: 0.296536979149981005 * 1e18 }); _assertReserveAuction({ - reserves: 24.501590217045517722 * 1e18, + reserves: 24.257411742331176814 * 1e18, claimableReserves : 0, claimableReservesRemaining: 0, auctionPrice: 0, @@ -271,326 +270,7 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { }); } - function testKickAndSaveByRepay() external tearDown { - - // Skip to make borrower undercollateralized - skip(100 days); - - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 9.767138988573636287 * 1e18, - neutralPrice: 0 - }) - ); - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 19.534277977147272574 * 1e18, - borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 0.995306391810796636 * 1e18 - }); - - _kick({ - from: _lender, - borrower: _borrower, - debt: 19.778456451861613481 * 1e18, - collateral: 2 * 1e18, - bond: 0.195342779771472726 * 1e18, - transferAmount: 0.195342779771472726 * 1e18 - }); - - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: true, - kicker: _lender, - bondSize: 0.195342779771472726 * 1e18, - bondFactor: 0.01 * 1e18, - kickTime: block.timestamp, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 328.175870016074179200 * 1e18, - debtInAuction: 19.778456451861613481 * 1e18, - thresholdPrice: 9.889228225930806740 * 1e18, - neutralPrice: 10.255495938002318100 * 1e18 - }) - ); - _assertKicker({ - kicker: _lender, - claimable: 0, - locked: 0.195342779771472726 * 1e18 - }); - - _repayAndSettleAuction({ - from: _borrower, - borrower: _borrower, - amount: 2 * 1e18, - repaid: 2 * 1e18, - collateral: 2 * 1e18, - newLup: 9.721295865031779605 * 1e18 - }); - - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 8.889228225930806741 * 1e18, - neutralPrice: 0 - }) - ); - _assertKicker({ - kicker: _lender, - claimable: 0.195342779771472726 * 1e18, - locked: 0 - }); - - // Skip to make borrower undercollateralized again - skip(750 days); - - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 19.500754673204780612 * 1e18, - borrowerCollateral: 2 * 1e18, - borrowert0Np: 9.254718877190426163 * 1e18, - borrowerCollateralization: 0.997017400397270737 * 1e18 - }); - - // Kick method only emit Kick event and doesn't call transfer method when kicker has enough bond amount in claimable - _kick({ - from: _lender, - borrower: _borrower, - debt: 19.720138163278334394 * 1e18, - collateral: 2 * 1e18, - bond: 0.195007546732047806 * 1e18, - transferAmount: 0 - }); - - uint256 snapshot = vm.snapshot(); - - // kicker not saved if partial debt paid only - _repayDebt({ - from: _borrower, - borrower: _borrower, - amountToRepay: 0.0001 * 1e18, - amountRepaid: 0.0001 * 1e18, - collateralToPull: 0, - newLup: 9.721295865031779605 * 1e18 - }); - - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: true, - kicker: address(_lender), - bondSize: 0.195007546732047806 * 1e18, - bondFactor: 0.01 * 1e18, - kickTime: _startTime + 850 days, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 329.321295632797165408 * 1e18, - debtInAuction: 19.720038163278334394 * 1e18, - thresholdPrice: 9.860019081639167197 * 1e18, - neutralPrice: 10.291290488524911419 * 1e18 - }) - ); - - vm.revertTo(snapshot); - - // kicker saved if enough debt paid - _repayDebt({ - from: _borrower, - borrower: _borrower, - amountToRepay: 10 * 1e18, - amountRepaid: 10 * 1e18, - collateralToPull: 0, - newLup: 9.721295865031779605 * 1e18 - }); - - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 4.860069081639167197 * 1e18, - neutralPrice: 0 - }) - ); - - // kicker balance before withdraw auction bonds - assertEq(_quote.balanceOf(_lender), 46_999.804657220228527274 * 1e18); - - // should revert if user without claimable amount tries to withdraw bond - vm.expectRevert(IPoolErrors.InsufficientLiquidity.selector); - _pool.withdrawBonds(_withdrawRecipient, type(uint256).max); - - snapshot = vm.snapshot(); - - changePrank(_lender); - - // should revert if trying to withdraw 0 bond amount - vm.expectRevert(IPoolErrors.InsufficientLiquidity.selector); - _pool.withdrawBonds(_withdrawRecipient, 0); - - // kicker withdraws partial auction bonds and transfer to a different address - vm.expectEmit(true, true, false, true); - emit BondWithdrawn(_lender, _withdrawRecipient, 0.1 * 1e18); - _pool.withdrawBonds(_withdrawRecipient, 0.1 * 1e18); - - // kicker withdraws remaining auction bonds - vm.expectEmit(true, true, false, true); - emit BondWithdrawn(_lender, _lender, 0.095342779771472726 * 1e18); - _pool.withdrawBonds(_lender, type(uint256).max); - - assertEq(_quote.balanceOf(_withdrawRecipient), 0.1 * 1e18); - assertEq(_quote.balanceOf(_lender), 46_999.9 * 1e18); - - vm.revertTo(snapshot); - - // kicker withdraws entire auction bonds - vm.expectEmit(true, true, false, true); - emit BondWithdrawn(_lender, _lender, 0.195342779771472726 * 1e18); - _pool.withdrawBonds(_lender, type(uint256).max); - - assertEq(_quote.balanceOf(_lender), 47_000 * 1e18); - - _assertKicker({ - kicker: _lender, - claimable: 0, - locked: 0 - }); - } - - function testKickAndSaveByPledgeCollateral() external tearDown { - - // Skip to make borrower undercollateralized - skip(100 days); - - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 9.767138988573636287 * 1e18, - neutralPrice: 0 - }) - ); - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 19.534277977147272574 * 1e18, - borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 0.995306391810796636 * 1e18 - }); - - _kick({ - from: _lender, - borrower: _borrower, - debt: 19.778456451861613481 * 1e18, - collateral: 2 * 1e18, - bond: 0.195342779771472726 * 1e18, - transferAmount: 0.195342779771472726 * 1e18 - }); - - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: true, - kicker: _lender, - bondSize: 0.195342779771472726 * 1e18, - bondFactor: 0.01 * 1e18, - kickTime: block.timestamp, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 328.175870016074179200 * 1e18, - debtInAuction: 19.778456451861613481 * 1e18, - thresholdPrice: 9.889228225930806740 * 1e18, - neutralPrice: 10.255495938002318100 * 1e18 - }) - ); - _assertKicker({ - kicker: _lender, - claimable: 0, - locked: 0.195342779771472726 * 1e18 - }); - - _pledgeCollateralAndSettleAuction({ - from: _borrower, - borrower: _borrower, - amount: 2 * 1e18, - collateral: 4 * 1e18 // collateral after auction settled = 2 new pledged + initial 2 collateral pledged - }); - - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 4.944614112965403370 * 1e18, - neutralPrice: 0 - }) - ); - _assertKicker({ - kicker: _lender, - claimable: 0.195342779771472726 * 1e18, - locked: 0 - }); - - // kicker withdraws his auction bonds - changePrank(_lender); - assertEq(_quote.balanceOf(_lender), 46_999.804657220228527274 * 1e18); - - _pool.withdrawBonds(_lender, type(uint256).max); - - assertEq(_quote.balanceOf(_lender), 47_000 * 1e18); - - _assertKicker({ - kicker: _lender, - claimable: 0, - locked: 0 - }); - } - function testKickActiveAuctionReverts() external tearDown { - // Skip to make borrower undercollateralized skip(100 days); @@ -602,7 +282,7 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -614,17 +294,17 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.534277977147272574 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 0.995306391810796636 * 1e18 }); _kick({ from: _lender, borrower: _borrower, - debt: 19.778456451861613481 * 1e18, + debt: 19.534277977147272573 * 1e18, collateral: 2 * 1e18, - bond: 0.195342779771472726 * 1e18, - transferAmount: 0.195342779771472726 * 1e18 + bond: 0.296536979149981005 * 1e18, + transferAmount: 0.296536979149981005 * 1e18 }); _assertAuction( @@ -632,15 +312,15 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.195342779771472726 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.296536979149981005 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 0.195342779771472726 * 1e18, - auctionPrice: 328.175870016074179200 * 1e18, - debtInAuction: 19.778456451861613481 * 1e18, - thresholdPrice: 9.889228225930806740 * 1e18, - neutralPrice: 10.255495938002318100 * 1e18 + referencePrice: 11.249823884323541351 * 1e18, + totalBondEscrowed: 0.296536979149981005 * 1e18, + auctionPrice: 2_879.954914386826585856 * 1e18, + debtInAuction: 19.534277977147272574 * 1e18, + thresholdPrice: 9.767138988573636287 * 1e18, + neutralPrice: 11.249823884323541351 * 1e18 }) ); @@ -658,7 +338,6 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { } function testKickAuctionWithoutCollateralReverts() external tearDown { - // Skip to make borrower undercollateralized skip(100 days); @@ -670,7 +349,7 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -682,36 +361,36 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.534277977147272574 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 0.995306391810796636 * 1e18 }); _kick({ from: _lender, borrower: _borrower, - debt: 19.778456451861613481 * 1e18, + debt: 19.534277977147272573 * 1e18, collateral: 2 * 1e18, - bond: 0.195342779771472726 * 1e18, - transferAmount: 0.195342779771472726 * 1e18 + bond: 0.296536979149981005 * 1e18, + transferAmount: 0.296536979149981005 * 1e18 }); - // skip enough time to take collateral at 0 price - skip(100 days); + // skip enough time to take collateral close to 0 price + skip(70 hours); _take({ from: _lender, borrower: _borrower, maxCollateral: 2 * 1e18, bondChange: 0, - givenAmount: 0, + givenAmount: 18, collateralTaken: 2 * 1e18, isReward: true }); // entire borrower collateral is taken but auction not settled as there's still bad debt _assertBorrower({ borrower: _borrower, - borrowerDebt: 21.425476464349380091 * 1e18, + borrowerDebt: 19.541303552517827759 * 1e18, borrowerCollateral: 0, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 0 }); @@ -738,14 +417,14 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.534277977147272574 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 0.995306391810796636 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 9_853.394241979221645667 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, + borrowert0Np: 11.194764859809874960 * 1e18, borrowerCollateralization: 0.986593617011217057 * 1e18 }); _assertLoans({ @@ -758,10 +437,10 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { _kick({ from: _lender, borrower: _borrower2, - debt: 9_976.561670003961916237 * 1e18, + debt: 9_853.394241979221645666 * 1e18, collateral: 1_000 * 1e18, - bond: 98.533942419792216457 * 1e18, - transferAmount: 98.533942419792216457 * 1e18 + bond: 149.577873638769639523 * 1e18, + transferAmount: 149.577873638769639523 * 1e18 }); _assertLoans({ @@ -774,10 +453,10 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { _kick({ from: _lender, borrower: _borrower, - debt: 19.754038604390179389 * 1e18, + debt: 19.534277977147272573 * 1e18, collateral: 2 * 1e18, - bond: 0.195342779771472726 * 1e18, - transferAmount: 0.195342779771472726 * 1e18 + bond: 0.296536979149981005 * 1e18, + transferAmount: 0.296536979149981005 * 1e18 }); _assertLoans({ @@ -791,8 +470,8 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { lup: 9.721295865031779605 * 1e18, poolSize: 73_114.174951097528944000 * 1e18, pledgedCollateral: 1_002 * 1e18, - encumberedCollateral: 1_028.290450922889736704 * 1e18, - poolDebt: 9_996.315708608352095627 * 1e18, + encumberedCollateral: 1_015.597987863945504486 * 1e18, + poolDebt: 9_872.928519956368918240 * 1e18, actualUtilization: 0.541033613782051282 * 1e18, targetUtilization: 0.999781133426980224 * 1e18, minDebtAmount: 0, @@ -810,7 +489,7 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { from: _lender1, amount: 1 * 1e18, index: _i9_91, - lpAward: 0.993688287401017551 * 1e18, + lpAward: 0.993688394051845486 * 1e18, newLup: 9.721295865031779605 * 1e18 }); @@ -818,11 +497,11 @@ contract ERC20PoolLiquidationsKickTest is ERC20HelperContract { PoolParams({ htp: 0, lup: 9.721295865031779605 * 1e18, - poolSize: 73_115.810705342225439101 * 1e18, + poolSize: 73_115.802858058164606426 * 1e18, pledgedCollateral: 1_002 * 1e18, - encumberedCollateral: 1_028.364405977643667984 * 1e18, - poolDebt: 9_997.034647576329686632 * 1e18, - actualUtilization: 0.100837784413285088 * 1e18, + encumberedCollateral: 1_015.671030071750751166 * 1e18, + poolDebt: 9_873.638584869078854771 * 1e18, + actualUtilization: 0.100677654461506314 * 1e18, targetUtilization: 0.999781133426980224 * 1e18, minDebtAmount: 0, loans: 0, @@ -930,3 +609,62 @@ contract ERC20PoolLiquidationKickFuzzyTest is ERC20FuzzyHelperContract { } } } + +contract ERC20PoolLiquidationKickHighThresholdPriceBorrower is ERC20HelperContract { + address internal _borrower; + address internal _lender; + + function setUp() external { + _startTest(); + + _borrower = makeAddr("borrower"); + _lender = makeAddr("lender"); + + _mintQuoteAndApproveTokens(_lender, 10_000_000 * 1e18); + _mintCollateralAndApproveTokens(_borrower, 4 * 1e18); + } + + function testKickHighThresholdPriceBorrower() external tearDown { + _addInitialLiquidity({ + from: _lender, + amount: 1_000 * 1e18, + index: 1 + }); + + _pledgeCollateral({ + from: _borrower, + borrower: _borrower, + amount: 0.00000105 * 1e18 + }); + + _borrow({ + from: _borrower, + amount: 999 * 1e18, + indexLimit: 7388, + newLup: _priceAt(1) + }); + + for (uint256 i = 0; i < 2000; i++) { + skip(13 hours); + _updateInterest(); + } + + uint256 htp = _poolUtils.htp(address(_pool)); + + // htp is greater than MAX_INFLATED_PRICE + assertTrue(htp > MAX_INFLATED_PRICE); + + // htp is greater than max uint96 value + assertTrue(htp > type(uint96).max); + + // Kick borrower + _kick({ + from: _lender, + borrower: _borrower, + debt: 102_216_005.616368048436296920 * 1e18, + collateral: 0.00000105 * 1e18, + bond: 1_551_673.707198968377320142 * 1e18, + transferAmount: 1_551_673.707198968377320142 * 1e18 + }); + } +} diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsLenderKick.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsLenderKick.t.sol index fc2b976c7..795bc719e 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsLenderKick.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsLenderKick.t.sol @@ -177,9 +177,9 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender1, index: 2500, borrower: _borrower1, - debt: 20_269.471153846153855500 * 1e18, + debt: 20_019.230769230769240000 * 1e18, collateral: 1_000 * 1e18, - bond: 6_005.769230769230772000 * 1e18 + bond: 303.8987273632000937560 * 1e18 }); /******************************/ @@ -192,11 +192,11 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { lup: 3_844.432207828138682757 * 1e18, poolSize: 111_000 * 1e18, pledgedCollateral: 5_000 * 1e18, - encumberedCollateral: 26.101746319376146305 * 1e18, - poolDebt: 100_346.394230769230815500 * 1e18, + encumberedCollateral: 26.036654682669472623 * 1e18, + poolDebt: 100_096.153846153846200000 * 1e18, actualUtilization: 0, targetUtilization: 1e18, - minDebtAmount: 2_508.659855769230770388 * 1e18, + minDebtAmount: 2_502.403846153846155000 * 1e18, loans: 4, maxBorrower: address(_borrower5), interestRate: 0.05 * 1e18, @@ -205,8 +205,8 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { ); // assert balances - no change, bond was covered from deposit - assertEq(_quote.balanceOf(address(_pool)), 17_005.769230769230772000 * 1e18); - assertEq(_quote.balanceOf(_lender1), 42_994.230769230769228000 * 1e18); + assertEq(_quote.balanceOf(address(_pool)), 11_303.898727363200093756 * 1e18); + assertEq(_quote.balanceOf(_lender1), 48_696.101272636799906244 * 1e18); assertEq(_quote.balanceOf(_lender2), 140_000 * 1e18); assertEq(_quote.balanceOf(_borrower1), 20_000 * 1e18); assertEq(_quote.balanceOf(_borrower2), 20_000 * 1e18); @@ -239,7 +239,7 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { _assertKicker({ kicker: _lender1, claimable: 0, - locked: 6_005.769230769230772000 * 1e18 + locked: 303.898727363200093756 * 1e18 }); // assert kicked auction _assertAuction( @@ -247,15 +247,15 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { borrower: _borrower1, active: true, kicker: _lender1, - bondSize: 6_005.769230769230772000 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 303.898727363200093756 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime, - kickMomp: 3_863.654368867279344664 * 1e18, - totalBondEscrowed: 6_005.769230769230772000 * 1e18, - auctionPrice: 123_636.939803752939029248 * 1e18, - debtInAuction: 20_269.471153846153855500 * 1e18, - thresholdPrice: 20.269471153846153855 * 1e18, - neutralPrice: 21.020192307692307702 * 1e18 + referencePrice: 23.058218042862770257 * 1e18, + totalBondEscrowed: 303.898727363200093756 * 1e18, + auctionPrice: 5_902.903818972869185792 * 1e18, + debtInAuction: 20_019.230769230769240000 * 1e18, + thresholdPrice: 20.019230769230769240 * 1e18, + neutralPrice: 23.058218042862770257 * 1e18 }) ); @@ -267,7 +267,7 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { - bond auction is not covered entirely by removed deposit (bucket still contains LP), difference to cover bond is sent by lender */ - // borrower 1 draws more debt from pool, bond size will increase from 6_005.769230769230772000 in prev scenario to 8_708.365384615384619400 + // borrower 1 draws more debt from pool, bond size will increase from 303.8987273632000937560 in prev scenario to 440.653154676640135945 _drawDebt({ from: _borrower1, borrower: _borrower1, @@ -307,9 +307,9 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender3, index: 2500, borrower: _borrower1, - debt: 29_390.733173076923090475 * 1e18, + debt: 29_027.884615384615398000 * 1e18, collateral: 1_000 * 1e18, - bond: 8_708.365384615384619400 * 1e18 + bond: 440.653154676640135945 * 1e18 }); /******************************/ @@ -322,11 +322,11 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { lup: 3_844.432207828138682757 * 1e18, poolSize: 111_000 * 1e18, pledgedCollateral: 5_000 * 1e18, - encumberedCollateral: 28.474336477334401997 * 1e18, - poolDebt: 109_467.656250000000050475 * 1e18, + encumberedCollateral: 28.379953604109725159 * 1e18, + poolDebt: 109_104.807692307692358000 * 1e18, actualUtilization: 0, targetUtilization: 1e18, - minDebtAmount: 2_736.691406250000001262 * 1e18, + minDebtAmount: 2_727.620192307692308950 * 1e18, loans: 4, maxBorrower: address(_borrower5), interestRate: 0.05 * 1e18, @@ -335,10 +335,10 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { ); // assert balances - assertEq(_quote.balanceOf(address(_pool)), 10_708.365384615384619400 * 1e18); // increased with the amount sent to cover bond + assertEq(_quote.balanceOf(address(_pool)), 2_440.653154676640135945 * 1e18); // increased with the amount sent to cover bond assertEq(_quote.balanceOf(_lender1), 49_000 * 1e18); assertEq(_quote.balanceOf(_lender2), 140_000 * 1e18); - assertEq(_quote.balanceOf(_lender3), 141_291.634615384615380600 * 1e18); // decreased with the amount sent to cover bond + assertEq(_quote.balanceOf(_lender3), 149_559.346845323359864055 * 1e18); // decreased with the amount sent to cover bond assertEq(_quote.balanceOf(_borrower1), 29_000 * 1e18); assertEq(_quote.balanceOf(_borrower2), 20_000 * 1e18); assertEq(_quote.balanceOf(_borrower3), 20_000 * 1e18); @@ -370,7 +370,7 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { _assertKicker({ kicker: _lender3, claimable: 0, - locked: 8_708.365384615384619400 * 1e18 + locked: 440.653154676640135945 * 1e18 }); // assert kicked auction _assertAuction( @@ -378,15 +378,15 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { borrower: _borrower1, active: true, kicker: _lender3, - bondSize: 8_708.365384615384619400 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 440.653154676640135945 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime, - kickMomp: 3_863.654368867279344664 * 1e18, - totalBondEscrowed: 8_708.365384615384619400 * 1e18, - auctionPrice: 123_636.939803752939029248 * 1e18, - debtInAuction: 29_390.733173076923090475 * 1e18, - thresholdPrice: 29.390733173076923090 * 1e18, - neutralPrice: 30.631675240384615148 * 1e18 + referencePrice: 33.434416162151016873 * 1e18, + totalBondEscrowed: 440.653154676640135945 * 1e18, + auctionPrice: 8_559.210537510660319488 * 1e18, + debtInAuction: 29_027.884615384615398000 * 1e18, + thresholdPrice: 29.027884615384615398 * 1e18, + neutralPrice: 33.434416162151016873 * 1e18 }) ); } @@ -438,9 +438,9 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender2, index: 2499, borrower: _borrower1, - debt: 35_471.574519230769247125 * 1e18, + debt: 35_033.653846153846170000 * 1e18, collateral: 1_000 * 1e18, - bond: 10_510.096153846153851000 * 1e18 + bond: 531.8227728856001640720 * 1e18 }); /******************************/ @@ -453,11 +453,11 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { lup: 3_844.432207828138682757 * 1e18, poolSize: 121_000 * 1e18, pledgedCollateral: 5_000 * 1e18, - encumberedCollateral: 30.056063249306572459 * 1e18, - poolDebt: 115_548.497596153846207125 * 1e18, + encumberedCollateral: 29.942152885069893516 * 1e18, + poolDebt: 115_110.576923076923130000 * 1e18, actualUtilization: 0, targetUtilization: 1e18, - minDebtAmount: 2_888.712439903846155178 * 1e18, + minDebtAmount: 2_877.764423076923078250 * 1e18, loans: 4, maxBorrower: address(_borrower5), interestRate: 0.05 * 1e18, @@ -466,9 +466,9 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { ); // assert balances - assertEq(_quote.balanceOf(address(_pool)), 16_510.096153846153851000 * 1e18); // increased with the amount sent to cover bond + assertEq(_quote.balanceOf(address(_pool)), 6_531.822772885600164072 * 1e18); // increased with the amount sent to cover bond assertEq(_quote.balanceOf(_lender1), 49_000 * 1e18); - assertEq(_quote.balanceOf(_lender2), 119_489.903846153846149000 * 1e18); // decreased with the amount sent to cover bond + assertEq(_quote.balanceOf(_lender2), 129_468.177227114399835928 * 1e18); // decreased with the amount sent to cover bond assertEq(_quote.balanceOf(_lender3), 150_000 * 1e18); assertEq(_quote.balanceOf(_borrower1), 35_000 * 1e18); assertEq(_quote.balanceOf(_borrower2), 20_000 * 1e18); @@ -495,7 +495,7 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { _assertKicker({ kicker: _lender2, claimable: 0, - locked: 10_510.096153846153851000 * 1e18 + locked: 531.822772885600164072 * 1e18 }); // assert kicked auction _assertAuction( @@ -503,15 +503,15 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { borrower: _borrower1, active: true, kicker: _lender2, - bondSize: 10_510.096153846153851000 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 531.822772885600164072 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime, - kickMomp: 3_863.654368867279344664 * 1e18, - totalBondEscrowed: 10_510.096153846153851000 * 1e18, - auctionPrice: 123_636.939803752939029248 * 1e18, - debtInAuction: 35_471.574519230769247125 * 1e18, - thresholdPrice: 35.471574519230769247 * 1e18, - neutralPrice: 36.969263221153845869 * 1e18 + referencePrice: 40.351881575009847950 * 1e18, + totalBondEscrowed: 531.822772885600164072 * 1e18, + auctionPrice: 10_330.081683202521075200 * 1e18, + debtInAuction: 35_033.653846153846170000 * 1e18, + thresholdPrice: 35.033653846153846170 * 1e18, + neutralPrice: 40.351881575009847950 * 1e18 }) ); } @@ -556,9 +556,9 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender1, index: 2500, borrower: _borrower1, - debt: 20_269.471153846153855500 * 1e18, + debt: 20_019.230769230769240000 * 1e18, collateral: 1_000 * 1e18, - bond: 6_005.769230769230772000 * 1e18 + bond: 303.898727363200093756 * 1e18 }); /******************************/ @@ -571,11 +571,11 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { lup: 3_844.432207828138682757 * 1e18, poolSize: 111_000 * 1e18, pledgedCollateral: 5_000 * 1e18, - encumberedCollateral: 26.101746319376146305 * 1e18, - poolDebt: 100_346.394230769230815500 * 1e18, + encumberedCollateral: 26.036654682669472623 * 1e18, + poolDebt: 100_096.153846153846200000 * 1e18, actualUtilization: 0, targetUtilization: 1e18, - minDebtAmount: 2_508.659855769230770388 * 1e18, + minDebtAmount: 2_502.403846153846155000 * 1e18, loans: 4, maxBorrower: address(_borrower5), interestRate: 0.05 * 1e18, @@ -584,8 +584,8 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { ); // assert balances - no change, bond was covered from deposit - assertEq(_quote.balanceOf(address(_pool)), 17_005.769230769230772000 * 1e18); // increased by amount used to cover auction bond - assertEq(_quote.balanceOf(_lender1), 42_994.230769230769228000 * 1e18); // reduced by amount used to cover auction bond + assertEq(_quote.balanceOf(address(_pool)), 11_303.898727363200093756 * 1e18); // increased by amount used to cover auction bond + assertEq(_quote.balanceOf(_lender1), 48_696.101272636799906244 * 1e18); // reduced by amount used to cover auction bond assertEq(_quote.balanceOf(_lender2), 140_000 * 1e18); assertEq(_quote.balanceOf(_borrower1), 20_000 * 1e18); assertEq(_quote.balanceOf(_borrower2), 20_000 * 1e18); @@ -618,7 +618,7 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { _assertKicker({ kicker: _lender1, claimable: 0, - locked: 6_005.769230769230772000 * 1e18 + locked: 303.898727363200093756 * 1e18 }); // assert kicked auction _assertAuction( @@ -626,15 +626,15 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { borrower: _borrower1, active: true, kicker: _lender1, - bondSize: 6_005.769230769230772000 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 303.898727363200093756 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime, - kickMomp: 3_863.654368867279344664 * 1e18, - totalBondEscrowed: 6_005.769230769230772000 * 1e18, - auctionPrice: 123_636.939803752939029248 * 1e18, - debtInAuction: 20_269.471153846153855500 * 1e18, - thresholdPrice: 20.269471153846153855 * 1e18, - neutralPrice: 21.020192307692307702 * 1e18 + referencePrice: 23.058218042862770257 * 1e18, + totalBondEscrowed: 303.898727363200093756 * 1e18, + auctionPrice: 5_902.903818972869185792 * 1e18, + debtInAuction: 20_019.230769230769240000 * 1e18, + thresholdPrice: 20.019230769230769240 * 1e18, + neutralPrice: 23.058218042862770257 * 1e18 }) ); @@ -665,9 +665,9 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender1, index: 2500, borrower: _borrower1, - debt: 20_269.471153846153855500 * 1e18, + debt: 20_019.230769230769240000 * 1e18, collateral: 1_000 * 1e18, - bond: 6_005.769230769230772000 * 1e18 + bond: 303.898727363200093756 * 1e18 }); (borrower, thresholdPrice) = _pool.loanInfo(1); @@ -689,9 +689,9 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { address head; address next; address prev; - (, , , , , , head, next, prev, ) = _pool.auctionInfo(address(0)); + (, , , , , , head, next, prev) = _pool.auctionInfo(address(0)); assertEq(head, _borrower1); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower1); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower1); assertEq(head, _borrower1); assertEq(next, address(0)); assertEq(prev, address(0)); @@ -701,9 +701,9 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender1, index: 2500, borrower: _borrower5, - debt: 20_269.471153846153855500 * 1e18, + debt: 20_019.230769230769240000 * 1e18, collateral: 1_000 * 1e18, - bond: 6_005.769230769230772000 * 1e18 + bond: 303.898727363200093756 * 1e18 }); (borrower, thresholdPrice) = _pool.loanInfo(1); @@ -722,11 +722,11 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { assertEq(borrower, address(0)); assertEq(thresholdPrice, 0); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower1); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower1); assertEq(head, _borrower1); assertEq(next, _borrower5); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower5); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower5); assertEq(head, _borrower1); assertEq(next, address(0)); assertEq(prev, _borrower1); @@ -736,9 +736,9 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender1, index: 2500, borrower: _borrower4, - debt: 20_269.471153846153855500 * 1e18, + debt: 20_019.230769230769240000 * 1e18, collateral: 1_000 * 1e18, - bond: 6_005.769230769230772000 * 1e18 + bond: 303.898727363200093756 * 1e18 }); (borrower, thresholdPrice) = _pool.loanInfo(1); @@ -757,15 +757,15 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { assertEq(borrower, address(0)); assertEq(thresholdPrice, 0); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower1); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower1); assertEq(head, _borrower1); assertEq(next, _borrower5); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower5); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower5); assertEq(head, _borrower1); assertEq(next, _borrower4); assertEq(prev, _borrower1); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower4); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower4); assertEq(head, _borrower1); assertEq(next, address(0)); assertEq(prev, _borrower5); @@ -775,9 +775,9 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender1, index: 2500, borrower: _borrower3, - debt: 20_269.471153846153855500 * 1e18, + debt: 20_019.230769230769240000 * 1e18, collateral: 1_000 * 1e18, - bond: 6_005.769230769230772000 * 1e18 + bond: 303.898727363200093756 * 1e18 }); (borrower, thresholdPrice) = _pool.loanInfo(1); @@ -796,19 +796,19 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { assertEq(borrower, address(0)); assertEq(thresholdPrice, 0); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower1); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower1); assertEq(head, _borrower1); assertEq(next, _borrower5); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower5); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower5); assertEq(head, _borrower1); assertEq(next, _borrower4); assertEq(prev, _borrower1); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower4); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower4); assertEq(head, _borrower1); assertEq(next, _borrower3); assertEq(prev, _borrower5); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower3); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower3); assertEq(head, _borrower1); assertEq(next, address(0)); assertEq(prev, _borrower4); @@ -818,9 +818,9 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender1, index: 2500, borrower: _borrower2, - debt: 20_269.471153846153855500 * 1e18, + debt: 20_019.230769230769240000 * 1e18, collateral: 1_000 * 1e18, - bond: 6_005.769230769230772000 * 1e18 + bond: 303.898727363200093756 * 1e18 }); (borrower, thresholdPrice) = _pool.loanInfo(1); @@ -839,23 +839,23 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { assertEq(borrower, address(0)); assertEq(thresholdPrice, 0); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower1); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower1); assertEq(head, _borrower1); assertEq(next, _borrower5); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower5); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower5); assertEq(head, _borrower1); assertEq(next, _borrower4); assertEq(prev, _borrower1); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower4); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower4); assertEq(head, _borrower1); assertEq(next, _borrower3); assertEq(prev, _borrower5); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower3); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower3); assertEq(head, _borrower1); assertEq(next, _borrower2); assertEq(prev, _borrower4); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower2); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower2); assertEq(head, _borrower1); assertEq(next, address(0)); assertEq(prev, _borrower3); @@ -867,8 +867,8 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { lup: 3_844.432207828138682757 * 1e18, poolSize: 111_000 * 1e18, pledgedCollateral: 5_000 * 1e18, - encumberedCollateral: 26.362112866202841031 * 1e18, - poolDebt: 101_347.355769230769277500 * 1e18, + encumberedCollateral: 26.036654682669472623 * 1e18, + poolDebt: 100_096.153846153846200000 * 1e18, actualUtilization: 0, targetUtilization: 1e18, minDebtAmount: 0, @@ -888,15 +888,15 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender1, - bondSize: 6_005.769230769230772000 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 303.898727363200093756 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime, - kickMomp: 3_863.654368867279344664 * 1e18, - totalBondEscrowed: 30_028.846153846153860000 * 1e18, + referencePrice: 23.058218042862770257 * 1e18, + totalBondEscrowed: 1_519.493636816000468780 * 1e18, auctionPrice: 0, - debtInAuction: 101_347.355769230769277500 * 1e18, - thresholdPrice: 20.278728733568272609 * 1e18, - neutralPrice: 21.020192307692307702 * 1e18 + debtInAuction: 100_096.153846153846200000 * 1e18, + thresholdPrice: 20.028374057845207515 * 1e18, + neutralPrice: 23.058218042862770257 * 1e18 }) ); @@ -904,7 +904,7 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender1, borrower: _borrower2, maxDepth: 1, - settledDebt: 20_269.471153846153855500 * 1e18 + settledDebt: 20_019.230769230769240000 * 1e18 }); _assertAuction( @@ -915,32 +915,32 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 30_028.846153846153860000 * 1e18, + referencePrice: 0, + totalBondEscrowed: 1_519.493636816000468780 * 1e18, auctionPrice: 0, - debtInAuction: 81_114.914934273090436936 * 1e18, + debtInAuction: 80_113.496231380830061171 * 1e18, thresholdPrice: 0, neutralPrice: 0 }) ); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower1); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower1); assertEq(head, _borrower1); assertEq(next, _borrower5); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower5); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower5); assertEq(head, _borrower1); assertEq(next, _borrower4); assertEq(prev, _borrower1); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower4); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower4); assertEq(head, _borrower1); assertEq(next, _borrower3); assertEq(prev, _borrower5); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower3); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower3); assertEq(head, _borrower1); assertEq(next, address(0)); assertEq(prev, _borrower4); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower2); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower2); assertEq(head, _borrower1); assertEq(next, address(0)); assertEq(prev, address(0)); @@ -951,15 +951,15 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { borrower: _borrower4, active: true, kicker: _lender1, - bondSize: 6_005.769230769230772000 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 303.898727363200093756 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime, - kickMomp: 3_863.654368867279344664 * 1e18, - totalBondEscrowed: 30_028.846153846153860000 * 1e18, + referencePrice: 23.058218042862770257 * 1e18, + totalBondEscrowed: 1_519.493636816000468780 * 1e18, auctionPrice: 0, - debtInAuction: 81_114.914934273090436936 * 1e18, - thresholdPrice: 20.278728733568272609 * 1e18, - neutralPrice: 21.125293269230769068 * 1e18 + debtInAuction: 80_113.496231380830061171 * 1e18, + thresholdPrice: 20.028374057845207515 * 1e18, + neutralPrice: 23.058218042862770257 * 1e18 }) ); @@ -967,7 +967,7 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender1, borrower: _borrower4, maxDepth: 5, - settledDebt: 20_269.471153846153855500 * 1e18 + settledDebt: 20_019.230769230769240000 * 1e18 }); _assertAuction( @@ -978,32 +978,32 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 30_028.846153846153860000 * 1e18, + referencePrice: 0, + totalBondEscrowed: 1_519.493636816000468780 * 1e18, auctionPrice: 0, - debtInAuction: 60_836.186200704817827702 * 1e18, + debtInAuction: 60_085.122173535622545879 * 1e18, thresholdPrice: 0, neutralPrice: 0 }) ); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower1); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower1); assertEq(head, _borrower1); assertEq(next, _borrower5); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower5); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower5); assertEq(head, _borrower1); assertEq(next, _borrower3); assertEq(prev, _borrower1); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower4); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower4); assertEq(head, _borrower1); assertEq(next, address(0)); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower3); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower3); assertEq(head, _borrower1); assertEq(next, address(0)); assertEq(prev, _borrower5); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower2); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower2); assertEq(head, _borrower1); assertEq(next, address(0)); assertEq(prev, address(0)); @@ -1014,15 +1014,15 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { borrower: _borrower1, active: true, kicker: _lender1, - bondSize: 6_005.769230769230772000 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 303.898727363200093756 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime, - kickMomp: 3_863.654368867279344664 * 1e18, - totalBondEscrowed: 30_028.846153846153860000 * 1e18, + referencePrice: 23.058218042862770257 * 1e18, + totalBondEscrowed: 1_519.493636816000468780 * 1e18, auctionPrice: 0, - debtInAuction: 60_836.186200704817827702 * 1e18, - thresholdPrice: 20.278728733568272609 * 1e18, - neutralPrice: 21.020192307692307702 * 1e18 + debtInAuction: 60_085.122173535622545879 * 1e18, + thresholdPrice: 20.028374057845207515 * 1e18, + neutralPrice: 23.058218042862770257 * 1e18 }) ); @@ -1030,7 +1030,7 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender1, borrower: _borrower1, maxDepth: 5, - settledDebt: 20_269.471153846153855500 * 1e18 + settledDebt: 20_019.230769230769240000 * 1e18 }); _assertAuction( @@ -1041,32 +1041,32 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 30_028.846153846153860000 * 1e18, + referencePrice: 0, + totalBondEscrowed: 1_519.493636816000468780 * 1e18, auctionPrice: 0, - debtInAuction: 40_557.457467136545218468 * 1e18, + debtInAuction: 40_056.748115690415030586 * 1e18, thresholdPrice: 0, neutralPrice: 0 }) ); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower1); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower1); assertEq(head, _borrower5); assertEq(next, address(0)); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower5); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower5); assertEq(head, _borrower5); assertEq(next, _borrower3); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower4); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower4); assertEq(head, _borrower5); assertEq(next, address(0)); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower3); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower3); assertEq(head, _borrower5); assertEq(next, address(0)); assertEq(prev, _borrower5); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower2); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower2); assertEq(head, _borrower5); assertEq(next, address(0)); assertEq(prev, address(0)); @@ -1077,15 +1077,15 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { borrower: _borrower5, active: true, kicker: _lender1, - bondSize: 6_005.769230769230772000 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 303.898727363200093756 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime, - kickMomp: 3_863.654368867279344664 * 1e18, - totalBondEscrowed: 30_028.846153846153860000 * 1e18, + referencePrice: 23.058218042862770257 * 1e18, + totalBondEscrowed: 1_519.493636816000468780 * 1e18, auctionPrice: 0, - debtInAuction: 40_557.457467136545218468 * 1e18, - thresholdPrice: 20.278728733568272609 * 1e18, - neutralPrice: 21.230919735576922742 * 1e18 + debtInAuction: 40_056.748115690415030586 * 1e18, + thresholdPrice: 20.028374057845207515 * 1e18, + neutralPrice: 23.058218042862770257 * 1e18 }) ); @@ -1093,7 +1093,7 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender1, borrower: _borrower5, maxDepth: 5, - settledDebt: 20_269.471153846153855500 * 1e18 + settledDebt: 20_019.230769230769240000 * 1e18 }); _assertAuction( @@ -1104,32 +1104,32 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 30_028.846153846153860000 * 1e18, + referencePrice: 0, + totalBondEscrowed: 1_519.493636816000468780 * 1e18, auctionPrice: 0, - debtInAuction: 20_278.728733568272609234 * 1e18, + debtInAuction: 20_028.374057845207515293 * 1e18, thresholdPrice: 0, neutralPrice: 0 }) ); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower1); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower1); assertEq(head, _borrower3); assertEq(next, address(0)); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower5); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower5); assertEq(head, _borrower3); assertEq(next, address(0)); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower4); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower4); assertEq(head, _borrower3); assertEq(next, address(0)); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower3); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower3); assertEq(head, _borrower3); assertEq(next, address(0)); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower2); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower2); assertEq(head, _borrower3); assertEq(next, address(0)); assertEq(prev, address(0)); @@ -1140,15 +1140,15 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { borrower: _borrower3, active: true, kicker: _lender1, - bondSize: 6_005.769230769230772000 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 303.898727363200093756 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime, - kickMomp: 3_863.654368867279344664 * 1e18, - totalBondEscrowed: 30_028.846153846153860000 * 1e18, + referencePrice: 23.058218042862770257 * 1e18, + totalBondEscrowed: 1_519.493636816000468780 * 1e18, auctionPrice: 0, - debtInAuction: 20_278.728733568272609234 * 1e18, - thresholdPrice: 20.278728733568272609 * 1e18, - neutralPrice: 21.125293269230769068 * 1e18 + debtInAuction: 20_028.374057845207515293 * 1e18, + thresholdPrice: 20.028374057845207515 * 1e18, + neutralPrice: 23.058218042862770257 * 1e18 }) ); @@ -1158,7 +1158,7 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { from: _lender1, borrower: _borrower3, maxDepth: 5, - settledDebt: 20_269.471153846153855500 * 1e18 + settledDebt: 20_019.230769230769240000 * 1e18 }); _assertAuction( @@ -1169,8 +1169,8 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 30_028.846153846153860000 * 1e18, + referencePrice: 0, + totalBondEscrowed: 1_519.493636816000468780 * 1e18, auctionPrice: 0, debtInAuction: 0, thresholdPrice: 0, @@ -1178,23 +1178,23 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { }) ); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower1); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower1); assertEq(head, address(0)); assertEq(next, address(0)); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower5); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower5); assertEq(head, address(0)); assertEq(next, address(0)); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower4); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower4); assertEq(head, address(0)); assertEq(next, address(0)); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower3); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower3); assertEq(head, address(0)); assertEq(next, address(0)); assertEq(prev, address(0)); - (, , , , , , head, next, prev, ) = _pool.auctionInfo(_borrower2); + (, , , , , , head, next, prev) = _pool.auctionInfo(_borrower2); assertEq(head, address(0)); assertEq(next, address(0)); assertEq(prev, address(0)); @@ -1204,8 +1204,8 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { PoolParams({ htp: 0, lup: MAX_PRICE, - poolSize: 9_645.701045977641587831 * 1e18, - pledgedCollateral: 4_973.703521110015138686 * 1e18, + poolSize: 10_896.988687385325019536 * 1e18, + pledgedCollateral: 4_974.029127598743052356 * 1e18, encumberedCollateral: 0, poolDebt: 0, actualUtilization: 0, @@ -1227,43 +1227,43 @@ contract ERC20PoolLiquidationsLenderKickAuctionTest is ERC20HelperContract { // assert lender1 as a kicker _assertKicker({ kicker: _lender1, - claimable: 30_028.846153846153860000 * 1e18, + claimable: 1_519.493636816000468780 * 1e18, locked: 0 }); // assert borrowers after settle _assertBorrower({ borrower: _borrower1, borrowerDebt: 0, - borrowerCollateral: 994.750357720674222924 * 1e18, - borrowert0Np: 21.020192307692307702 * 1e18, + borrowerCollateral: 994.816126720381654072 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 0, - borrowerCollateral: 994.751412316543869246 * 1e18, - borrowert0Np: 21.020192307692307702 * 1e18, + borrowerCollateral: 994.816209695351969626 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); _assertBorrower({ borrower: _borrower3, borrowerDebt: 0, - borrowerCollateral: 994.725169378126588635 * 1e18, - borrowert0Np: 21.125293269230769068 * 1e18, + borrowerCollateral: 994.790290743828729516 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); _assertBorrower({ borrower: _borrower4, borrowerDebt: 0, - borrowerCollateral: 994.751412316543869246 * 1e18, - borrowert0Np: 21.125293269230769068 * 1e18, + borrowerCollateral: 994.816209695351969626 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); _assertBorrower({ borrower: _borrower5, borrowerDebt: 0, - borrowerCollateral: 994.725169378126588635 * 1e18, - borrowert0Np: 21.230919735576922742 * 1e18, + borrowerCollateral: 994.790290743828729516 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); } diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsMisc.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsMisc.t.sol index 4298bcb0f..bf934eace 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsMisc.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsMisc.t.sol @@ -106,14 +106,14 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.268509615384615394 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 1.009034539679184679 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 7_987.673076923076926760 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 8.471136974495192174 * 1e18, + borrowert0Np: 9.200228999102245332 * 1e18, borrowerCollateralization: 1.217037273735858713 * 1e18 }); _assertReserveAuction({ @@ -186,7 +186,7 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -198,17 +198,17 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.272843317722413899 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 0.998794730435100100 * 1e18 }); _kick({ from: _lender, borrower: _borrower, - debt: 19.489662805046791054 * 1e18, + debt: 19.272843317722413898 * 1e18, collateral: 2 * 1e18, - bond: 0.192728433177224139 * 1e18, - transferAmount: 0.192728433177224139 * 1e18 + bond: 0.292568312161539120 * 1e18, + transferAmount: 0.292568312161539120 * 1e18 }); _assertBucket({ @@ -223,15 +223,15 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.192728433177224139 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.292568312161539120 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.721295865031779605 * 1e18, - totalBondEscrowed: 0.192728433177224139 * 1e18, - auctionPrice: 323.783767737736553472 * 1e18, - debtInAuction: 19.489662805046791055 * 1e18, - thresholdPrice: 9.744831402523395527 * 1e18, - neutralPrice: 10.118242741804267296 * 1e18 + referencePrice: 11.099263219668902589 * 1e18, + totalBondEscrowed: 0.292568312161539120 * 1e18, + auctionPrice: 2_841.411384235239062784 * 1e18, + debtInAuction: 19.272843317722413899 * 1e18, + thresholdPrice: 9.636421658861206949 * 1e18, + neutralPrice: 11.099263219668902589 * 1e18 }) ); @@ -275,32 +275,32 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.192728433177224139 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.292568312161539120 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 3 hours, - kickMomp: 9.721295865031779605 * 1e18, - totalBondEscrowed: 0.192728433177224139 * 1e18, - auctionPrice: 80.945941934434138368 * 1e18, - debtInAuction: 19.489662805046791055 * 1e18, - thresholdPrice: 9.744966562937366149 * 1e18, - neutralPrice: 10.118242741804267296 * 1e18 + referencePrice: 11.099263219668902589 * 1e18, + totalBondEscrowed: 0.292568312161539120 * 1e18, + auctionPrice: 31.393457155209254668 * 1e18, + debtInAuction: 19.272843317722413899 * 1e18, + thresholdPrice: 9.636555315636456019 * 1e18, + neutralPrice: 11.099263219668902589 * 1e18 }) ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 19.489933125874732299 * 1e18, + borrowerDebt: 19.273110631272912039 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, - borrowerCollateralization: 0.987669594447545452 * 1e18 + borrowert0Np: 11.096767433127708186 * 1e18, + borrowerCollateralization: 0.998780877385080338 * 1e18 }); _take({ from: _lender, borrower: _borrower, maxCollateral: 2.0 * 1e18, - bondChange: 0.192728433177224139 * 1e18, - givenAmount: 20.854228444685963559 * 1e18, - collateralTaken: 0.257631549479994909 * 1e18, + bondChange: 0.292568312161539120 * 1e18, + givenAmount: 19.722195067961733839 * 1e18, + collateralTaken: 0.628226288377708765 * 1e18, isReward: false }); @@ -313,7 +313,7 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -324,7 +324,7 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { _assertBorrower({ borrower: _borrower, borrowerDebt: 0, - borrowerCollateral: 1.742368450520005091 * 1e18, + borrowerCollateral: 1.371773711622291235 * 1e18, borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); @@ -332,11 +332,11 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { PoolParams({ htp: 7.989580407145861718 * 1e18, lup: 9.721295865031779605 * 1e18, - poolSize: 63_008.829558890303235305 * 1e18, - pledgedCollateral: 1_001.742368450520005091 * 1e18, + poolSize: 63_008.829556315248414267 * 1e18, + pledgedCollateral: 1_001.371773711622291235 * 1e18, encumberedCollateral: 821.863722498661263922 * 1e18, poolDebt: 7_989.580407145861717463 * 1e18, - actualUtilization: 0.121389301029167552 * 1e18, + actualUtilization: 0.121389232097000537 * 1e18, targetUtilization: 0.822758145478171949 * 1e18, minDebtAmount: 798.958040714586171746 * 1e18, loans: 1, @@ -348,7 +348,7 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { _removeLiquidity({ from: _lender, - amount: 8_008.368802555852473042 * 1e18, + amount: 8_008.368802228565193289 * 1e18, index: _i9_72, newLup: 9.624807173121239337 * 1e18, lpRedeem: 8_007.361474606956967924 * 1e18 @@ -364,7 +364,7 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { _removeLiquidity({ from: _lender, - amount: 25_000.037740139097750000 * 1e18, + amount: 25_000.037739117392250000 * 1e18, index: _i9_62, newLup: 9.529276179422528643 * 1e18, lpRedeem: 25_000.000000000000000000 * 1e18 @@ -383,15 +383,15 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { amount: 22_000 * 1e18, index: _i9_52, newLup: 9.529276179422528643 * 1e18, - lpRedeem: 21_999.966788727729901404 * 1e18 + lpRedeem: 21_999.966789626828026872 * 1e18 }); _assertBucket({ index: _i9_52, - lpBalance: 8_000.033211272270098596 * 1e18, + lpBalance: 8_000.033210373171973128 * 1e18, collateral: 0, - deposit: 8_000.045288166917300000 * 1e18, - exchangeRate: 1.000001509605563911 * 1e18 + deposit: 8_000.045286940870700000 * 1e18, + exchangeRate: 1.000001509564695691 * 1e18 }); _assertRemoveAllLiquidityLupBelowHtpRevert({ @@ -405,11 +405,11 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { PoolParams({ htp: 7.989580407145861718 * 1e18, lup: 9.529276179422528643 * 1e18, - poolSize: 8_000.423016195353009887 * 1e18, - pledgedCollateral: 1_001.742368450520005091 * 1e18, + poolSize: 8_000.423014969290972838 * 1e18, + pledgedCollateral: 1_001.371773711622291235 * 1e18, encumberedCollateral: 838.521600516187410670 * 1e18, poolDebt: 7_990.503913730158190391 * 1e18, - actualUtilization: 0.121389301029167552 * 1e18, + actualUtilization: 0.121389232097000537 * 1e18, targetUtilization: 0.822758145478171949 * 1e18, minDebtAmount: 799.050391373015819039 * 1e18, loans: 1, @@ -422,7 +422,7 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 7_990.503913730158190391 * 1e18, borrowerCollateral: 1_000.00 * 1e18, - borrowert0Np: 8.471136974495192174 * 1e18, + borrowert0Np: 9.200228999102245332 * 1e18, borrowerCollateralization: 1.192575121957988603 * 1e18 }); @@ -433,11 +433,11 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { PoolParams({ htp: 7.990503913730158191 * 1e18, lup: 9.529276179422528643 * 1e18, - poolSize: 8_001.213845441144339172 * 1e18, - pledgedCollateral: 1_001.742368450520005091 * 1e18, + poolSize: 8_001.213844211612533894 * 1e18, + pledgedCollateral: 1_001.371773711622291235 * 1e18, encumberedCollateral: 838.521600516187410670 * 1e18, poolDebt: 7_990.503913730158190391 * 1e18, - actualUtilization: 0.383638008977773077 * 1e18, + actualUtilization: 0.383637856267925676 * 1e18, targetUtilization: 0.829403289225492236 * 1e18, minDebtAmount: 799.050391373015819039 * 1e18, loans: 1, @@ -453,7 +453,7 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 8_084.412285638162564830 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 8.471136974495192174 * 1e18, + borrowert0Np: 9.200228999102245332 * 1e18, borrowerCollateralization: 0.000000012349231999 * 1e18 }); @@ -465,11 +465,11 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { PoolParams({ htp: 0, lup: 0.000000099836282890 * 1e18, - poolSize: 8_083.134379679494060567 * 1e18, - pledgedCollateral: 1_001.742368450520005091 * 1e18, - encumberedCollateral: 81_714_595_700.439346767851204401 * 1e18, - poolDebt: 8_158.081492591040321202 * 1e18, - actualUtilization: 0.998661461633463484 * 1e18, + poolSize: 8_083.134377459926771461 * 1e18, + pledgedCollateral: 1_001.371773711622291235 * 1e18, + encumberedCollateral: 80_976_695_562.129442225570824234 * 1e18, + poolDebt: 8_084.412285638162564830 * 1e18, + actualUtilization: 0.998661461786925952 * 1e18, targetUtilization: 0.838521600515840801 * 1e18, minDebtAmount: 0, loans: 0, @@ -492,31 +492,31 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 80.844122856381625648 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 122.724126286659537773 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 10 hours, - kickMomp: 0.000000099836282890 * 1e18, - totalBondEscrowed: 80.844122856381625648 * 1e18, - auctionPrice: 0.535858215296360576 * 1e18, - debtInAuction: 8_158.081492591040321202 * 1e18, - thresholdPrice: 8.158454900996626324 * 1e18, - neutralPrice: 8.573731444741769263 * 1e18 + referencePrice: 9.311653548504757974 * 1e18, + totalBondEscrowed: 122.724126286659537773 * 1e18, + auctionPrice: 2.327913387126189492 * 1e18, + debtInAuction: 8_084.412285638162564830 * 1e18, + thresholdPrice: 8.084782322086612071 * 1e18, + neutralPrice: 9.311653548504757974 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 8_158.454900996626324182 * 1e18, + borrowerDebt: 8_084.782322086612071679 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 8.471136974495192174 * 1e18, - borrowerCollateralization: 0.000000012237155699 * 1e18 + borrowert0Np: 9.200228999102245332 * 1e18, + borrowerCollateralization: 0.000000012348666781 * 1e18 }); _take({ from: _lender, borrower: _borrower2, maxCollateral: 1_000.0 * 1e18, - bondChange: 5.358582152963605760 * 1e18, //TODO: review - givenAmount: 535.858215296360576000 * 1e18, + bondChange: 35.338516445234474376 * 1e18, + givenAmount: 2_327.913387126189492000 * 1e18, collateralTaken: 1_000 * 1e18, isReward: true }); @@ -524,12 +524,12 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { _assertPool( PoolParams({ htp: 0, - lup: 0.000000099836282890 * 1e18, - poolSize: 8_083.501615236504132602 * 1e18, - pledgedCollateral: 1.742368450520005091 * 1e18, - encumberedCollateral: 82_124_923_660.837160770168974387 * 1e18, - poolDebt: 8_199.047110922993196875 * 1e18, - actualUtilization: 0.998661461633463484 * 1e18, + lup: 9.529276179422528643 * 1e18, + poolSize: 8_083.498296802166583218 * 1e18, + pledgedCollateral: 1.371773711622291235 * 1e18, + encumberedCollateral: 607.832887025912931068 * 1e18, + poolDebt: 5_792.207451405657054680 * 1e18, + actualUtilization: 0.998661461786925952 * 1e18, targetUtilization: 0.838521600515840801 * 1e18, minDebtAmount: 0, loans: 0, @@ -540,9 +540,9 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 8_199.047110922993196875 * 1e18, + borrowerDebt: 5_792.207451405657054680 * 1e18, borrowerCollateral: 0, - borrowert0Np: 8.471136974495192174 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 0 }); @@ -556,18 +556,18 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxDepth: 10, - settledDebt: 8_100.565390045132587717 * 1e18 + settledDebt: 5_722.635152359337569948 * 1e18 }); _assertPool( PoolParams({ htp: 0, lup: MAX_PRICE, - poolSize: 551.311957051027493010 * 1e18, - pledgedCollateral: 1.742368450520005091 * 1e18, + poolSize: 2_312.355002439841726602 * 1e18, + pledgedCollateral: 1.371773711622291235 * 1e18, encumberedCollateral: 0, poolDebt: 0, - actualUtilization: 0.998661461633463484 * 1e18, + actualUtilization: 0.998661461786925952 * 1e18, targetUtilization: 0.838521600515840801 * 1e18, minDebtAmount: 0, loans: 0, @@ -606,10 +606,10 @@ contract ERC20PoolLiquidationsMiscTest is ERC20HelperContract { }); _assertBucket({ index: _i9_52, - lpBalance: 8_000.033211272270098596 * 1e18, + lpBalance: 8_000.033210373171973128 * 1e18, collateral: 0, - deposit: 551.311957051027493215 * 1e18, - exchangeRate: 0.068913708542386244 * 1e18 + deposit: 2_312.355002439841725846 * 1e18, + exchangeRate: 0.289043175401015481 * 1e18 }); } } diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsScaled.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsScaled.t.sol index 093c90a3c..f6416a7b4 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsScaled.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsScaled.t.sol @@ -127,7 +127,6 @@ contract ERC20PoolLiquidationsScaledTest is ERC20DSTestPlus { uint8 quotePrecisionDecimals_, uint16 startBucketId_ ) external tearDown { - uint256 boundColPrecision = bound(uint256(collateralPrecisionDecimals_), 6, 18); uint256 boundQuotePrecision = bound(uint256(quotePrecisionDecimals_), 1, 18); uint256 startBucketId = bound(uint256(startBucketId_), 2000, 5388); @@ -217,7 +216,6 @@ contract ERC20PoolLiquidationsScaledTest is ERC20DSTestPlus { if (bucketQuote != 0) _pool.removeQuoteToken(type(uint256).max, startBucketId + i); } - // check bond transfer amount with rounding (uint256 claimableBond, ) = _pool.kickerInfo(_bidder); uint256 bondTransferAmount = claimableBond / _pool.quoteTokenScale(); @@ -238,7 +236,6 @@ contract ERC20PoolLiquidationsScaledTest is ERC20DSTestPlus { uint8 quotePrecisionDecimals_, uint16 startBucketId_ ) external tearDown { - uint256 boundColPrecision = bound(uint256(collateralPrecisionDecimals_), 12, 18); uint256 boundQuotePrecision = bound(uint256(quotePrecisionDecimals_), 1, 18); uint256 startBucketId = bound(uint256(startBucketId_), 1, 7388 - BUCKETS_WITH_DEPOSIT); @@ -316,23 +313,20 @@ contract ERC20PoolLiquidationsScaledTest is ERC20DSTestPlus { uint256 auctionBondFactor, uint256 auctionBondSize, uint256 auctionKickTime, - uint256 auctionKickMomp, + uint256 auctionReferencePrice, uint256 auctionNeutralPrice, , , - , ) = _pool.auctionInfo(_borrower); - assertEq(auctionKicker, kicker); - assertGe(auctionBondFactor, 0.01 * 1e18); - assertLe(auctionBondFactor, 0.3 * 1e18); - assertGt(auctionBondSize, 0); - assertLt(auctionBondSize, _pool.depositSize()); - assertEq(auctionKickTime, _startTime + timeSinceStart); - assertGt(auctionKickMomp, _priceAt(_startBucketId + BUCKETS_WITH_DEPOSIT)); - assertLt(auctionKickMomp, _priceAt(_startBucketId)); - assertGt(auctionNeutralPrice, _priceAt(_startBucketId)); - assertLt(auctionNeutralPrice, Maths.wmul(_priceAt(_startBucketId), 1.1 * 1e18)); + assertEq(auctionKicker, kicker); + assertGe(auctionBondFactor, 0.01 * 1e18); + assertLe(auctionBondFactor, 0.3 * 1e18); + assertGt(auctionBondSize, 0); + assertLt(auctionBondSize, _pool.depositSize()); + assertEq(auctionKickTime, _startTime + timeSinceStart); + assertGt(auctionReferencePrice, _priceAt(_startBucketId + BUCKETS_WITH_DEPOSIT)); + assertGt(auctionNeutralPrice, _priceAt(_startBucketId)); } function _take(uint256 collateralToTake, address bidder) internal { @@ -376,8 +370,8 @@ contract ERC20PoolLiquidationsScaledTest is ERC20DSTestPlus { } // confirm LP were awarded to the kicker - (address kicker, , , uint256 kickTime, uint256 kickMomp, uint256 neutralPrice, , , , ) = _pool.auctionInfo(_borrower); - uint256 auctionPrice = _auctionPrice(kickMomp, neutralPrice, kickTime); + (address kicker, , , uint256 kickTime, uint256 referencePrice, uint256 neutralPrice, , ,) = _pool.auctionInfo(_borrower); + uint256 auctionPrice = _auctionPrice(referencePrice, kickTime); if (auctionPrice < neutralPrice) { uint256 kickerLP = _kickerLP(bucketId); assertGt(kickerLP, lastKickerLP); @@ -447,12 +441,12 @@ contract ERC20PoolLiquidationsScaledTest is ERC20DSTestPlus { uint256 auctionDebt_, uint256 auctionCollateral_ ){ - (, , , uint256 kickTime, uint256 kickMomp, uint256 neutralPrice, , , , ) = _pool.auctionInfo(_borrower); - uint256 lastAuctionPrice = _auctionPrice(kickMomp, neutralPrice, kickTime); + (, , , uint256 kickTime, uint256 referencePrice, , , , ) = _pool.auctionInfo(_borrower); + uint256 lastAuctionPrice = _auctionPrice(referencePrice, kickTime); (uint256 lastAuctionDebt, uint256 lastAuctionCollateral, ) = _poolUtils.borrowerInfo(address(_pool), _borrower); if (secondsToSkip != 0) { skip(secondsToSkip); - auctionPrice_ = _auctionPrice(kickMomp, neutralPrice, kickTime); + auctionPrice_ = _auctionPrice(referencePrice, kickTime); (uint256 auctionDebt, uint256 auctionCollateral, ) = _poolUtils.borrowerInfo(address(_pool), _borrower); // ensure auction price decreases and auction debt increases as time passes assertLt(auctionPrice_, lastAuctionPrice); @@ -473,7 +467,7 @@ contract ERC20PoolLiquidationsScaledTest is ERC20DSTestPlus { } function _kickerLP(uint256 bucketId) internal view returns (uint256) { - (address kicker, , , , , , , , , ) = _pool.auctionInfo(_borrower); + (address kicker, , , , , , , , ) = _pool.auctionInfo(_borrower); (uint256 kickerLP, ) = _pool.lenderInfo(bucketId, kicker); return kickerLP; } diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsSettle.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsSettle.t.sol index 296769888..9ad4e9a1c 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsSettle.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsSettle.t.sol @@ -27,7 +27,7 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { _mintQuoteAndApproveTokens(_lender1, 120_000 * 1e18); _mintCollateralAndApproveTokens(_borrower, 4 * 1e18); - _mintCollateralAndApproveTokens(_borrower2, 1_000 * 1e18); + _mintCollateralAndApproveTokens(_borrower2, 1_001 * 1e18); _mintCollateralAndApproveTokens(_lender1, 4 * 1e18); // Lender adds Quote token accross 5 prices @@ -108,14 +108,14 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.268509615384615394 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 1.009034539679184679 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 7_987.673076923076926760 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 8.471136974495192174 * 1e18, + borrowert0Np: 9.200228999102245332 * 1e18, borrowerCollateralization: 1.217037273735858713 * 1e18 }); _assertReserveAuction({ @@ -150,7 +150,7 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -162,17 +162,17 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 9_853.394241979221645667 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, + borrowert0Np: 11.194764859809874960 * 1e18, borrowerCollateralization: 0.986593617011217057 * 1e18 }); _kick({ from: _lender, borrower: _borrower2, - debt: 9_976.561670003961916237 * 1e18, + debt: 9_853.394241979221645666 * 1e18, collateral: 1_000 * 1e18, - bond: 98.533942419792216457 * 1e18, - transferAmount: 98.533942419792216457 * 1e18 + bond: 149.577873638769639523 * 1e18, + transferAmount: 149.577873638769639523 * 1e18 }); _assertAuction( @@ -180,23 +180,23 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.533942419792216457 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime + 100 days, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.533942419792216457 * 1e18, - auctionPrice: 334.393063846970122880 * 1e18, - debtInAuction: 9_976.561670003961916237 * 1e18, - thresholdPrice: 9.976561670003961916 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 2_905.388282461931028480 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.853394241979221645 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_976.561670003961916237 * 1e18, + borrowerDebt: 9_853.394241979221645667 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.974413448899967463 * 1e18 + borrowert0Np: 11.194764859809874960 * 1e18, + borrowerCollateralization: 0.986593617011217057 * 1e18 }); _assertBucket({ index: _i9_91, @@ -235,23 +235,23 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.533942419792216457 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime + 100 days, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.533942419792216457 * 1e18, - auctionPrice: 0.653111452826113536 * 1e18, - debtInAuction: 9_976.561670003961916237 * 1e18, - thresholdPrice: 9.977074177773911990 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 2.837293244591729520 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.853900422492752583 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_977.074177773911990382 * 1e18, + borrowerDebt: 9_853.900422492752583093 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.974363394700228467 * 1e18 + borrowert0Np: 11.194764859809874960 * 1e18, + borrowerCollateralization: 0.986542937133981323 * 1e18 }); // take partial 800 collateral @@ -259,8 +259,8 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxCollateral: 800 * 1e18, - bondChange: 5.224891622608908288 * 1e18, - givenAmount: 522.489162260890828800 * 1e18, + bondChange: 34.456860650725712362 * 1e18, + givenAmount: 2_269.834595673383616 * 1e18, collateralTaken: 800 * 1e18, isReward: true }); @@ -270,44 +270,44 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 103.758834042401124745 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 184.034734289495351885 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime + 100 days, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 103.758834042401124745 * 1e18, - auctionPrice: 0.653111452826113536 * 1e18, - debtInAuction: 10_158.205099579803908909 * 1e18, - thresholdPrice: 50.791025497899019544 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 184.034734289495351885 * 1e18, + auctionPrice: 2.837293244591729520 * 1e18, + debtInAuction: 7_618.522687470094679893 * 1e18, + thresholdPrice: 38.092613437350473399 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 10_158.205099579803908909 * 1e18, + borrowerDebt: 7_618.522687470094679893 * 1e18, borrowerCollateral: 200 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.191397904841159446 * 1e18 + borrowert0Np: 43.276046239860018335 * 1e18, + borrowerCollateralization: 0.255201599150450493 * 1e18 }); _assertBucket({ index: _i9_91, lpBalance: 2_000 * 1e18, collateral: 0, - deposit: 2_012.736560735960384000 * 1e18, - exchangeRate: 1.006368280367980192 * 1e18 + deposit: 2_012.735939051273346000 * 1e18, + exchangeRate: 1.006367969525636673 * 1e18 }); _assertBucket({ index: _i9_81, lpBalance: 5_000 * 1e18, collateral: 0, - deposit: 5_031.841401839900960000 * 1e18, - exchangeRate: 1.006368280367980192 * 1e18 + deposit: 5_031.839847628183365000 * 1e18, + exchangeRate: 1.006367969525636673 * 1e18 }); _assertBucket({ index: _i9_72, lpBalance: 11_000 * 1e18, collateral: 0, - deposit: 11_070.051084047782112000 * 1e18, - exchangeRate: 1.006368280367980192 * 1e18 + deposit: 11_070.047664782003403000 * 1e18, + exchangeRate: 1.006367969525636673 * 1e18 }); _assertBucket({ index: _i9_62, @@ -322,24 +322,24 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { _assertBorrower({ borrower: _borrower2, - borrowerDebt: 10_162.015140830231868754 * 1e18, + borrowerDebt: 7_621.380169222238377339 * 1e18, borrowerCollateral: 200 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.191326144082827145 * 1e18 + borrowert0Np: 43.276046239860018335 * 1e18, + borrowerCollateralization: 0.255105916492388742 * 1e18 }); _assertBucket({ index: _i9_91, lpBalance: 2_000 * 1e18, collateral: 0, - deposit: 2_012.736560735960384000 * 1e18, - exchangeRate: 1.006368280367980192 * 1e18 + deposit: 2_012.735939051273346000 * 1e18, + exchangeRate: 1.006367969525636673 * 1e18 }); _settle({ from: _lender, borrower: _borrower2, maxDepth: 10, - settledDebt: 10_019.485661146575724663 * 1e18 + settledDebt: 7_514.484899441934449285 * 1e18 }); _assertAuction( @@ -350,8 +350,8 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 103.758834042401124745 * 1e18, + referencePrice: 0, + totalBondEscrowed: 184.034734289495351885 * 1e18, auctionPrice: 0, debtInAuction: 0, thresholdPrice: 0, @@ -362,7 +362,7 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 0, borrowerCollateral: 0, - borrowert0Np: 10.307611531622595991 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); _assertBucket({ @@ -383,8 +383,8 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { index: _i9_72, lpBalance: 11_000 * 1e18, collateral: 0, - deposit: 8_807.556808084119380150 * 1e18, - exchangeRate: 0.800686982553101762 * 1e18 + deposit: 10_525.670272469343333339 * 1e18, + exchangeRate: 0.956879115679031213 * 1e18 }); _assertBucket({ index: _i9_62, @@ -397,7 +397,7 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { PoolParams({ htp: 9.771304290202671377 * 1e18, lup: 9.721295865031779605 * 1e18, - poolSize: 63_807.556808084119380150 * 1e18, + poolSize: 65_525.670272469343333339 * 1e18, pledgedCollateral: 2 * 1e18, encumberedCollateral: 2.010288427770370775 * 1e18, poolDebt: 19.542608580405342754 * 1e18, @@ -432,7 +432,7 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -444,17 +444,17 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 9_853.394241979221645667 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, + borrowert0Np: 11.194764859809874960 * 1e18, borrowerCollateralization: 0.986593617011217057 * 1e18 }); _kick({ from: _lender, borrower: _borrower2, - debt: 9_976.561670003961916237 * 1e18, + debt: 9_853.394241979221645666 * 1e18, collateral: 1_000 * 1e18, - bond: 98.533942419792216457 * 1e18, - transferAmount: 98.533942419792216457 * 1e18 + bond: 149.577873638769639523 * 1e18, + transferAmount: 149.577873638769639523 * 1e18 }); _assertAuction( @@ -462,23 +462,23 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.533942419792216457 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime + 100 days, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.533942419792216457 * 1e18, - auctionPrice: 334.393063846970122880 * 1e18, - debtInAuction: 9_976.561670003961916237 * 1e18, - thresholdPrice: 9.976561670003961916 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 2_905.388282461931028480 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.853394241979221645 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_976.561670003961916237 * 1e18, + borrowerDebt: 9_853.394241979221645667 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.974413448899967463 * 1e18 + borrowert0Np: 11.194764859809874960 * 1e18, + borrowerCollateralization: 0.986593617011217057 * 1e18 }); _assertBucket({ index: _i9_91, @@ -518,30 +518,30 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.533942419792216457 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 73 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.533942419792216457 * 1e18, + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, auctionPrice: 0, - debtInAuction: 9_976.561670003961916237 * 1e18, - thresholdPrice: 9.980303582194898667 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.857089957723356708 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_980.303582194898667002 * 1e18, + borrowerDebt: 9_857.089957723356708150 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.974048112361512224 * 1e18 + borrowert0Np: 11.194764859809874960 * 1e18, + borrowerCollateralization: 0.986223713766031127 * 1e18 }); _settle({ from: _lender, borrower: _borrower2, maxDepth: 10, - settledDebt: 9_840.828245192307696845 * 1e18 + settledDebt: 9_719.336538461538466020 * 1e18 }); _assertAuction( @@ -552,8 +552,8 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 98.533942419792216457 * 1e18, + referencePrice: 0, + totalBondEscrowed: 149.577873638769639523 * 1e18, auctionPrice: 0, debtInAuction: 0, thresholdPrice: 0, @@ -564,29 +564,29 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 0, borrowerCollateral: 0, - borrowert0Np: 10.307611531622595991 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); _assertBucket({ index: _i9_91, lpBalance: 2_000 * 1e18, - collateral: 202.986484470302055715 * 1e18, + collateral: 202.986026776638220827 * 1e18, deposit: 0, - exchangeRate: 1.006527243605609346 * 1e18 + exchangeRate: 1.006524974089276386 * 1e18 }); _assertBucket({ index: _i9_81, lpBalance: 5_000 * 1e18, - collateral: 512.553559942792076265 * 1e18, + collateral: 512.552404237685039184 * 1e18, deposit: 0, - exchangeRate: 1.006527243605609346 * 1e18 + exchangeRate: 1.006524974089276386 * 1e18 }); _assertBucket({ index: _i9_72, lpBalance: 11_000 * 1e18, - collateral: 284.459955586905868020 * 1e18, - deposit: 8_290.291541398584037503 * 1e18, - exchangeRate: 1.005055539219335976 * 1e18 + collateral: 284.461568985676739989 * 1e18, + deposit: 8_290.291541398624686508 * 1e18, + exchangeRate: 1.005056965067230573 * 1e18 }); _assertBucket({ index: _i9_62, @@ -595,9 +595,19 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { deposit: 25_000 * 1e18, exchangeRate: 1 * 1e18 }); + + // borrower can re-open a loan once their previous loan is fully settled + _drawDebt({ + from: _borrower2, + borrower: _borrower2, + amountToBorrow: 5 * 1e18, + limitIndex: _i9_72, + collateralToPledge: 1 * 1e18, + newLup: 9.721295865031779605 * 1e18 + }); } - function testSettleAuctionReverts() external tearDown { + function testSettleAuctionReverts() external { // Borrower2 borrows _borrow({ from: _borrower2, @@ -619,10 +629,10 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { _kick({ from: _lender, borrower: _borrower2, - debt: 9_976.561670003961916237 * 1e18, + debt: 9_853.394241979221645666 * 1e18, collateral: 1_000 * 1e18, - bond: 98.533942419792216457 * 1e18, - transferAmount: 98.533942419792216457 * 1e18 + bond: 149.577873638769639523 * 1e18, + transferAmount: 149.577873638769639523 * 1e18 }); _assertAuction( @@ -630,23 +640,23 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.533942419792216457 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: kickTime, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.533942419792216457 * 1e18, - auctionPrice: 334.393063846970122880 * 1e18, - debtInAuction: 9_976.561670003961916237 * 1e18, - thresholdPrice: 9.976561670003961916 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 2_905.388282461931028480 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.853394241979221645 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_976.561670003961916237 * 1e18, + borrowerDebt: 9_853.394241979221645667 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.974413448899967463 * 1e18 + borrowert0Np: 11.194764859809874960 * 1e18, + borrowerCollateralization: 0.986593617011217057 * 1e18 }); // settle should revert on an kicked auction but 72 hours not passed (there's still debt to settle and collateral to be auctioned) @@ -656,30 +666,30 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { }); // skip ahead so take can be called on the loan - skip(10 hours); + skip(12.5 hours); _assertAuction( AuctionParams({ borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.533942419792216457 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: kickTime, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.533942419792216457 * 1e18, - auctionPrice: 0.653111452826113536 * 1e18, - debtInAuction: 9_976.561670003961916237 * 1e18, - thresholdPrice: 9.977074177773911990 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 1.192934859200383004 * 1e18, + debtInAuction: 9853.394241979221645667 * 1e18, + thresholdPrice: 9.854026971684066190 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_977.074177773911990382 * 1e18, + borrowerDebt: 9_854.026971684066190794 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.974363394700228467 * 1e18 + borrowert0Np: 11.194764859809874960 * 1e18, + borrowerCollateralization: 0.986530267571451282 * 1e18 }); _addLiquidityWithPenalty({ @@ -690,12 +700,12 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { lpAward: 99.987671232876712300 * 1e18, newLup: 9.721295865031779605 * 1e18 }); - + _addLiquidity({ from: _lender1, amount: 100 * 1e18, index: _i9_91, - lpAward: 99.367201799558744044 * 1e18, + lpAward: 99.366617416827728755 * 1e18, newLup: 9.721295865031779605 * 1e18 }); @@ -704,8 +714,8 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxCollateral: 1_000 * 1e18, - bondChange: 6.531114528261135360 * 1e18, - givenAmount: 653.111452826113536000 * 1e18, + bondChange: 18.109156626307515503 * 1e18, + givenAmount: 1_192.934859200383004000 * 1e18, collateralTaken: 1_000 * 1e18, isReward: true }); @@ -738,32 +748,33 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { _assertLenderLpBalance({ lender: _lender1, index: _i9_91, - lpBalance: 99.367201799558744044 * 1e18, - depositTime: _startTime + 100 days + 10 hours + lpBalance: 99.366617416827728755 * 1e18, + depositTime: _startTime + 100 days + 12.5 hours }); // settle to make buckets insolvent // settle should work because there is still debt to settle but no collateral left to auction (even if 72 hours didn't pass from kick) _assertBorrower({ borrower: _borrower2, - borrowerDebt: 10_028.889031920233428709 * 1e18, + borrowerDebt: 8679.201269109990702794 * 1e18, borrowerCollateral: 0, - borrowert0Np: 10.307611531622595991 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 0 }); + assertTrue(block.timestamp - kickTime < 72 hours); // assert auction was kicked less than 72 hours ago // LP forfeited when forgive bad debt should be reflected in BucketBankruptcy event vm.expectEmit(true, true, false, true); - emit BucketBankruptcy(_i9_91, 2_099.367201799558744044 * 1e18); + emit BucketBankruptcy(_i9_91, 2_099.366617416827728755 * 1e18); vm.expectEmit(true, true, false, true); emit BucketBankruptcy(_i9_81, 5_000 * 1e18); _settle({ from: _lender, borrower: _borrower2, maxDepth: 10, - settledDebt: 9_891.935520844277346923 * 1e18 + settledDebt: 8_560.569020353099739628 * 1e18 }); // bucket is insolvent, balances are resetted @@ -785,7 +796,7 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { lender: _lender1, index: _i9_91, lpBalance: 0, - depositTime: _startTime + 100 days + 10 hours + depositTime: _startTime + 100 days + 12.5 hours }); // cannot add liquidity in same block when bucket marked insolvent @@ -830,7 +841,7 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { lender: _lender1, index: _i9_91, lpBalance: 149.668739373743648296 * 1e18, - depositTime: _startTime + 100 days + 10 hours + 1 hours + depositTime: _startTime + 100 days + 12.5 hours + 1 hours }); // bucket is healthy again _assertBucket({ @@ -856,7 +867,7 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { lender: _lender, index: _i9_91, lpBalance: 1_000 * 1e18, - depositTime: _startTime + 100 days + 10 hours + 1 // _i9_91 bucket insolvency time + 1 (since deposit in _i9_52 from bucket was done before _i9_91 target bucket become insolvent) + depositTime: _startTime + 100 days + 12.5 hours + 1 // _i9_91 bucket insolvency time + 1 (since deposit in _i9_52 from bucket was done before _i9_91 target bucket become insolvent) }); _pool.addQuoteToken(1_000 * 1e18, _i9_52, block.timestamp + 1 minutes, false); @@ -866,7 +877,7 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { lender: _lender, index: _i9_91, lpBalance: 2_000 * 1e18, - depositTime: _startTime + 100 days + 10 hours + 1 hours // time of deposit in _i9_52 from bucket (since deposit in _i9_52 from bucket was done after _i9_91 target bucket become insolvent) + depositTime: _startTime + 100 days + 12.5 hours + 1 hours // time of deposit in _i9_52 from bucket (since deposit in _i9_52 from bucket was done after _i9_91 target bucket become insolvent) }); // ensure bucket bankruptcy when moving amounts from an unbalanced bucket leave bucket healthy @@ -874,8 +885,8 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { index: _i9_72, lpBalance: 11_000 * 1e18, collateral: 0 * 1e18, - deposit: 9_036.877963971180232637 * 1e18, - exchangeRate: 0.821534360361016385 * 1e18 + deposit: 9_565.123570257669797761 * 1e18, + exchangeRate: 0.869556688205242709 * 1e18 }); _pool.moveQuoteToken(10000000000 * 1e18, _i9_72, _i9_91, type(uint256).max, false); @@ -905,16 +916,16 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { from: _lender, borrower: _borrower2 }); - + uint256 kickTime = _startTime + 100 days; _kick({ from: _lender, borrower: _borrower2, - debt: 9_976.561670003961916237 * 1e18, + debt: 9_853.394241979221645666 * 1e18, collateral: 1_000 * 1e18, - bond: 98.533942419792216457 * 1e18, - transferAmount: 98.533942419792216457 * 1e18 + bond: 149.577873638769639523 * 1e18, + transferAmount: 149.577873638769639523 * 1e18 }); _assertAuction( @@ -922,23 +933,23 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.533942419792216457 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: kickTime, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.533942419792216457 * 1e18, - auctionPrice: 334.393063846970122880 * 1e18, - debtInAuction: 9_976.561670003961916237 * 1e18, - thresholdPrice: 9.976561670003961916 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 2_905.388282461931028480 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.853394241979221645 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_976.561670003961916237 * 1e18, + borrowerDebt: 9_853.394241979221645667 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.974413448899967463 * 1e18 + borrowert0Np: 11.194764859809874960 * 1e18, + borrowerCollateralization: 0.986593617011217057 * 1e18 }); // skip ahead so take can be called on the loan @@ -949,23 +960,23 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.533942419792216457 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: kickTime, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.533942419792216457 * 1e18, - auctionPrice: 0.653111452826113536 * 1e18, - debtInAuction: 9_976.561670003961916237 * 1e18, - thresholdPrice: 9.977074177773911990 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 2.837293244591729520 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.853900422492752583 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_977.074177773911990382 * 1e18, + borrowerDebt: 9_853.900422492752583093 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.974363394700228467 * 1e18 + borrowert0Np: 11.194764859809874960 * 1e18, + borrowerCollateralization: 0.986542937133981323 * 1e18 }); // add liquidity in same block should be possible as debt was not yet settled / bucket is not yet insolvent @@ -973,7 +984,7 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { from: _lender1, amount: 100 * 1e18, index: _i9_91, - lpAward: 99.367201799558744044 * 1e18, + lpAward: 99.367232491646341844 * 1e18, newLup: 9.721295865031779605 * 1e18 }); @@ -982,8 +993,8 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxCollateral: 1_000 * 1e18, - bondChange: 6.531114528261135360 * 1e18, - givenAmount: 653.111452826113536000 * 1e18, + bondChange: 43.071075813407140453 * 1e18, + givenAmount: 2_837.29324459172952 * 1e18, collateralTaken: 1_000 * 1e18, isReward: true }); @@ -991,34 +1002,34 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { _assertLenderLpBalance({ lender: _lender1, index: _i9_91, - lpBalance: 99.367201799558744044 * 1e18, + lpBalance: 99.367232491646341844 * 1e18, depositTime: _startTime + 100 days + 10 hours }); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 10_028.889031920233428709 * 1e18, + borrowerDebt: 7_059.678253714430204093 * 1e18, borrowerCollateral: 0, - borrowert0Np: 10.307611531622595991 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 0 }); _assertBucket({ index: _i9_91, - lpBalance: 2_099.367201799558744044 * 1e18, + lpBalance: 2_099.367232491646341844 * 1e18, collateral: 0, - deposit: 2_112.736560735960384000 * 1e18, - exchangeRate: 1.006368280367980193 * 1e18 + deposit: 2_112.735939051273346000 * 1e18, + exchangeRate: 1.006367969525636674 * 1e18 }); // LP forfeited when forgive bad debt should be reflected in BucketBankruptcy event vm.expectEmit(true, true, false, true); - emit BucketBankruptcy(_i9_91, 2_099.367201799558744044 * 1e18); + emit BucketBankruptcy(_i9_91, 2_099.367232491646341844 * 1e18); _settle({ from: _lender, borrower: _borrower2, maxDepth: 10, - settledDebt: 9_891.935520844277346923 * 1e18 + settledDebt: 6_963.271989687033445101 * 1e18 }); // bucket is insolvent, balances are resetted @@ -1029,7 +1040,6 @@ contract ERC20PoolLiquidationsSettleTest is ERC20HelperContract { deposit: 0, exchangeRate: 1 * 1e18 }); - } } @@ -1075,62 +1085,50 @@ contract ERC20PoolLiquidationsSettleRegressionTest is ERC20HelperContract { _mintCollateralAndApproveTokens(actor8, type(uint256).max); } - function testSettleAndBankruptcyOnHPBWithTinyDeposit() external { + function test_regression_bankruptcy_on_hpb_with_tiny_deposit() external { + // add liquidity to bucket 2572 changePrank(actor6); _pool.addQuoteToken(2_000_000 * 1e18, 2572, block.timestamp + 100, false); skip(100 days); - ERC20Pool(address(_pool)).drawDebt(actor6, 1000000 * 1e18, 7388, 372.489032271806320214 * 1e18); + + // borrower 6 draws debt and becomes undercollateralized due to interest accrual + ERC20Pool(address(_pool)).drawDebt(actor6, 1_000_000 * 1e18, 7388, 372.489032271806320214 * 1e18); skip(100 days); + // borrower 1 kicks borrower 6 and draws debt before auction 6 is settled changePrank(actor1); - _pool.updateInterest(); _pool.kick(actor6, 7388); skip(100 hours); - ERC20Pool(address(_pool)).drawDebt(actor1, 1000000 * 1e18, 7388, 10066231386838.450530455239517417 * 1e18); + ERC20Pool(address(_pool)).drawDebt(actor1, 1_000_000 * 1e18, 7388, 10_066_231_386_838.450530455239517417 * 1e18); skip(100 days); + // another actor kicks borrower 1 changePrank(actor2); - _pool.updateInterest(); _pool.kick(actor1, 7388); skip(10 days); + // attempt to deposit tiny amount into bucket 2571, creating new HPB changePrank(actor3); + vm.expectRevert(abi.encodeWithSignature('AuctionNotCleared()')); _pool.addQuoteToken(2, 2571, block.timestamp + 100, false); - (uint256 bucketLps, uint256 collateral, , uint256 deposit, ) = _pool.bucketInfo(2571); - assertEq(bucketLps, 2); - assertEq(collateral, 0); - assertEq(deposit, 2); - (uint256 borrowerDebt, uint256 borrowerCollateral, ) = _pool.borrowerInfo(actor1); - assertEq(borrowerDebt, 985_735.245058880968054979 * 1e18); - assertEq(borrowerCollateral, 10066231386838.450530455239517417 * 1e18); - - changePrank(actor8); - _pool.updateInterest(); - vm.expectEmit(true, true, false, true); - emit BucketBankruptcy(2571, 2); - ERC20Pool(address(_pool)).settle(actor1, 1); - - (bucketLps, collateral, , deposit, ) = _pool.bucketInfo(2571); - assertEq(bucketLps, 0); // entire LP removed from bucket 2571 - assertEq(collateral, 0); // no collateral added in bucket 2571 - assertEq(deposit, 0); // entire deposit from bucket 2571 used to settle - (borrowerDebt, borrowerCollateral, ) = _pool.borrowerInfo(actor1); - assertEq(borrowerDebt, 985_735.245058880968054978 * 1e18); // decreased with 1 - assertEq(borrowerCollateral, 10066231386838.450530455239517417 * 1e18); // same as before settle + // Previous test added quote token successfully, then settled auction 1, bankrupting bucket 2571. + // This is not possible because we prevent depositing into bucket when an uncleared auction exists. } - function testSettleWithReserves() external tearDown { + function test_regression_settle_with_reserves() external tearDown { changePrank(actor2); - - ERC20Pool(address(_pool)).updateInterest(); _addInitialLiquidity({ from: actor2, amount: 112_807_891_516.8015826259279868 * 1e18, index: 2572 }); - ERC20Pool(address(_pool)).updateInterest(); + // no reserves + (uint256 reserves, uint256 claimableReserves, , ,) = _poolUtils.poolReservesInfo(address(_pool)); + assertEq(reserves, 0); + assertEq(claimableReserves, 0); + _drawDebtNoLupCheck({ from: actor2, borrower: actor2, @@ -1139,34 +1137,35 @@ contract ERC20PoolLiquidationsSettleRegressionTest is ERC20HelperContract { collateralToPledge: 21_009_851.171858165566322122 * 1e18 }); + // origination fee goes to reserves + (reserves, claimableReserves, , ,) = _poolUtils.poolReservesInfo(address(_pool)); + assertEq(reserves, 54_234_563.229231556141209574 * 1e18); + assertEq(claimableReserves, 0); + // skip some time to make actor2 undercollateralized skip(200 days); + ERC20Pool(address(_pool)).updateInterest(); + // check reserves after interest accrual + (reserves, claimableReserves, , ,) = _poolUtils.poolReservesInfo(address(_pool)); + assertEq(reserves, 289_462_063.392449001089942144 * 1e18); + assertEq(claimableReserves, 0); + // kick actor2 changePrank(actor4); - - ERC20Pool(address(_pool)).updateInterest(); _kick({ from: actor4, borrower: actor2, - debt: 58_679_160_247.182050965227801655 * 1e18, + debt: 58_026_363_656.051471906282127718 * 1e18, collateral: 21_009_851.171858165566322122 * 1e18, - bond: 580_263_636.560514719062821277 * 1e18, - transferAmount: 580_263_636.560514719062821277 * 1e18 - }); - - changePrank(actor1); - - ERC20Pool(address(_pool)).updateInterest(); - _kickReserveAuction({ - from: actor1, - remainingReserves: 642_374_111.754807749608166225 * 1e18, - price: 1_000_000_000 * 1e18, - epoch: 1 + bond: 880_859_922.734477445997454079 * 1e18, + transferAmount: 880_859_922.734477445997454079 * 1e18 }); + // ensure reserves did not increase as result of kick + (reserves, claimableReserves, , ,) = _poolUtils.poolReservesInfo(address(_pool)); + assertEq(reserves, 289_462_063.392449001089942144 * 1e18); + assertEq(claimableReserves, 0); changePrank(actor7); - - ERC20Pool(address(_pool)).updateInterest(); _drawDebtNoLupCheck({ from: actor7, borrower: actor7, @@ -1177,28 +1176,27 @@ contract ERC20PoolLiquidationsSettleRegressionTest is ERC20HelperContract { // skip some time to make actor7 undercollateralized skip(200 days); - - changePrank(actor6); - - ERC20Pool(address(_pool)).updateInterest(); - (uint256 borrowerDebt, , ) = _poolUtils.borrowerInfo(address(_pool), actor2); - assertEq(borrowerDebt, 60_144_029_463.415046012797744619 * 1e18); - - (uint256 reserves, , , ,) = _poolUtils.poolReservesInfo(address(_pool)); - assertEq(reserves, 467_743_959.189518118524102933 * 1e18); + assertEq(borrowerDebt, 59_474_936_428.593370593619524964 * 1e18); + // reserves increase slightly due to interest accrual + (reserves, claimableReserves, , ,) = _poolUtils.poolReservesInfo(address(_pool)); + assertEq(reserves, 289_462_928.777064385704942145 * 1e18); + assertEq(claimableReserves, 0); + // settle auction with reserves + changePrank(actor6); _settle({ from: actor6, borrower: actor2, maxDepth: 2, - settledDebt: 57_093_334_850.248360626382636508 * 1e18 + settledDebt: 56_458_180_321.630022869105202974 * 1e18 }); - (reserves, , , ,) = _poolUtils.poolReservesInfo(address(_pool)); - - assertEq(reserves, 58.746831970548518322 * 1e18); + // almost all the reserves are used to settle debt + (reserves, claimableReserves, , ,) = _poolUtils.poolReservesInfo(address(_pool)); + assertEq(reserves, 58.732475079196632424 * 1e18); + assertEq(claimableReserves, 0); } } @@ -1253,7 +1251,7 @@ contract ERC20PoolLiquidationSettleFuzzyTest is ERC20FuzzyHelperContract { borrower: _borrower, borrowerDebt: 290_278.84615384615398 * 1e18, borrowerCollateral: 100 * 1e18, - borrowert0Np: 3_047.92788461538461679 * 1e18, + borrowert0Np: 3_343.441616215101687356 * 1e18, borrowerCollateralization: 1.026946145846449373 * 1e18 }); @@ -1263,12 +1261,11 @@ contract ERC20PoolLiquidationSettleFuzzyTest is ERC20FuzzyHelperContract { _kick({ from: _kicker, borrower: _borrower, - debt: 310_461.23296586145968703 * 1e18, + debt: 306_628.378237887861419289 * 1e18, collateral: 100 * 1e18, - bond: 3_066.283782378878614193 * 1e18, - transferAmount: 3_066.283782378878614193 * 1e18 + bond: 4_654.723000803723493401 * 1e18, + transferAmount: 4_654.723000803723493401 * 1e18 }); - } function testSettleWithDepositFuzzy(uint256 quoteAmount, uint256 bucketIndex) external { diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsTake.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsTake.t.sol index b7606efa8..568f5dff9 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsTake.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsTake.t.sol @@ -105,14 +105,14 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.268509615384615394 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 1.009034539679184679 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 7_987.673076923076926760 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 8.471136974495192174 * 1e18, + borrowert0Np: 9.200228999102245332 * 1e18, borrowerCollateralization: 1.217037273735858713 * 1e18 }); _assertReserveAuction({ @@ -133,51 +133,6 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { }); } - function testTakeCoolDownPeriod() external tearDown { - - // should revert if there's no auction started - _assertTakeNoAuctionRevert({ - from: _lender, - borrower: _borrower, - maxCollateral: 10 * 1e18 - }); - - /********************/ - /*** Kick Auction ***/ - /********************/ - - _borrow({ - from: _borrower2, - amount: 1_700.0 * 1e18, - indexLimit: _i9_72, - newLup: _p9_72 - }); - - skip(100 days); - - _kick({ - from: _lender, - borrower: _borrower2, - debt: 9_945.738101507554206918 * 1e18, - collateral: 1_000 * 1e18, - bond: 98.229512113654856365 * 1e18, - transferAmount: 98.229512113654856365 * 1e18 - }); - - /********************/ - /*** Take Auction ***/ - /********************/ - - skip(30 minutes); - - // should revert if still in cool down period - _assertTakeAuctionInCooldownRevert({ - from: _lender, - borrower: _borrower2, - maxCollateral: 10 * 1e18 - }); - } - function testTakeLoanColConstraintBpfPosNoResidual() external tearDown { // Increase neutralPrice so it exceeds TP @@ -230,7 +185,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 9_689.307692307692312160* 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, + borrowert0Np: 11.160177532745580804 * 1e18, borrowerCollateralization: 1.003301388885552947 * 1e18 }); @@ -261,7 +216,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -273,34 +228,34 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 9_822.951211365485636463 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, + borrowert0Np: 11.160177532745580804 * 1e18, borrowerCollateralization: 0.989651241857326201 * 1e18 }); _kick({ from: _lender, borrower: _borrower2, - debt: 9_945.738101507554206918 * 1e18, + debt: 9_822.951211365485636462 * 1e18, collateral: 1_000 * 1e18, - bond: 2_946.885363409645690939 * 1e18, - transferAmount: 2_946.885363409645690939 * 1e18 + bond: 149.115738086847591203 * 1e18, + transferAmount: 149.115738086847591203 * 1e18 }); _assertKicker({ kicker: _lender, claimable: 0, - locked: 2_946.885363409645690939 * 1e18 + locked: 149.115738086847591203 * 1e18 }); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_945.738101507554206919 * 1e18, + borrowerDebt: 9_822.951211365485636463 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, - borrowerCollateralization: 0.977433325291186371 * 1e18 + borrowert0Np: 11.160177532745580804 * 1e18, + borrowerCollateralization: 0.989651241857326201 * 1e18 }); _assertReserveAuction({ - reserves: 179.552281242188325468 * 1e18, - claimableReserves : 83.959813435773714795 * 1e18, + reserves: 56.765391100119755012 * 1e18, + claimableReserves : 0, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 @@ -314,11 +269,11 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { lup: 9.721295865031779605 * 1e18, poolSize: 83_219.674636105806588000 * 1e18, pledgedCollateral: 2_002.000000000000000000 * 1e18, - encumberedCollateral: 1_966.791200431324241706 * 1e18, - poolDebt: 19_119.759164133922414841 * 1e18, + encumberedCollateral: 1_954.159641123343178119 * 1e18, + poolDebt: 18_996.964038864342413928 * 1e18, actualUtilization: 0.225749991311399444 * 1e18, targetUtilization: 0.963953858271529038 * 1e18, - minDebtAmount: 1_911.975916413392241484 * 1e18, + minDebtAmount: 1_899.696403886434241393 * 1e18, loans: 1, maxBorrower: address(_borrower), interestRate: 0.045 * 1e18, @@ -330,23 +285,23 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 2_946.885363409645690939 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 149.115738086847591203 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 47000 seconds, - kickMomp: 1505.263728469068226832 * 1e18, - totalBondEscrowed: 2_946.885363409645690939 * 1e18, - auctionPrice: 12.005655124053999200 * 1e18, - debtInAuction: 9_945.738101507554206919 * 1e18, - thresholdPrice: 9.946405146835980073 * 1e18, - neutralPrice: 1_597.054445085392479852 * 1e18 + referencePrice: 11.314108592233961587 * 1e18, + totalBondEscrowed: 149.115738086847591203 * 1e18, + auctionPrice: 0.980964776869723804 * 1e18, + debtInAuction: 9_822.951211365485636463 * 1e18, + thresholdPrice: 9.823610021566400073 * 1e18, + neutralPrice: 11.314108592233961587 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_946.405146835980073930 * 1e18, + borrowerDebt: 9_823.610021566400073017 * 1e18, borrowerCollateral: 1_000.000000000000000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, - borrowerCollateralization: 0.977367774740624830 * 1e18 + borrowert0Np: 11.160177532745580804 * 1e18, + borrowerCollateralization: 0.989584871924882640 * 1e18 }); // BPF Positive, Loan Col constraint @@ -354,8 +309,8 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxCollateral: 1_001 * 1e18, - bondChange: 3_598.602058071496018124 * 1e18, - givenAmount: 12_005.655124053999200000 * 1e18, + bondChange: 14.891378730546973678 * 1e18, + givenAmount: 980.964776869723804000 * 1e18, collateralTaken: 1_000 * 1e18, isReward: true }); @@ -366,93 +321,43 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: address(0xb012341CA6E91C00A290F658fbaA5211F2559fB1), - bondSize: 6_545.487421481141709063 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 164.007116817394564881 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 47000 seconds, - kickMomp: 1_505.263728469068226832 * 1e18, - totalBondEscrowed: 6_545.487421481141709063 * 1e18, - auctionPrice: 12.005655124053999200 * 1e18, - debtInAuction: 2_235.600441131995497105 * 1e18, + referencePrice: 11.314108592233961587 * 1e18, + totalBondEscrowed: 164.007116817394564881 * 1e18, + auctionPrice: 0.980964776869723804 * 1e18, + debtInAuction: 8_857.536623427223243018 * 1e18, thresholdPrice: 0, - neutralPrice: 1_597.054445085392479852 * 1e18 + neutralPrice: 11.314108592233961587 * 1e18 }) ); // Bad debt remains _assertBorrower({ borrower: _borrower2, - borrowerDebt: 2_235.600441131995497105 * 1e18, + borrowerDebt: 8_857.536623427223243018 * 1e18, borrowerCollateral: 0, - borrowert0Np: 1_575.326150647652569911 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 0 }); _assertPool( PoolParams({ htp: 9.155043929439064212 * 1e18, - lup: 9.917184843435912074 * 1e18, - poolSize: 83_220.780269640882398489 * 1e18, + lup: 9.721295865031779605 * 1e18, + poolSize: 83_220.773168797860489236 * 1e18, pledgedCollateral: 1_002.0 * 1e18, - encumberedCollateral: 1_150.422689356386608344 * 1e18, - poolDebt: 11_408.954458429937838016 * 1e18, - actualUtilization: 0.175622917264332252 * 1e18, + encumberedCollateral: 1_854.782622714283711888 * 1e18, + poolDebt: 18_030.890640725165583929 * 1e18, + actualUtilization: 0.175476347926803679 * 1e18, targetUtilization: 0.962794543732489691 * 1e18, - minDebtAmount: 1_140.895445842993783802 * 1e18, + minDebtAmount: 1_803.089064072516558393 * 1e18, loans: 1, maxBorrower: address(_borrower), interestRate: 0.0405 * 1e18, interestRateUpdate: block.timestamp }) ); - - // borrower recollateralizes themselves by pleding collateral - _pledgeCollateral({ - from: _borrower2, - borrower: _borrower2, - amount: 1_000 * 1e18 - }); - - _assertAuction( - AuctionParams({ - borrower: _borrower2, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 6_545.487421481141709063 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 2.235600441131995497 * 1e18, - neutralPrice: 0 - }) - ); - - _assertBorrower({ - borrower: _borrower2, - borrowerDebt: 2_235.600441131995497105 * 1e18, - borrowerCollateral: 1_000.0 * 1e18, - borrowert0Np: 348.242758284751090878 * 1e18, - borrowerCollateralization: 4.436027413921223336 * 1e18 - }); - - _assertPool( - PoolParams({ - htp: 9.155043929439064212 * 1e18, - lup: 9.917184843435912074 * 1e18, - poolSize: 83_220.780269640882398489 * 1e18, - pledgedCollateral: 2_002.0 * 1e18, - encumberedCollateral: 1_150.422689356386608344 * 1e18, - poolDebt: 11_408.954458429937838016 * 1e18, - actualUtilization: 0.175622917264332252 * 1e18, - targetUtilization: 0.962794543732489691 * 1e18, - minDebtAmount: 570.447722921496891901 * 1e18, - loans: 2, - maxBorrower: address(_borrower), - interestRate: 0.0405 * 1e18, - interestRateUpdate: block.timestamp - }) - ); } function testTakeCallerColConstraintBpfPosNoResidual() external tearDown { @@ -507,7 +412,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 9_689.307692307692312160 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, + borrowert0Np: 11.160177532745580804 * 1e18, borrowerCollateralization: 1.003301388885552947 * 1e18 }); @@ -538,7 +443,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -550,34 +455,34 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 9_822.951211365485636463 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, + borrowert0Np: 11.160177532745580804 * 1e18, borrowerCollateralization: 0.989651241857326201 * 1e18 }); _kick({ from: _lender, borrower: _borrower2, - debt: 9_945.738101507554206918 * 1e18, + debt: 9_822.951211365485636462 * 1e18, collateral: 1_000 * 1e18, - bond: 2_946.885363409645690939 * 1e18, - transferAmount: 2_946.885363409645690939 * 1e18 + bond: 149.115738086847591203 * 1e18, + transferAmount: 149.115738086847591203 * 1e18 }); _assertKicker({ kicker: _lender, claimable: 0, - locked: 2_946.885363409645690939 * 1e18 + locked: 149.115738086847591203 * 1e18 }); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_945.738101507554206919 * 1e18, + borrowerDebt: 9_822.951211365485636463 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, - borrowerCollateralization: 0.977433325291186371 * 1e18 + borrowert0Np: 11.160177532745580804 * 1e18, + borrowerCollateralization: 0.989651241857326201 * 1e18 }); _assertReserveAuction({ - reserves: 179.552281242188325468 * 1e18, - claimableReserves : 83.959813435773714795 * 1e18, + reserves: 56.765391100119755012 * 1e18, + claimableReserves : 0, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 @@ -591,11 +496,11 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { lup: 9.721295865031779605 * 1e18, poolSize: 83_219.674636105806588000 * 1e18, pledgedCollateral: 2_002.000000000000000000 * 1e18, - encumberedCollateral: 1_966.779974486190376300 * 1e18, - poolDebt: 19_119.650033399911495437 * 1e18, + encumberedCollateral: 1_954.148487275944809732 * 1e18, + poolDebt: 18_996.855609013749459851 * 1e18, actualUtilization: 0.225749991311399444 * 1e18, targetUtilization: 0.963953858271529038 * 1e18, - minDebtAmount: 1_911.965003339991149544 * 1e18, + minDebtAmount: 1_899.685560901374945985 * 1e18, loans: 1, maxBorrower: address(_borrower), interestRate: 0.045 * 1e18, @@ -607,23 +512,23 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 2_946.885363409645690939 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 149.115738086847591203 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 43000 seconds, - kickMomp: 1505.263728469068226832 * 1e18, - totalBondEscrowed: 2_946.885363409645690939 * 1e18, - auctionPrice: 25.933649477033750336 * 1e18, - debtInAuction: 9_945.738101507554206919 * 1e18, - thresholdPrice: 9.946348375279124882 * 1e18, - neutralPrice: 1_597.054445085392479852 * 1e18 + referencePrice: 11.314108592233961587 * 1e18, + totalBondEscrowed: 149.115738086847591203 * 1e18, + auctionPrice: 1.441757768272869640 * 1e18, + debtInAuction: 9_822.951211365485636463 * 1e18, + thresholdPrice: 9.823553950892962846 * 1e18, + neutralPrice: 11.314108592233961587 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_946.348375279124882461 * 1e18, + borrowerDebt: 9_823.553950892962846875 * 1e18, borrowerCollateral: 1_000.000000000000000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, - borrowerCollateralization: 0.977373353339734632 * 1e18 + borrowert0Np: 11.160177532745580804 * 1e18, + borrowerCollateralization: 0.989590520256481315 * 1e18 }); // BPF Positive, caller collateral is constraint @@ -631,8 +536,8 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxCollateral: 10 * 1e18, - bondChange: 77.051043093949465946 * 1e18, - givenAmount: 259.336494770337503360 * 1e18, + bondChange: 0.218863729578241083 * 1e18, + givenAmount: 14.417577682728696400 * 1e18, collateralTaken: 10.0 * 1e18, isReward: true }); @@ -643,28 +548,27 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: address(0xb012341CA6E91C00A290F658fbaA5211F2559fB1), - bondSize: 3_023.936406503595156885 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 149.334601816425832286 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 43000 seconds, - kickMomp: 1_505.263728469068226832 * 1e18, - totalBondEscrowed: 3_023.936406503595156885 * 1e18, - auctionPrice: 25.933649477033750336 * 1e18, - debtInAuction: 10_460.307309872275586823 * 1e18, - thresholdPrice: 10.565966979668965239 * 1e18, - neutralPrice: 1_597.054445085392479852 * 1e18 + referencePrice: 11.314108592233961587 * 1e18, + totalBondEscrowed: 149.334601816425832286 * 1e18, + auctionPrice: 1.441757768272869640 * 1e18, + debtInAuction: 9_809.355236939812391565 * 1e18, + thresholdPrice: 9.908439633272537769 * 1e18, + neutralPrice: 11.314108592233961587 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 10_460.307309872275586823 * 1e18, + borrowerDebt: 9_809.355236939812391565 * 1e18, borrowerCollateral: 990 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, - borrowerCollateralization: 0.920057377023560467 * 1e18 + borrowert0Np: 11.256613027484040114 * 1e18, + borrowerCollateralization: 0.981112690275436564 * 1e18 }); } - function testTakeCallerColConstraintBpfPosResidual () external tearDown { - + function testTakeCallerColConstraintBpfPosResidual () external tearDown { // Increase neutralPrice so it exceeds TP _addLiquidity({ from: _lender, @@ -715,7 +619,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 9_689.307692307692312160* 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, + borrowert0Np: 11.160177532745580804 * 1e18, borrowerCollateralization: 1.003301388885552947 * 1e18 }); @@ -746,7 +650,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -758,40 +662,40 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 9_822.951211365485636463 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, + borrowert0Np: 11.160177532745580804 * 1e18, borrowerCollateralization: 0.989651241857326201 * 1e18 }); _kick({ from: _lender, borrower: _borrower2, - debt: 9_945.738101507554206918 * 1e18, + debt: 9_822.951211365485636462 * 1e18, collateral: 1_000 * 1e18, - bond: 2_946.885363409645690939 * 1e18, - transferAmount: 2_946.885363409645690939 * 1e18 + bond: 149.115738086847591203 * 1e18, + transferAmount: 149.115738086847591203 * 1e18 }); _assertKicker({ kicker: _lender, claimable: 0, - locked: 2_946.885363409645690939 * 1e18 + locked: 149.115738086847591203 * 1e18 }); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_945.738101507554206919 * 1e18, + borrowerDebt: 9_822.951211365485636463 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, - borrowerCollateralization: 0.977433325291186371 * 1e18 + borrowert0Np: 11.160177532745580804 * 1e18, + borrowerCollateralization: 0.989651241857326201 * 1e18 }); _assertReserveAuction({ - reserves: 179.552281242188325468 * 1e18, - claimableReserves : 83.959813435773714795 * 1e18, + reserves: 56.765391100119755012 * 1e18, + claimableReserves : 0.000000000000000000 * 1e18, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 }); - skip(43000 seconds); // 11.94 hrs + skip(22000 seconds); _assertPool( PoolParams({ @@ -799,15 +703,15 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { lup: 9.721295865031779605 * 1e18, poolSize: 83_219.674636105806588000 * 1e18, pledgedCollateral: 2_002.000000000000000000 * 1e18, - encumberedCollateral: 1_966.779974486190376300 * 1e18, - poolDebt: 19_119.650033399911495437 * 1e18, + encumberedCollateral: 1_954.089930621571444937 * 1e18, + poolDebt: 18_996.286362451719573593 * 1e18, actualUtilization: 0.225749991311399444 * 1e18, targetUtilization: 0.963953858271529038 * 1e18, - minDebtAmount: 1_911.965003339991149544 * 1e18, + minDebtAmount: 1_899.628636245171957359 * 1e18, loans: 1, maxBorrower: address(_borrower), interestRate: 0.045 * 1e18, - interestRateUpdate: block.timestamp - 43000 seconds + interestRateUpdate: block.timestamp - 22000 seconds }) ); _assertAuction( @@ -815,23 +719,23 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 2_946.885363409645690939 * 1e18, - bondFactor: 0.3 * 1e18, - kickTime: block.timestamp - 43000 seconds, - kickMomp: 1505.263728469068226832 * 1e18, - totalBondEscrowed: 2_946.885363409645690939 * 1e18, - auctionPrice: 25.933649477033750336 * 1e18, - debtInAuction: 9_945.738101507554206919 * 1e18, - thresholdPrice: 9.946348375279124882 * 1e18, - neutralPrice: 1_597.054445085392479852 * 1e18 + bondSize: 149.115738086847591203 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 22000 seconds, + referencePrice: 11.314108592233961587 * 1e18, + totalBondEscrowed: 149.115738086847591203 * 1e18, + auctionPrice: 10.886704980656377540 * 1e18, + debtInAuction: 9_822.951211365485636463 * 1e18, + thresholdPrice: 9.823259585107984853 * 1e18, + neutralPrice: 11.314108592233961587 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_946.348375279124882461 * 1e18, + borrowerDebt: 9_823.259585107984853687 * 1e18, borrowerCollateral: 1_000.000000000000000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, - borrowerCollateralization: 0.977373353339734632 * 1e18 + borrowert0Np: 11.160177532745580804 * 1e18, + borrowerCollateralization: 0.989620174526306750 * 1e18 }); // BPF Positive, Caller Col constraint @@ -839,37 +743,36 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxCollateral: 577 * 1e18, - bondChange: 4_445.845186520884185062 * 1e18, - givenAmount: 14_963.715748248473943872 * 1e18, + bondChange: 27.337468146252670459 * 1e18, + givenAmount: 6_281.628773838729840580 * 1e18, collateralTaken: 577 * 1e18, isReward: true }); - // Residual is collateralized, auction is not active + // Residual is collateralized, auction remains active. _assertAuction( AuctionParams({ borrower: _borrower2, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 7_392.730549930529876001 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 0.294851536220032779 * 1e18, - neutralPrice: 0 + active: true, + kicker: _lender, + bondSize: 176.453206233100261662 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 22000 seconds, + referencePrice: 11.314108592233961587 * 1e18, + totalBondEscrowed: 176.453206233100261662 * 1e18, + auctionPrice: 10.886704980656377540 * 1e18, + debtInAuction: 3_653.993019025148320626 * 1e18, + thresholdPrice: 8.638281368853778535 * 1e18, + neutralPrice: 11.314108592233961587 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 124.722199821073865675 * 1e18, + borrowerDebt: 3_653.993019025148320626 * 1e18, borrowerCollateral: 423.000000000000000000 * 1e18, - borrowert0Np: 0.303909165615512483 * 1e18, - borrowerCollateralization: 5_105.158167959369510853 * 1e18 + borrowert0Np: 9.813927120521769770 * 1e18, + borrowerCollateralization: 1.136655711572588218 * 1e18 }); - } function testTakeCallerColConstraintBpfNegResidual () external tearDown { @@ -902,7 +805,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 9_689.307692307692312160 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.275765152019230606 * 1e18, + borrowert0Np: 11.160177532745580804 * 1e18, borrowerCollateralization: 1.003301388885552947 * 1e18 }); @@ -911,10 +814,10 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { _kick({ from: _lender, borrower: _borrower2, - debt: 9_945.738101507554206918 * 1e18, + debt: 9_822.951211365485636462 * 1e18, collateral: 1_000 * 1e18, - bond: 98.229512113654856365 * 1e18, - transferAmount: 98.229512113654856365 * 1e18 + bond: 149.115738086847591203 * 1e18, + transferAmount: 149.115738086847591203 * 1e18 }); _assertAuction( @@ -922,38 +825,38 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.229512113654856365 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 149.115738086847591203 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.229512113654856365 * 1e18, - auctionPrice: 333.359923587916662112 * 1e18, - debtInAuction: 9_945.738101507554206919 * 1e18, - thresholdPrice: 9.945738101507554206 * 1e18, - neutralPrice: 10.417497612122395691 * 1e18 + referencePrice: 11.314108592233961587 * 1e18, + totalBondEscrowed: 149.115738086847591203 * 1e18, + auctionPrice: 2_896.411799611894166272 * 1e18, + debtInAuction: 9_822.951211365485636463 * 1e18, + thresholdPrice: 9.822951211365485636 * 1e18, + neutralPrice: 11.314108592233961587 * 1e18 }) ); _assertKicker({ kicker: _lender, claimable: 0, - locked: 98.229512113654856365 * 1e18 + locked: 149.115738086847591203 * 1e18 }); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_945.738101507554206919 * 1e18, + borrowerDebt: 9_822.951211365485636463 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.275765152019230606 * 1e18, - borrowerCollateralization: 0.977433325291186371 * 1e18 + borrowert0Np: 11.160177532745580804 * 1e18, + borrowerCollateralization: 0.989651241857326201 * 1e18 }); _assertReserveAuction({ - reserves: 152.199485178078897492 * 1e18, - claimableReserves : 102.373050166832495788 * 1e18, + reserves: 29.412595036010327036 * 1e18, + claimableReserves : 0 * 1e18, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 }); - skip(2 hours); + skip(80 minutes); _assertPool( PoolParams({ @@ -961,15 +864,15 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { lup: 9.721295865031779605 * 1e18, poolSize: 73_113.822894306622582000 * 1e18, pledgedCollateral: 1_002 * 1e18, - encumberedCollateral: 1_025.107650389722106875 * 1e18, - poolDebt: 9_965.374762946048672277 * 1e18, + encumberedCollateral: 1_012.473341055493309162 * 1e18, + poolDebt: 9_842.552903857677844743 * 1e18, actualUtilization: 0.539365344551282052 * 1e18, targetUtilization: 0.996698234880015451 * 1e18, - minDebtAmount: 996.537476294604867228 * 1e18, + minDebtAmount: 984.255290385767784474 * 1e18, loans: 1, maxBorrower: address(_borrower), interestRate: 0.045 * 1e18, - interestRateUpdate: block.timestamp - 2 hours + interestRateUpdate: block.timestamp - 80 minutes }) ); _assertAuction( @@ -977,23 +880,23 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.229512113654856365 * 1e18, - bondFactor: 0.01 * 1e18, - kickTime: block.timestamp - 2 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.229512113654856365 * 1e18, - auctionPrice: 166.679961793958331072 * 1e18, - debtInAuction: 9_945.738101507554206919 * 1e18, - thresholdPrice: 9.945840284273233679 * 1e18, - neutralPrice: 10.417497612122395691 * 1e18 + bondSize: 149.115738086847591203 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 80 minutes, + referencePrice: 11.314108592233961587 * 1e18, + totalBondEscrowed: 149.115738086847591203 * 1e18, + auctionPrice: 181.025737475743385344 * 1e18, + debtInAuction: 9_822.951211365485636463 * 1e18, + thresholdPrice: 9.823018492083647863 * 1e18, + neutralPrice: 11.314108592233961587 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_945.840284273233679079 * 1e18, + borrowerDebt: 9_823.018492083647863197 * 1e18, borrowerCollateral: 1_000.000000000000000 * 1e18, - borrowert0Np: 10.275765152019230606 * 1e18, - borrowerCollateralization: 0.977423283219567398 * 1e18 + borrowert0Np: 11.160177532745580804 * 1e18, + borrowerCollateralization: 0.989644463447376554 * 1e18 }); // BPF Negative, Caller collateral constraint @@ -1001,54 +904,53 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxCollateral: 10.0 * 1e18, - bondChange: 16.667996179395833107 * 1e18, - givenAmount: 1_666.799617939583310720 * 1e18, + bondChange: 27.480322232669404372 * 1e18, + givenAmount: 1_810.257374757433853440 * 1e18, collateralTaken: 10.0 * 1e18, isReward: false }); _assertPool( PoolParams({ - htp: 9.767239336407496599 * 1e18, + htp: 9.767205887014990773 * 1e18, lup: 9.721295865031779605 * 1e18, - poolSize: 73_113.913417169507608000 * 1e18, + poolSize: 73_113.882499196138656000 * 1e18, pledgedCollateral: 992.0 * 1e18, - encumberedCollateral: 925.265940856763249328 * 1e18, - poolDebt: 8_994.783964905591719093 * 1e18, - actualUtilization: 0.539426554958980321 * 1e18, - targetUtilization: 0.996698499658312393 * 1e18, - minDebtAmount: 449.739198245279585955 * 1e18, - loans: 2, + encumberedCollateral: 830.497921731842609849 * 1e18, + poolDebt: 8_073.516012449248097864 * 1e18, + actualUtilization: 0.539405362783948025 * 1e18, + targetUtilization: 0.996698410914855915 * 1e18, + minDebtAmount: 807.351601244924809786 * 1e18, + loans: 1, // TODO: is this test still relevant like this? maxBorrower: address(_borrower), interestRate: 0.045 * 1e18, - interestRateUpdate: block.timestamp - 2 hours + interestRateUpdate: block.timestamp - 80 minutes }) ); - // Residual is collateralized, auction is not active + // take recollateralized borrower however once in auction, always in auction... _assertAuction( AuctionParams({ borrower: _borrower2, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 81.561515934259023258 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 9.065908571952299723 * 1e18, - neutralPrice: 0 + active: true, + kicker: _lender, + bondSize: 121.635415854178186831 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 80 minutes, + referencePrice: 11.314108592233961587 * 1e18, + totalBondEscrowed: 121.635415854178186831 * 1e18, + auctionPrice: 181.025737475743385344 * 1e18, + debtInAuction: 8_053.981600675218116317 * 1e18, + thresholdPrice: 8.135334950176987996 * 1e18, + neutralPrice: 11.314108592233961587 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 8_975.249486232776725895 * 1e18, + borrowerDebt: 8_053.981600675218116317 * 1e18, borrowerCollateral: 990.000000000000000000 * 1e18, - borrowert0Np: 9.438566662973887791 * 1e18, - borrowerCollateralization: 1.072291407736791833 * 1e18 + borrowert0Np: 9.242757957291237631 * 1e18, + borrowerCollateralization: 1.194947217854906920 * 1e18 }); - } function testTakeLoanDebtConstraintBpfPosResidual() external tearDown { @@ -1103,7 +1005,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 9_689.307692307692312160* 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, + borrowert0Np: 11.160177532745580804 * 1e18, borrowerCollateralization: 1.003301388885552947 * 1e18 }); @@ -1134,7 +1036,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -1146,40 +1048,40 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 9_822.951211365485636463 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, + borrowert0Np: 11.160177532745580804 * 1e18, borrowerCollateralization: 0.989651241857326201 * 1e18 }); _kick({ from: _lender, borrower: _borrower2, - debt: 9_945.738101507554206918 * 1e18, + debt: 9_822.951211365485636462 * 1e18, collateral: 1_000 * 1e18, - bond: 2_946.885363409645690939 * 1e18, - transferAmount: 2_946.885363409645690939 * 1e18 + bond: 149.115738086847591203 * 1e18, + transferAmount: 149.115738086847591203 * 1e18 }); _assertKicker({ kicker: _lender, claimable: 0, - locked: 2_946.885363409645690939 * 1e18 + locked: 149.115738086847591203 * 1e18 }); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_945.738101507554206919 * 1e18, + borrowerDebt: 9_822.951211365485636463 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, - borrowerCollateralization: 0.977433325291186371 * 1e18 + borrowert0Np: 11.160177532745580804 * 1e18, + borrowerCollateralization: 0.989651241857326201 * 1e18 }); _assertReserveAuction({ - reserves: 179.552281242188325468 * 1e18, - claimableReserves : 83.959813435773714795 * 1e18, + reserves: 56.765391100119755012 * 1e18, + claimableReserves : 0, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 }); - skip(43000 seconds); // 11.94 hrs + skip(22000 seconds); // 6.11s hrs _assertPool( PoolParams({ @@ -1187,15 +1089,15 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { lup: 9.721295865031779605 * 1e18, poolSize: 83_219.674636105806588000 * 1e18, pledgedCollateral: 2_002.000000000000000000 * 1e18, - encumberedCollateral: 1_966.779974486190376300 * 1e18, - poolDebt: 19_119.650033399911495437 * 1e18, + encumberedCollateral: 1_954.089930621571444937 * 1e18, + poolDebt: 18_996.286362451719573593 * 1e18, actualUtilization: 0.225749991311399444 * 1e18, targetUtilization: 0.963953858271529038 * 1e18, - minDebtAmount: 1_911.965003339991149544 * 1e18, + minDebtAmount: 1_899.628636245171957359 * 1e18, loans: 1, maxBorrower: address(_borrower), interestRate: 0.045 * 1e18, - interestRateUpdate: block.timestamp - 43000 seconds + interestRateUpdate: block.timestamp - 22000 seconds }) ); _assertAuction( @@ -1203,23 +1105,23 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 2_946.885363409645690939 * 1e18, - bondFactor: 0.3 * 1e18, - kickTime: block.timestamp - 43000 seconds, - kickMomp: 1505.263728469068226832 * 1e18, - totalBondEscrowed: 2_946.885363409645690939 * 1e18, - auctionPrice: 25.933649477033750336 * 1e18, - debtInAuction: 9_945.738101507554206919 * 1e18, - thresholdPrice: 9.946348375279124882 * 1e18, - neutralPrice: 1_597.054445085392479852 * 1e18 + bondSize: 149.115738086847591203 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 22000 seconds, + referencePrice: 11.314108592233961587 * 1e18, + totalBondEscrowed: 149.115738086847591203 * 1e18, + auctionPrice: 10.886704980656377540 * 1e18, + debtInAuction: 9_822.951211365485636463 * 1e18, + thresholdPrice: 9.823259585107984853 * 1e18, + neutralPrice: 11.314108592233961587 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_946.348375279124882461 * 1e18, + borrowerDebt: 9_823.259585107984853687 * 1e18, borrowerCollateral: 1_000.000000000000000 * 1e18, - borrowert0Np: 1_575.326150647652569911 * 1e18, - borrowerCollateralization: 0.977373353339734632 * 1e18 + borrowert0Np: 11.160177532745580804 * 1e18, + borrowerCollateralization: 0.989620174526306750 * 1e18 }); // BPF Positive, Loan Debt constraint @@ -1227,9 +1129,9 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxCollateral: 1_001 * 1e18, - bondChange: 4_498.564564314381167419 * 1e18, - givenAmount: 15_141.157325863044791651 * 1e18, - collateralTaken: 583.842136806534270091 * 1e18, + bondChange: 43.529168844258845077 * 1e18, + givenAmount: 10_002.172770738542860841 * 1e18, + collateralTaken: 918.751154597329341626 * 1e18, isReward: true }); @@ -1242,8 +1144,8 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 7_445.449927724026858358 * 1e18, + referencePrice: 0, + totalBondEscrowed: 192.644906931106436280 * 1e18, auctionPrice: 0, debtInAuction: 0, thresholdPrice: 0, @@ -1253,7 +1155,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { _assertBorrower({ borrower: _borrower2, borrowerDebt: 0, - borrowerCollateral: 416.157863193465729909 * 1e18, + borrowerCollateral: 81.248845402670658374 * 1e18, borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); @@ -1276,17 +1178,17 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 9_853.394241979221645667 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, + borrowert0Np: 11.194764859809874960 * 1e18, borrowerCollateralization: 0.986593617011217057 * 1e18 }); _kick({ from: _lender, borrower: _borrower2, - debt: 9_976.561670003961916237 * 1e18, + debt: 9_853.394241979221645666 * 1e18, collateral: 1_000 * 1e18, - bond: 98.533942419792216457 * 1e18, - transferAmount: 98.533942419792216457 * 1e18 + bond: 149.577873638769639523 * 1e18, + transferAmount: 149.577873638769639523 * 1e18 }); _assertAuction( @@ -1294,32 +1196,32 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.533942419792216457 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.533942419792216457 * 1e18, - auctionPrice: 334.393063846970122880 * 1e18, - debtInAuction: 9_976.561670003961916237 * 1e18, - thresholdPrice: 9.976561670003961916 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 2_905.388282461931028480 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.853394241979221645 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertKicker({ kicker: _lender, claimable: 0, - locked: 98.533942419792216457 * 1e18 + locked: 149.577873638769639523 * 1e18 }); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_976.561670003961916237 * 1e18, + borrowerDebt: 9_853.394241979221645667 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.974413448899967463 * 1e18 + borrowert0Np: 11.194764859809874960 * 1e18, + borrowerCollateralization: 0.986593617011217057 * 1e18 }); _assertReserveAuction({ - reserves: 152.670996883580244810 * 1e18, - claimableReserves : 102.690444029499747768 * 1e18, + reserves: 29.503568858839974240 * 1e18, + claimableReserves : 0, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 @@ -1327,38 +1229,38 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { uint256 preTakeSnapshot = vm.snapshot(); - skip(364 minutes); + skip(500 minutes); _assertAuction( AuctionParams({ borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.533942419792216457 * 1e18, - bondFactor: 0.01 * 1e18, - kickTime: block.timestamp - 364 minutes, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.533942419792216457 * 1e18, - auctionPrice: 9.977887794379977376 * 1e18, - debtInAuction: 9_976.561670003961916237 * 1e18, - thresholdPrice: 9.976872588243234769 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 500 minutes, + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 5.055481829190032044 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.853816057268096589 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_976.872588243234769567 * 1e18, + borrowerDebt: 9_853.816057268096589430 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.974383082378677738 * 1e18 + borrowert0Np: 11.194764859809874960 * 1e18, + borrowerCollateralization: 0.986551383599395369 * 1e18 }); _take({ from: _lender, borrower: _borrower2, maxCollateral: 1_000 * 1e18, - bondChange: 99.778877943799773760 * 1e18, - givenAmount: 9_977.887794379977376000 * 1e18, + bondChange: 76.743932462179586888 * 1e18, + givenAmount: 5_055.481829190032044 * 1e18, collateralTaken: 1000.0 * 1e18, isReward: true }); @@ -1368,28 +1270,28 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 198.312820363591990217 * 1e18, - bondFactor: 0.01 * 1e18, - kickTime: block.timestamp - 364 minutes, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 198.312820363591990217 * 1e18, - auctionPrice: 9.977887794379977376 * 1e18, - debtInAuction: 797.144752984083601437 * 1e18, + bondSize: 226.321806100949226411 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 500 minutes, + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 226.321806100949226411 * 1e18, + auctionPrice: 5.055481829190032044 * 1e18, + debtInAuction: 4_875.078160540244132430 * 1e18, thresholdPrice: 0, - neutralPrice: 10.449783245217816340 * 1e18 + neutralPrice: 11.34917297836691808 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 797.144752984083601437 * 1e18, + borrowerDebt: 4_875.078160540244132430 * 1e18, borrowerCollateral: 0, - borrowert0Np: 10.307611531622595991 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 0 }); _assertKicker({ kicker: _lender, claimable: 0, - locked: 198.312820363591990217 * 1e18 + locked: 226.321806100949226411 * 1e18 }); vm.revertTo(preTakeSnapshot); @@ -1402,23 +1304,23 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.533942419792216457 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 10 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.533942419792216457 * 1e18, - auctionPrice: 0.653111452826113536 * 1e18, - debtInAuction: 9_976.561670003961916237 * 1e18, - thresholdPrice: 9.977074177773911990 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + referencePrice: 11.34917297836691808 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 2.837293244591729520 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.853900422492752583 * 1e18, + neutralPrice: 11.34917297836691808 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_977.074177773911990382 * 1e18, + borrowerDebt: 9_853.900422492752583093 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.974363394700228467 * 1e18 + borrowert0Np: 11.194764859809874960 * 1e18, + borrowerCollateralization: 0.986542937133981323 * 1e18 }); // partial take for 20 collateral @@ -1427,8 +1329,8 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxCollateral: 20 * 1e18, - bondChange: 0.130622290565222707 * 1e18, - givenAmount: 13.062229056522270720 * 1e18, + bondChange: 0.861421516268142809 * 1e18, + givenAmount: 56.745864891834590400 * 1e18, collateralTaken: 20 * 1e18, isReward: true }); @@ -1438,33 +1340,33 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.664564710357439164 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 150.439295155037782332 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 10 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.664564710357439164 * 1e18, - auctionPrice: 0.653111452826113536 * 1e18, - debtInAuction: 10_662.537763452128781688 * 1e18, - thresholdPrice: 10.880140574951151818 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 150.439295155037782332 * 1e18, + auctionPrice: 2.837293244591729520 * 1e18, + debtInAuction: 9_798.015979117186135514 * 1e18, + thresholdPrice: 9.997975488895087893 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 10_662.537763452128781688 * 1e18, + borrowerDebt: 9_798.015979117186135514 * 1e18, borrowerCollateral: 980 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.893489913853932440 * 1e18 + borrowert0Np: 11.358444866850947120 * 1e18, + borrowerCollateralization: 0.972326435069717785 * 1e18 }); _assertKicker({ kicker: _lender, claimable: 0, - locked: 98.664564710357439164 * 1e18 // locked bond + reward, auction is not yet finished + locked: 150.439295155037782332 * 1e18 // locked bond + reward, auction is not yet finished }); // reserves should increase after take action _assertReserveAuction({ - reserves: 851.125605070547985156 * 1e18, - claimableReserves : 797.715166731277766566 * 1e18, + reserves: 29.562252507398080560 * 1e18, + claimableReserves : 0, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 @@ -1475,8 +1377,8 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxCollateral: 981 * 1e18, - bondChange: 6.400492237695912653 * 1e18, - givenAmount: 640.049223769591265280 * 1e18, + bondChange: 42.209654297138997644 * 1e18, + givenAmount: 2_780.547379699894929600 * 1e18, collateralTaken: 980 * 1e18, isReward: true }); @@ -1486,33 +1388,33 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 105.065056948053351817 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 192.648949452176779976 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 10 hours, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 105.065056948053351817 * 1e18, - auctionPrice: 0.653111452826113536 * 1e18, - debtInAuction: 10_028.889031920233428709 * 1e18, + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 192.648949452176779976 * 1e18, + auctionPrice: 2.837293244591729520 * 1e18, + debtInAuction: 7_059.678253714430204094 * 1e18, thresholdPrice: 0, - neutralPrice: 10.449783245217816340 * 1e18 + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 10_028.889031920233428709 * 1e18, + borrowerDebt: 7_059.678253714430204094 * 1e18, borrowerCollateral: 0, - borrowert0Np: 10.307611531622595991 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 0 }); _assertKicker({ kicker: _lender, claimable: 0, - locked: 105.065056948053351817 * 1e18 // locked bond + reward, auction is not yet finalized + locked: 192.648949452176779976 * 1e18 // locked bond + reward, auction is not yet finalized }); // reserves should increase after take action _assertReserveAuction({ - reserves: 851.125605070547984804 * 1e18, - claimableReserves : 800.883410388937242979 * 1e18, + reserves: 29.562252507398081096 * 1e18, + claimableReserves : 0, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 @@ -1532,15 +1434,15 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { index: 3_696, lpBalance: 2_000 * 1e18, collateral: 0, - deposit: 2_012.736560735960384000 * 1e18, - exchangeRate: 1.006368280367980192 * 1e18 + deposit: 2_012.735939051273346000 * 1e18, + exchangeRate: 1.006367969525636673 * 1e18 }); _settle({ from: _lender, borrower: _borrower2, maxDepth: 10, - settledDebt: 9_891.935520844277346923 * 1e18 + settledDebt: 6_963.271989687033445102 * 1e18 }); _assertAuction( @@ -1551,8 +1453,8 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 105.065056948053351817 * 1e18, + referencePrice: 0, + totalBondEscrowed: 192.648949452176779976 * 1e18, auctionPrice: 0, debtInAuction: 0, thresholdPrice: 0, @@ -1563,12 +1465,12 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 0, borrowerCollateral: 0, - borrowert0Np: 10.307611531622595991 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); _assertKicker({ kicker: _lender, - claimable: 105.065056948053351817 * 1e18, + claimable: 192.648949452176779976 * 1e18, locked: 0 }); _assertBucket({ @@ -1586,23 +1488,23 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { }); _assertBucket({ index: _i9_81, - lpBalance: 0, // bucket is bankrupt + lpBalance: 5_000 * 1e18, collateral: 0, - deposit: 0, - exchangeRate: 1 * 1e18 + deposit: 14.459712357801136539 * 1e18, + exchangeRate: 0.002891942471560228 * 1e18 }); _assertLenderLpBalance({ lender: _lender, index: _i9_81, - lpBalance: 0, // bucket is bankrupt + lpBalance: 5_000 * 1e18, depositTime: _startTime }); _assertBucket({ index: _i9_72, lpBalance: 11_000 * 1e18, collateral: 0, - deposit: 8_936.865546659328965469 * 1e18, - exchangeRate: 0.812442322423575361 * 1e18 + deposit: 11_070.047664782003403 * 1e18, + exchangeRate: 1.006367969525636673 * 1e18 }); _assertLenderLpBalance({ lender: _lender, @@ -1636,12 +1538,13 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { lpBalance: 30_000 * 1e18, depositTime: _startTime }); + // done vm.revertTo(postTakeSnapshot); _assertReserveAuction({ - reserves: 851.125605070547984804 * 1e18, - claimableReserves : 800.883410388937242979 * 1e18, + reserves: 29.562252507398081096 * 1e18, + claimableReserves : 0, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 @@ -1651,10 +1554,10 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxDepth: 0, - settledDebt: 839.502646350469647166 * 1e18 + settledDebt: 29.158481211449497738 * 1e18 }); _assertReserveAuction({ - reserves: 0.000073114629046626 * 1e18, + reserves: 0.000073114623451463 * 1e18, claimableReserves : 0, claimableReservesRemaining: 0, auctionPrice: 0, @@ -1666,7 +1569,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxDepth: 1, - settledDebt: 1_985.250830463506159498 * 1e18 + settledDebt: 1_985.25021726848337055 * 1e18 }); _assertAuction( @@ -1674,28 +1577,28 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 105.065056948053351817 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 192.648949452176779976 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime + 100 days, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 105.065056948053351817 * 1e18, - auctionPrice: 0.653111452826113536 * 1e18, - debtInAuction: 7_165.026939228354106531 * 1e18, + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 192.648949452176779976 * 1e18, + auctionPrice: 2.837293244591729520 * 1e18, + debtInAuction: 5_017.380135270382228461 * 1e18, thresholdPrice: 0, - neutralPrice: 10.449783245217816340 * 1e18 + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 7_165.026939228354106531 * 1e18, + borrowerDebt: 5_017.380135270382228461 * 1e18, borrowerCollateral: 0, - borrowert0Np: 10.307611531622595991 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 0 }); _assertKicker({ kicker: _lender, claimable: 0, - locked: 105.065056948053351817 * 1e18 // locked bond + reward, auction is not yet finalized + locked: 192.648949452176779976 * 1e18 // locked bond + reward, auction is not yet finalized }); // clear remaining debt @@ -1703,7 +1606,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxDepth: 5, - settledDebt: 7_067.182044030301540259 * 1e18 + settledDebt: 4_948.863291207100576814 * 1e18 }); _assertAuction( @@ -1714,8 +1617,8 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 105.065056948053351817 * 1e18, + referencePrice: 0, + totalBondEscrowed: 192.648949452176779976 * 1e18, auctionPrice: 0, debtInAuction: 0, thresholdPrice: 0, @@ -1726,21 +1629,21 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, borrowerDebt: 0, borrowerCollateral: 0, - borrowert0Np: 10.307611531622595991 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); _assertKicker({ kicker: _lender, - claimable: 105.065056948053351817 * 1e18, + claimable: 192.648949452176779976 * 1e18, locked: 0 }); // kicker withdraws his auction bonds - assertEq(_quote.balanceOf(_lender), 46_248.354604754094247543 * 1e18); + assertEq(_quote.balanceOf(_lender), 44_013.128881769500840477 * 1e18); _pool.withdrawBonds(_lender, type(uint256).max); - assertEq(_quote.balanceOf(_lender), 46_353.419661702147599360 * 1e18); + assertEq(_quote.balanceOf(_lender), 44_205.777831221677620453 * 1e18); _assertKicker({ kicker: _lender, @@ -1765,10 +1668,10 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { _kick({ from: _lender, borrower: _borrower2, - debt: 9_976.561670003961916237 * 1e18, + debt: 9_853.394241979221645666 * 1e18, collateral: 1_000 * 1e18, - bond: 98.533942419792216457 * 1e18, - transferAmount: 98.533942419792216457 * 1e18 + bond: 149.577873638769639523 * 1e18, + transferAmount: 149.577873638769639523 * 1e18 }); _assertAuction( @@ -1776,32 +1679,32 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.533942419792216457 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.533942419792216457 * 1e18, - auctionPrice: 334.393063846970122880 * 1e18, - debtInAuction: 9_976.561670003961916237 * 1e18, - thresholdPrice: 9.976561670003961916 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 2_905.388282461931028480 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.853394241979221645 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_976.561670003961916237 * 1e18, + borrowerDebt: 9_853.394241979221645667 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.974413448899967463 * 1e18 + borrowert0Np: 11.194764859809874960 * 1e18, + borrowerCollateralization: 0.986593617011217057 * 1e18 }); _assertKicker({ kicker: _lender, claimable: 0, - locked: 98.533942419792216457 * 1e18 + locked: 149.577873638769639523 * 1e18 }); _assertReserveAuction({ - reserves: 152.670996883580244810 * 1e18, - claimableReserves : 102.690444029499747768 * 1e18, + reserves: 29.503568858839974240 * 1e18, + claimableReserves : 0, claimableReservesRemaining: 0, auctionPrice: 0, timeRemaining: 0 @@ -1818,10 +1721,10 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 98.533942419792216457 * 1e18, + referencePrice: 0, + totalBondEscrowed: 149.577873638769639523 * 1e18, auctionPrice: 0, - debtInAuction: 9_976.561670003961916237 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, thresholdPrice: 9.888301125810259647 * 1e18, neutralPrice: 0 }) @@ -1830,17 +1733,17 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 19.776602251620519295 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.115967548076923081 * 1e18, + borrowert0Np: 11.096767433127708186 * 1e18, borrowerCollateralization: 0.983110823724556080 * 1e18 }); _kick({ from: _lender, borrower: _borrower, - debt: 19.999089026951250136 * 1e18, + debt: 19.776602251620519294 * 1e18, collateral: 2 * 1e18, - bond: 0.197766022516205193 * 1e18, - transferAmount: 0.197766022516205193 * 1e18 + bond: 0.300215543999476476 * 1e18, + transferAmount: 0.300215543999476476 * 1e18 }); _assertAuction( @@ -1848,21 +1751,21 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.197766022516205193 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.300215543999476476 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.731708442308421650 * 1e18, - auctionPrice: 332.246917827224724128 * 1e18, - debtInAuction: 10_120.320801313999710974 * 1e18, - thresholdPrice: 9.999544513475625068 * 1e18, - neutralPrice: 10.382716182100772629 * 1e18 + referencePrice: 11.389378845807642064 * 1e18, + totalBondEscrowed: 149.878089182769115999 * 1e18, + auctionPrice: 2_915.680984526756368384 * 1e18, + debtInAuction: 9_995.402984757347394196 * 1e18, + thresholdPrice: 9.888301125810259647 * 1e18, + neutralPrice: 11.389378845807642064 * 1e18 }) ); _assertKicker({ kicker: _lender, claimable: 0, - locked: 98.731708442308421650 * 1e18 + locked: 149.878089182769115999 * 1e18 }); skip(2 hours); @@ -1880,62 +1783,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { }); } - function testTakeAfterSettleReverts() external tearDown { - // Borrower draws debt - _borrow({ - from: _borrower2, - amount: 1_730 * 1e18, - indexLimit: _i9_72, - newLup: 9.721295865031779605 * 1e18 - }); - - // Skip to make borrower undercollateralized and kick auction - skip(100 days); - _kick({ - from: _lender, - borrower: _borrower2, - debt: 9_976.561670003961916237 * 1e18, - collateral: 1_000 * 1e18, - bond: 98.533942419792216457 * 1e18, - transferAmount: 98.533942419792216457 * 1e18 - }); - - // Take everything - skip(10 hours); - _take({ - from: _lender, - borrower: _borrower2, - maxCollateral: 1_000 * 1e18, - bondChange: 6.531114528261135360 * 1e18, - givenAmount: 653.1114528261135360 * 1e18, - collateralTaken: 1_000 * 1e18, - isReward: true - }); - - // Partially settle the auction, such that it is not removed from queue - _settle({ - from: _lender, - borrower: _borrower2, - maxDepth: 1, - settledDebt: 2_824.753476813975806664 * 1e18 - }); - - // Borrower draws more debt - _drawDebt({ - from: _borrower2, - borrower: _borrower2, - amountToBorrow: 1_000 * 1e18, - limitIndex: _i9_72, - collateralToPledge: 1_000 * 1e18, - newLup: 9.721295865031779605 * 1e18 - }); - - // Take should revert - _assertTakeNoAuctionRevert(_borrower2, _borrower2, 1_000 * 1e18); - } - function testTakeAuctionPriceLtNeutralPrice() external tearDown { - _addLiquidity({ from: _lender1, amount: 1 * 1e18, @@ -1958,68 +1806,96 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { _kick({ from: _lender, borrower: _borrower2, - debt: 9_976.561670003961916237 * 1e18, + debt: 9_853.394241979221645666 * 1e18, collateral: 1_000 * 1e18, - bond: 98.533942419792216457 * 1e18, - transferAmount: 98.533942419792216457 * 1e18 + bond: 149.577873638769639523 * 1e18, + transferAmount: 149.577873638769639523 * 1e18 }); - _assertAuction( AuctionParams({ borrower: _borrower2, active: true, kicker: _lender, - bondSize: 98.533942419792216457 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.818751856078723036 * 1e18, - totalBondEscrowed: 98.533942419792216457 * 1e18, - auctionPrice: 334.393063846970122880 * 1e18, - debtInAuction: 9_976.561670003961916237 * 1e18, - thresholdPrice: 9.976561670003961916 * 1e18, - neutralPrice: 10.449783245217816340 * 1e18 + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 2_905.388282461931028480 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.853394241979221645 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 }) ); - assertEq(_poolUtils.momp(address(_pool)), 9.818751856078723036 * 1e18); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 9_976.561670003961916237 * 1e18, + borrowerDebt: 9_853.394241979221645667 * 1e18, borrowerCollateral: 1_000 * 1e18, - borrowert0Np: 10.307611531622595991 * 1e18, - borrowerCollateralization: 0.974413448899967463 * 1e18 + borrowert0Np: 11.194764859809874960 * 1e18, + borrowerCollateralization: 0.986593617011217057 * 1e18 }); _assertKicker({ kicker: _lender, claimable: 0, - locked: 98.533942419792216457 * 1e18 + locked: 149.577873638769639523 * 1e18 }); - skip(3 hours); + // after 6 hours, auction price should equal neutral price + skip(6 hours); + _assertAuction( + AuctionParams({ + borrower: _borrower2, + active: true, + kicker: _lender, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 6 hours, + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 11.349172978366918080 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.853697947167044034 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 + }) + ); - _assertBucket({ - index: _i9_91, - lpBalance: 2_001 * 1e18, - collateral: 0, - deposit: 2_013.691743633473441469 * 1e18, - exchangeRate: 1.006342700466503469 * 1e18 - }); + // skip another hour, and then take auction below neutral price + skip(1 hours); + _assertAuction( + AuctionParams({ + borrower: _borrower2, + active: true, + kicker: _lender, + bondSize: 149.577873638769639523 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 7 hours, + referencePrice: 11.349172978366918080 * 1e18, + totalBondEscrowed: 149.577873638769639523 * 1e18, + auctionPrice: 8.025077173862374200 * 1e18, + debtInAuction: 9_853.394241979221645667 * 1e18, + thresholdPrice: 9.853748565608429470 * 1e18, + neutralPrice: 11.349172978366918080 * 1e18 + }) + ); + // confirm kicker is rewarded _take({ from: _lender, borrower: _borrower2, maxCollateral: 1_001 * 1e18, - bondChange: 98.533942419792216457 * 1e18, - givenAmount: 10_675.085498940513902727 * 1e18, - collateralTaken: 127.695058936100465256 * 1e18, - isReward: false + bondChange: 121.823399122640329123 * 1e18, + givenAmount: 8_025.0771738623742 * 1e18, + collateralTaken: 1_000 * 1e18, + isReward: true }); + // borrower left with bad debt to be settled _assertBorrower({ borrower: _borrower2, - borrowerDebt: 0, - borrowerCollateral: 872.304941063899534744 * 1e18, + borrowerDebt: 1950.49479086869560036 * 1e18, + borrowerCollateral: 0, borrowert0Np: 0, - borrowerCollateralization: 1 * 1e18 + borrowerCollateralization: 0 }); } @@ -2058,10 +1934,10 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { _kick({ from: _lender, borrower: _borrower2, - debt: 9_945.738101507554206918 * 1e18, + debt: 9_822.951211365485636462 * 1e18, collateral: 1_000 * 1e18, - bond: 2_946.885363409645690939 * 1e18, - transferAmount: 2_946.885363409645690939 * 1e18 + bond: 149.115738086847591203 * 1e18, + transferAmount: 149.115738086847591203 * 1e18 }); skip(43000 seconds); // 11.94 hrs @@ -2069,8 +1945,6 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { // force pool state update _updateInterest(); - (uint256 borrowerDebt, ,) = _poolUtils.borrowerInfo(address(_pool), _borrower2); - (uint256 reservesBeforeTake, , , , ) = _poolUtils.poolReservesInfo(address(_pool)); // BPF Positive, Loan Debt constraint @@ -2078,16 +1952,115 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract { from: _lender, borrower: _borrower2, maxCollateral: 1_001 * 1e18, - bondChange: 4_498.564564314381167419 * 1e18, - givenAmount: 15_141.157325863044791651 * 1e18, - collateralTaken: 583.842136806534270091 * 1e18, + bondChange: 21.886372957824108251 * 1e18, + givenAmount: 1_441.75776827286964 * 1e18, + collateralTaken: 1000 * 1e18, isReward: true }); (uint256 reservesAfterTake, , , , ) = _poolUtils.poolReservesInfo(address(_pool)); - // reserves should only increase by 7% of the borrower debt on first take and settle auction - assertEq(reservesAfterTake, reservesBeforeTake + Maths.floorWmul(borrowerDebt, 0.07 * 1e18)); + // reserves should increase by borrower take penalty + assertGt(reservesAfterTake, reservesBeforeTake); + } +} + +contract ERC20PoolLiquidationsLowPriceCollateralTest is ERC20HelperContract { + + address internal _lender; + address internal _borrower; + uint256 internal _p0_00016 = 0.000016088121329146 * 1e18; + uint256 internal _i0_00016 = 6369; + + function setUp() external { + assertEq(_priceAt(_i0_00016), _p0_00016); + _startTest(); + + _lender = makeAddr("lender"); + _borrower = makeAddr("borrower"); + + _mintQuoteAndApproveTokens(_lender, 1_000_000 * 1e18); + _mintQuoteAndApproveTokens(_borrower, 1_000_000 * 1e18); + + _mintCollateralAndApproveTokens(_borrower, 50_000_000 * 1e18); + + _addInitialLiquidity({ + from: _lender, + amount: 1_000 * 1e18, + index: _i0_00016 + }); + } + + function testTakeRevertsOnZeroPrice() external tearDown { + // Borrower borrows + _drawDebt({ + from: _borrower, + borrower: _borrower, + amountToBorrow: 750 * 1e18, + limitIndex: _i0_00016+1, + collateralToPledge: Maths.wmul(Maths.wdiv(750 * 1e18, _p0_00016), 1.01 * 1e18), + newLup: _p0_00016 + }); + + // Skip to make borrower undercollateralized + skip(100 days); + + _kick({ + from: _lender, + borrower: _borrower, + debt: 761.075765343400230098 * 1e18, + collateral: 47_084_428.598115880943744161 * 1e18, + bond: 11.553388798051207996 * 1e18, + transferAmount: 11.553388798051207996 * 1e18 + }); + + _assertAuction( + AuctionParams({ + borrower: _borrower, + active: true, + kicker: _lender, + bondSize: 11.553388798051207996 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp, + referencePrice: 0.000018617825030991 * 1e18, + totalBondEscrowed: 11.553388798051207996 * 1e18, + auctionPrice: 0.004766163207933696 * 1e18, + debtInAuction: 761.075765343400230098 * 1e18, + thresholdPrice: 0.000016164065021144 * 1e18, + neutralPrice: 0.000018617825030991 * 1e18 + }) + ); + _assertBorrower({ + borrower: _borrower, + borrowerDebt: 761.075765343400230098 * 1e18, + borrowerCollateral: 47_084_428.598115880943744161 * 1e18, + borrowert0Np: 0.000018364525223142 * 1e18, + borrowerCollateralization: 0.995301695959551634 * 1e18 + }); + + // should revert if take occurs at 0 price + skip(71 hours); + _assertAuction( + AuctionParams({ + borrower: _borrower, + active: true, + kicker: _lender, + bondSize: 11.553388798051207996 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: _startTime + 100 days, + referencePrice: 0.000018617825030991 * 1e18, + totalBondEscrowed: 11.553388798051207996 * 1e18, + auctionPrice: 0 * 1e18, + debtInAuction: 761.075765343400230098 * 1e18, + thresholdPrice: 0.000016169961551610 * 1e18, + neutralPrice: 0.000018617825030991 * 1e18 + }) + ); + _assertTakeZeroBidRevert({ + from: _lender, + borrower: _borrower, + maxCollateral: 2_000_0000 * 1e18 + }); } } @@ -2160,24 +2133,24 @@ contract ERC20PoolLiquidationsTakeAndRepayAllDebtInPoolTest is ERC20HelperContra _kick({ from: _kicker, borrower: _borrower, - debt: 104.162540773774892916 * 1e18, + debt: 102.876583480271499176 * 1e18, collateral: 0.067433366047580170 * 1e18, - bond: 1.028765834802714992 * 1e18, - transferAmount: 1.028765834802714992 * 1e18 + bond: 1.561701503695180782 * 1e18, + transferAmount: 1.561701503695180782 * 1e18 }); skip(964); skip(3600 * 3); - + // the calculated repaid amount is with 1 WAD greater than the pool debt // check that take works and doesn't overflow _take({ from: _taker, borrower: _borrower, maxCollateral: 0.067433366047580170 * 1e18, - bondChange: 1.028765834802714992 * 1e18, - givenAmount: 111.455789568155429077 * 1e18, - collateralTaken: 0.010471063560951988 * 1e18, + bondChange: 1.561701503695180782 * 1e18, + givenAmount: 105.275486946083517714 * 1e18, + collateralTaken: 0.023241640918094312 * 1e18, isReward: false }); @@ -2228,7 +2201,7 @@ contract ERC20PoolLiquidationTakeFuzzyTest is ERC20FuzzyHelperContract { borrower: _borrower, borrowerDebt: 290_278.84615384615398 * 1e18, borrowerCollateral: 100 * 1e18, - borrowert0Np: 3_047.92788461538461679 * 1e18, + borrowert0Np: 3_343.441616215101687356 * 1e18, borrowerCollateralization: 1.026946145846449373 * 1e18 }); @@ -2238,23 +2211,31 @@ contract ERC20PoolLiquidationTakeFuzzyTest is ERC20FuzzyHelperContract { _kick({ from: _taker, borrower: _borrower, - debt: 310_461.23296586145968703 * 1e18, + debt: 306_628.378237887861419289 * 1e18, collateral: 100 * 1e18, - bond: 3_066.283782378878614193 * 1e18, - transferAmount: 3_066.283782378878614193 * 1e18 + bond: 4_654.723000803723493401 * 1e18, + transferAmount: 4_654.723000803723493401 * 1e18 }); } function testTakeCollateralFuzzy(uint256 takeAmount, uint256 skipTimeToTake) external tearDown { - takeAmount = bound(takeAmount, 1, 100 * 1e18); skipTimeToTake = bound(skipTimeToTake, 1.1 hours, 71 hours); // skip some time to make auction takeable skip(skipTimeToTake); + (,,,, uint256 auctionPrice, ) = _poolUtils.auctionStatus(address(_pool), _borrower); + + uint256 minCollateralTakeAmount = Maths.max(Maths.wdiv(1, auctionPrice), 1); + + takeAmount = bound(takeAmount, minCollateralTakeAmount, 100 * 1e18); + + uint256 quoteTokenRequired = Maths.ceilWmul(auctionPrice, takeAmount); + + // return when collateral price is too low and quote token required to take that collateral is 0 + if (quoteTokenRequired == 0) return; // calculate and mint quote tokens to buy collateral - (,,,, uint256 auctionPrice, ) = _poolUtils.auctionStatus(address(_pool), _borrower); - _mintQuoteAndApproveTokens(_taker, auctionPrice * takeAmount); + _mintQuoteAndApproveTokens(_taker, quoteTokenRequired); uint256 beforeTakerQuoteBalance = _quote.balanceOf(_taker); diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolPrecision.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolPrecision.t.sol index 94bf7becc..607ed97f2 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolPrecision.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolPrecision.t.sol @@ -241,7 +241,7 @@ contract ERC20PoolPrecisionTest is ERC20DSTestPlus { function testBorrowRepayPrecision( uint8 collateralPrecisionDecimals_, uint8 quotePrecisionDecimals_ - ) external tearDown { + ) external { // setup fuzzy bounds and initialize the pool uint256 boundColPrecision = bound(uint256(collateralPrecisionDecimals_), 1, 18); uint256 boundQuotePrecision = bound(uint256(quotePrecisionDecimals_), 1, 18); @@ -329,11 +329,12 @@ contract ERC20PoolPrecisionTest is ERC20DSTestPlus { uint256 debt = 10_008.653846153846150000 * 1e18; uint256 col = 50 * 1e18; + // 50 collateral @ 3025.9 = 151295, so borrower is 15_116% collateralized _assertBorrower({ borrower: _borrower, borrowerDebt: debt, borrowerCollateral: col, - borrowert0Np: 209.180865384615384535 * 1e18, + borrowert0Np: 229.411561015492614726 * 1e18, borrowerCollateralization: 15.116650694597107214 * 1e18 }); _assertPoolPrices({ @@ -395,7 +396,7 @@ contract ERC20PoolPrecisionTest is ERC20DSTestPlus { borrower: _borrower, borrowerDebt: debt, borrowerCollateral: col, - borrowert0Np: 209.180865384615384535 * 1e18, + borrowert0Np: 114.804959297694401926 * 1e18, borrowerCollateralization: 30.207183159927296805 * 1e18 }); _assertPoolPrices({ diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolQuoteToken.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolQuoteToken.t.sol index 6ecfb0a3b..75a129d05 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolQuoteToken.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolQuoteToken.t.sol @@ -979,7 +979,7 @@ contract ERC20PoolQuoteTokenTest is ERC20HelperContract { borrower: _borrower, borrowerDebt: 89_085.576923076923118000 * 1e18, borrowerCollateral: 30.0 * 1e18, - borrowert0Np: 3_117.995192307692309130 * 1e18, + borrowert0Np: 3_420.302343024644254882 * 1e18, borrowerCollateralization: 1.008888047888587643 * 1e18 }); diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolReserveAuction.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolReserveAuction.t.sol index 456c49a76..6d68900b4 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolReserveAuction.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolReserveAuction.t.sol @@ -88,7 +88,7 @@ contract ERC20PoolReserveAuctionTest is ERC20HelperContract { // kick off a new auction _kickReserveAuction({ from: _bidder, - remainingReserves: 1.411317956425859163 * 1e18, + remainingReserves: 1.425573693359453700 * 1e18, price: 1000000000 * 1e18, epoch: 1 }); @@ -96,22 +96,75 @@ contract ERC20PoolReserveAuctionTest is ERC20HelperContract { skip(60 hours); _assertReserveAuction({ - reserves: 0.000001743377232837 * 1e18, - claimableReserves : 0.000000736933594537 * 1e18, - claimableReservesRemaining: 1.411317956425859163 * 1e18, + reserves: 0.000001006443638300 * 1e18, + claimableReserves : 0, + claimableReservesRemaining: 1.425573693359453700 * 1e18, auctionPrice: 0.000000000867361737 * 1e18, timeRemaining: 43200 }); - assertEq(USDC.balanceOf(address(_pool)), 1_007.854958 * 1e6); - assertEq(USDC.balanceOf(address(_bidder)), 0.014255 * 1e6); // kicker reward - assertEq(AJNA.balanceOf(address(_bidder)), 10 * 1e18); + // taking 0 amount forbidden + vm.expectRevert(IPoolErrors.InvalidAmount.selector); + _pool.takeReserves(0); + // take all reserves + assertEq(USDC.balanceOf(address(_pool)), 1_007.869213 * 1e6); + assertEq(AJNA.balanceOf(address(_bidder)), 10 * 1e18); _pool.takeReserves(10 * 1e18); + assertEq(USDC.balanceOf(address(_pool)), 1_006.443640 * 1e6); + assertEq(USDC.balanceOf(address(_bidder)), 1.425573 * 1e6); + assertEq(AJNA.balanceOf(address(_bidder)), 9.999999998763511925 * 1e18); + } - assertEq(USDC.balanceOf(address(_pool)), 1_006.443641 * 1e6); - assertEq(USDC.balanceOf(address(_bidder)), 1.425572 * 1e6); - assertEq(AJNA.balanceOf(address(_bidder)), 9.999999998775876805 * 1e18); + function testZeroBid() external { + // mint into the pool to simulate reserves + deal(address(USDC), address(_pool), 1_000_000 * 1e6); + _assertReserveAuction({ + reserves: 999_300.2884615384615386 * 1e18, + claimableReserves : 999_298.787018230769230907 * 1e18, + claimableReservesRemaining: 0, + auctionPrice: 0, + timeRemaining: 0 + }); + + // kick off a new auction + _kickReserveAuction({ + from: _bidder, + remainingReserves: 999_298.787018230769230907 * 1e18, + price: 1_000_000_000 * 1e18, + epoch: 1 + }); + + // price cannot hit zero, but wait for it to be reasonably small + skip(71 hours); + _assertReserveAuction({ + reserves: 1.501443307692307693 * 1e18, + claimableReserves : 0, + claimableReservesRemaining: 999_298.787018230769230907 * 1e18, + auctionPrice: 0.000000000000423516 * 1e18, + timeRemaining: 1 hours + }); + + // try to take the smallest amount of USDC possible + assertEq(USDC.balanceOf(address(_bidder)), 0); + assertEq(AJNA.balanceOf(address(_bidder)), 10 * 1e18); + _pool.takeReserves(1 * 1e6); + // bidder got nothing, but burned 1wei of AJNA + assertEq(USDC.balanceOf(address(_bidder)), 0); + assertEq(AJNA.balanceOf(address(_bidder)), 9.999999999999999999 * 1e18); + + // try to take a smaller-than-possible amount of USDC + _pool.takeReserves(1); + // bidder got nothing, but burned another 1wei of AJNA + assertEq(USDC.balanceOf(address(_bidder)), 0); + assertEq(AJNA.balanceOf(address(_bidder)), 9.999999999999999998 * 1e18); + + // take a reasonable amount of USDC + assertEq(USDC.balanceOf(address(_bidder)), 0); + _pool.takeReserves(100 * 1e18); + // bidder burned some AJNA + assertEq(USDC.balanceOf(address(_bidder)), 100 * 1e6); + assertEq(AJNA.balanceOf(address(_bidder)), 9.999999999957648398 * 1e18); } } @@ -150,14 +203,10 @@ contract ERC20PoolReserveAuctionNoFundsTest is ERC20HelperContract { // pool balance is amount added minus new debt assertEq(_quote.balanceOf(address(pool)), 98903); - vm.warp(block.timestamp + 17280000); + vm.warp(block.timestamp + 17_280_000); changePrank(_actor9); pool.updateInterest(); - pool.kick(_actor3, 7388); - // pool balance increased by kick bond - assertEq(_quote.balanceOf(address(pool)), 99920); - // available quote token does not account the kick bond assertEq(_availableQuoteToken(), 98903); vm.warp(block.timestamp + 86400); @@ -168,21 +217,23 @@ contract ERC20PoolReserveAuctionNoFundsTest is ERC20HelperContract { vm.expectRevert(IPoolErrors.InsufficientLiquidity.selector); pool.drawDebt(_actor7, 99266, 7388, 999234524847); - pool.drawDebt(_actor7, 98903, 7388, 999234524847); + // actor 7 draws almost all available quote token + pool.drawDebt(_actor7, 98703, 7388, 999234524847); // pool balance decreased by new debt - assertEq(_quote.balanceOf(address(pool)), 1017); + assertEq(_quote.balanceOf(address(pool)), 200); // available quote token decreased with new debt - assertEq(_availableQuoteToken(), 0); + assertEq(_availableQuoteToken(), 200); vm.warp(block.timestamp + 86400); + // attempt to kick reserves and verify pool balance is unchanged changePrank(_actor2); pool.updateInterest(); vm.expectRevert(IPoolErrors.NoReserves.selector); pool.kickReserveAuction(); + assertEq(_quote.balanceOf(address(pool)), 200); - // pool balance remains the same - assertEq(_quote.balanceOf(address(pool)), 1017); + vm.warp(block.timestamp + 86400); changePrank(_actor3); pool.updateInterest(); @@ -192,26 +243,21 @@ contract ERC20PoolReserveAuctionNoFundsTest is ERC20HelperContract { // repay debt to have enough balance to kick new reserves auction ERC20Pool(address(_pool)).repayDebt(_actor3, type(uint256).max, 0, _actor3, MAX_FENWICK_INDEX); + ERC20Pool(address(_pool)).repayDebt(_actor7, type(uint256).max, 0, _actor7, MAX_FENWICK_INDEX); - uint256 initialPoolBalance = 103934; - uint256 initialAvailableAmount = 102917; + uint256 initialPoolBalance = 200784; + uint256 initialAvailableAmount = 200784; assertEq(_quote.balanceOf(address(pool)), initialPoolBalance); assertEq(_availableQuoteToken(), initialAvailableAmount); pool.kickReserveAuction(); - uint256 kickerReward = 12; - uint256 claimableTokens = 1229; + uint256 claimableTokens = 591; ( , , uint256 claimable, , ) = _poolUtils.poolReservesInfo(address(_pool)); assertEq(claimable, claimableTokens); - // pool balance diminished by reward given to reserves kicker (12) - assertEq(_quote.balanceOf(address(pool)), initialPoolBalance - kickerReward); - // available quote token (available to remove / draw debt from) diminished by kicker reward + claimable tokens - assertEq(_availableQuoteToken(), initialAvailableAmount - (kickerReward + claimableTokens)); - skip(24 hours); // mint and approve ajna tokens for taker @@ -221,9 +267,9 @@ contract ERC20PoolReserveAuctionNoFundsTest is ERC20HelperContract { pool.takeReserves(claimableTokens); // quote token balance diminished by quote token taken from reserve auction - assertEq(_quote.balanceOf(address(pool)), initialPoolBalance - kickerReward - claimableTokens); + assertEq(_quote.balanceOf(address(pool)), initialPoolBalance - claimableTokens); // available quote token (available to remove / draw debt from) is not modified - assertEq(_availableQuoteToken(), initialAvailableAmount - (kickerReward + claimableTokens)); + assertEq(_availableQuoteToken(), initialAvailableAmount - claimableTokens); } } diff --git a/tests/forge/unit/ERC721Pool/ERC721DSTestPlus.sol b/tests/forge/unit/ERC721Pool/ERC721DSTestPlus.sol index 543a2b857..ac5dadf09 100644 --- a/tests/forge/unit/ERC721Pool/ERC721DSTestPlus.sol +++ b/tests/forge/unit/ERC721Pool/ERC721DSTestPlus.sol @@ -41,6 +41,13 @@ abstract contract ERC721DSTestPlus is DSTestPlus, IERC721PoolEvents { address borrower ) internal { changePrank(borrower); + + // settle borrower if borrower is kicked + (uint256 kickTime, , , , , ) = _poolUtils.auctionStatus(address(_pool), borrower); + if (kickTime != 0) { + _pool.settle(borrower, bucketsUsed.length()); + } + uint256 borrowerT0debt; uint256 borrowerCollateral; (borrowerT0debt, borrowerCollateral, ) = _pool.borrowerInfo(borrower); @@ -140,16 +147,33 @@ abstract contract ERC721DSTestPlus is DSTestPlus, IERC721PoolEvents { assertEq(collateral, 0); } ( , uint256 loansCount, , , ) = _poolUtils.poolLoansInfo(address(_pool)); - (uint256 debt, , ,) = _pool.debtInfo(); + (uint256 debt, , uint256 t0DebtInAuction,) = _pool.debtInfo(); assertEq(debt, 0); + assertEq(t0DebtInAuction, 0); assertEq(loansCount, 0); assertEq(_pool.pledgedCollateral(), 0); } modifier tearDown { _; + + // Skip time to make all auctioned borrowers settleable + skip(73 hours); + for (uint i = 0; i < borrowers.length(); i++) { - repayDebt(borrowers.at(i)); + address borrower = borrowers.at(i); + (,,, uint256 kickTime,,,,,) = _pool.auctionInfo(borrower); + if (kickTime != 0) { + changePrank(borrower); + _pool.settle(borrower, bucketsUsed.length() + 1); + + // Settle again if not settled, this can happen when less reserves calculated with DEPOSIT_BUFFER and borrower is not fully settled + (,,, kickTime,,,,,) = _pool.auctionInfo(borrower); + if (kickTime != 0) { + _pool.settle(borrower, bucketsUsed.length() + 1); + } + } + repayDebt(borrower); } for (uint i = 0; i < lenders.length(); i++) { @@ -637,6 +661,15 @@ abstract contract ERC721DSTestPlus is DSTestPlus, IERC721PoolEvents { ERC721Pool(address(_pool)).repayDebt(from, 0, amount, from, indexLimit); } + function _assertRepayAuctionActiveRevert( + address from, + uint256 maxAmount + ) internal override { + changePrank(from); + vm.expectRevert(IPoolErrors.AuctionActive.selector); + ERC721Pool(address(_pool)).repayDebt(from, maxAmount, 0, from, MAX_FENWICK_INDEX); + } + function _assertRepayLimitIndexRevert( address from, uint256 amount, @@ -686,6 +719,25 @@ abstract contract ERC721DSTestPlus is DSTestPlus, IERC721PoolEvents { vm.expectRevert(IPoolErrors.InsufficientLP.selector); _pool.removeCollateral(amount, index); } + + function _assertRepayDebtAuctionActiveRevert( + address from, + address borrower, + uint256 amount + ) internal { + changePrank(from); + vm.expectRevert(IPoolErrors.AuctionActive.selector); + ERC721Pool(address(_pool)).repayDebt(borrower, amount, 0, borrower, MAX_FENWICK_INDEX); + } + + function _assertPledgeCollateralAuctionActiveRevert( + address from, + uint256[] memory tokenIds + ) internal { + changePrank(from); + vm.expectRevert(IPoolErrors.AuctionActive.selector); + ERC721Pool(address(_pool)).drawDebt(from, 0, 0, tokenIds); + } } abstract contract ERC721HelperContract is ERC721DSTestPlus { diff --git a/tests/forge/unit/ERC721Pool/ERC721PoolBorrow.t.sol b/tests/forge/unit/ERC721Pool/ERC721PoolBorrow.t.sol index 3a63580db..b8b41c6d2 100644 --- a/tests/forge/unit/ERC721Pool/ERC721PoolBorrow.t.sol +++ b/tests/forge/unit/ERC721Pool/ERC721PoolBorrow.t.sol @@ -248,7 +248,7 @@ contract ERC721SubsetPoolBorrowTest is ERC721PoolBorrowTest { borrower: _borrower, borrowerDebt: 3_002.884615384615386000 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_051.009615384615385100 * 1e18, + borrowert0Np: 1_152.910902143138512881 * 1e18, borrowerCollateralization: 3.007999714779824033 * 1e18 }); // pass time to allow interest to accumulate @@ -289,7 +289,6 @@ contract ERC721SubsetPoolBorrowTest is ERC721PoolBorrowTest { interestRateUpdate: _startTime + 10 days }) ); - assertEq(_poolUtils.momp(address(_pool)), 3_010.892022197881557845 * 1e18); // check bucket state after partial repay _assertBucket({ index: 2550, @@ -303,7 +302,7 @@ contract ERC721SubsetPoolBorrowTest is ERC721PoolBorrowTest { borrower: _borrower, borrowerDebt: 1_507.000974734143274062 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_051.009615384615385100 * 1e18, + borrowert0Np: 577.797569043003579568 * 1e18, borrowerCollateralization: 5.993809040625961846 * 1e18 }); @@ -315,7 +314,7 @@ contract ERC721SubsetPoolBorrowTest is ERC721PoolBorrowTest { borrower: _borrower, borrowerDebt: 1_508.860066921599065132 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_051.009615384615385100 * 1e18, + borrowert0Np: 577.797569043003579568 * 1e18, borrowerCollateralization: 5.986423966420065589 * 1e18 }); @@ -826,7 +825,7 @@ contract ERC721ScaledQuoteTokenBorrowAndRepayTest is ERC721NDecimalsHelperContra borrower: _borrower, borrowerDebt: 3_002.884615384615386000 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_051.009615384615385100 * 1e18, + borrowert0Np: 1_152.910902143138512881 * 1e18, borrowerCollateralization: 3.007999714779824033 * 1e18 }); // pass time to allow interest to accumulate @@ -868,7 +867,6 @@ contract ERC721ScaledQuoteTokenBorrowAndRepayTest is ERC721NDecimalsHelperContra interestRateUpdate: _startTime + 10 days }) ); - assertEq(_poolUtils.momp(address(_pool)), 3_010.892022197881557845 * 1e18); // check bucket state after partial repay _assertBucket({ index: 2550, @@ -882,7 +880,7 @@ contract ERC721ScaledQuoteTokenBorrowAndRepayTest is ERC721NDecimalsHelperContra borrower: _borrower, borrowerDebt: 1_507.000974734143274062 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_051.009615384615385100 * 1e18, + borrowert0Np: 577.797569043003579568 * 1e18, borrowerCollateralization: 5.993809040625961846 * 1e18 }); @@ -894,7 +892,7 @@ contract ERC721ScaledQuoteTokenBorrowAndRepayTest is ERC721NDecimalsHelperContra borrower: _borrower, borrowerDebt: 1_508.860066921599065132 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_051.009615384615385100 * 1e18, + borrowert0Np: 577.797569043003579568 * 1e18, borrowerCollateralization: 5.986423966420065589 * 1e18 }); diff --git a/tests/forge/unit/ERC721Pool/ERC721PoolCollateral.t.sol b/tests/forge/unit/ERC721Pool/ERC721PoolCollateral.t.sol index 7e55c866c..d4f1015fd 100644 --- a/tests/forge/unit/ERC721Pool/ERC721PoolCollateral.t.sol +++ b/tests/forge/unit/ERC721Pool/ERC721PoolCollateral.t.sol @@ -657,7 +657,7 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { borrower: _borrower, borrowerDebt: 150.144230769230769300 * 1e18, borrowerCollateral: 2.0 * 1e18, - borrowert0Np: 78.825721153846153882 * 1e18, + borrowert0Np: 86.468317660735388466 * 1e18, borrowerCollateralization: 3.043424968161510485 * 1e18, tokenIds: borrowerTokenIds }); @@ -693,10 +693,10 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { _kick({ from: _lender, borrower: _borrower, - debt: 598.174133241016922932 * 1e18, + debt: 590.789267398535232526 * 1e18, collateral: 2.0 * 1e18, - bond: 5.907892673985352325 * 1e18, - transferAmount: 5.907892673985352325 * 1e18 + bond: 8.968381880996266239 * 1e18, + transferAmount: 8.968381880996266239 * 1e18 }); skip(32 hours); @@ -706,15 +706,15 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { borrower: _borrower, active: true, kicker: address(_lender), - bondSize: 5.907892673985352325 * 1e18, - bondFactor: 0.010 * 1e18, + bondSize: 8.968381880996266239 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 32 hours, - kickMomp: 0.000000099836282890 * 1e18, - totalBondEscrowed: 5.907892673985352325 * 1e18, - auctionPrice: 0.000004621809202112 * 1e18, - debtInAuction: 598.174133241016922932 * 1e18, - thresholdPrice: 299.147163209604307694 * 1e18, - neutralPrice: 310.164365384230997074 * 1e18 + referencePrice: 340.236543104248948639 * 1e18, + totalBondEscrowed: 8.968381880996266239 * 1e18, + auctionPrice: 0.000081118713165342 * 1e18, + debtInAuction: 590.789267398535232527 * 1e18, + thresholdPrice: 295.453988355164748340 * 1e18, + neutralPrice: 340.236543104248948639 * 1e18 }) ); @@ -724,8 +724,8 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { lup: 99836282890, poolSize: 574.548281134908793200 * 1e18, pledgedCollateral: 2 * 1e18, - encumberedCollateral: 5_992_754_428.551908353085520210 * 1e18, - poolDebt: 598.294326419208615388 * 1e18, + encumberedCollateral: 5_918_769_805.977193435161155568 * 1e18, + poolDebt: 590.907976710329496681 * 1e18, actualUtilization: 0.750721153846153847 * 1e18, targetUtilization: 0.328577182109433013 * 1e18, minDebtAmount: 0, @@ -742,80 +742,80 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { index: 3060, lpBalance: 20 * 1e18, collateral: 0.0000000000000000000 * 1e18, - deposit: 57.465712770068876500 * 1e18, - exchangeRate: 2.873285638503443825 * 1e18 + deposit: 57.465578391592604940 * 1e18, + exchangeRate: 2.873278919579630247 * 1e18 }); _assertBucket({ index: 3061, lpBalance: 20.0 * 1e18, collateral: 0.0 * 1e18, - deposit: 57.465712770068876500 * 1e18, - exchangeRate: 2.873285638503443825 * 1e18 + deposit: 57.465578391592604940 * 1e18, + exchangeRate: 2.873278919579630247 * 1e18 }); _assertBucket({ index: 3062, lpBalance: 20.0 * 1e18, collateral: 0.0 * 1e18, - deposit: 57.465712770068876500 * 1e18, - exchangeRate: 2.873285638503443825 * 1e18 + deposit: 57.465578391592604940 * 1e18, + exchangeRate: 2.873278919579630247 * 1e18 }); _assertBucket({ index: 3063, lpBalance: 20.0 * 1e18, collateral: 0.0 * 1e18, - deposit: 57.465712770068876500 * 1e18, - exchangeRate: 2.873285638503443825 * 1e18 + deposit: 57.465578391592604940 * 1e18, + exchangeRate: 2.873278919579630247 * 1e18 }); _assertBucket({ index: 3064, lpBalance: 20.0 * 1e18, collateral: 0.0 * 1e18, - deposit: 57.465712770068876500 * 1e18, - exchangeRate: 2.873285638503443825 * 1e18 + deposit: 57.465578391592604940 * 1e18, + exchangeRate: 2.873278919579630247 * 1e18 }); _assertBucket({ index: 3065, lpBalance: 20.0 * 1e18, collateral: 0.0 * 1e18, - deposit: 57.465712770068876500 * 1e18, - exchangeRate: 2.873285638503443825 * 1e18 + deposit: 57.465578391592604940 * 1e18, + exchangeRate: 2.873278919579630247 * 1e18 }); _assertBucket({ index: 3066, lpBalance: 20.0 * 1e18, collateral: 0.0 * 1e18, - deposit: 57.465712770068876500 * 1e18, - exchangeRate: 2.873285638503443825 * 1e18 + deposit: 57.465578391592604940 * 1e18, + exchangeRate: 2.873278919579630247 * 1e18 }); _assertBucket({ index: 3067, lpBalance: 20.0 * 1e18, collateral: 0.0 * 1e18, - deposit: 57.465712770068876500 * 1e18, - exchangeRate: 2.873285638503443825 * 1e18 + deposit: 57.465578391592604940 * 1e18, + exchangeRate: 2.873278919579630247 * 1e18 }); _assertBucket({ index: 3068, lpBalance: 20.0 * 1e18, collateral: 0.0 * 1e18, - deposit: 57.465712770068876500 * 1e18, - exchangeRate: 2.873285638503443825 * 1e18 + deposit: 57.465578391592604940 * 1e18, + exchangeRate: 2.873278919579630247 * 1e18 }); _assertBucket({ index: 3069, lpBalance: 20.0 * 1e18, collateral: 0.0 * 1e18, - deposit: 57.465712770068876500 * 1e18, - exchangeRate: 2.873285638503443825 * 1e18 + deposit: 57.465578391592604940 * 1e18, + exchangeRate: 2.873278919579630247 * 1e18 }); _assertBucket({ @@ -841,18 +841,18 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { _assertBucket({ index: 3060, - lpBalance: 20.202020202020202020 * 1e18, - collateral: 0.245340879650286415 * 1e18, - deposit: 0, - exchangeRate: 2.873285638503443827 * 1e18 + lpBalance: 20.308286694556134654 * 1e18, + collateral: 0.246630842904997686 * 1e18, + deposit: 0.000000000000000144 * 1e18, + exchangeRate: 2.873278919579630248 * 1e18 }); _assertBucket({ index: 3061, - lpBalance: 20.202020202020202020 * 1e18, - collateral: 0.246567584048537845 * 1e18, - deposit: 0, - exchangeRate: 2.873285638503443827 * 1e18 + lpBalance: 20.308286694556134655 * 1e18, + collateral: 0.247863997119522673 * 1e18, + deposit: 0.000000000000000006 * 1e18, + exchangeRate: 2.873278919579630248 * 1e18 }); _assertBucket({ @@ -868,15 +868,15 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { borrower: _borrower, active: true, kicker: address(_lender), - bondSize: 5.907892673985352325 * 1e18, - bondFactor: 0.010 * 1e18, + bondSize: 8.968381880996266239 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 32 hours, - kickMomp: 0.000000099836282890 * 1e18, - totalBondEscrowed: 5.907892673985352325 * 1e18, - auctionPrice: 0.000004621809202112 * 1e18, - debtInAuction: 467.777790958346588935 * 1e18, - thresholdPrice: 371.166459589091918644 * 1e18, - neutralPrice: 310.164365384230997074 * 1e18 + referencePrice: 340.236543104248948639 * 1e18, + totalBondEscrowed: 8.968381880996266239 * 1e18, + auctionPrice: 0.000081118713165342 * 1e18, + debtInAuction: 418.511241535551682100 * 1e18, + thresholdPrice: 333.103014700636165105 * 1e18, + neutralPrice: 340.236543104248948639 * 1e18 }) ); @@ -884,10 +884,10 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { PoolParams({ htp: 0, lup: 99836282890, - poolSize: 402.259989390482135517 * 1e18, - pledgedCollateral: 1.260291114332395208 * 1e18, - encumberedCollateral: 4_685_448_790.934513817364339575 * 1e18, - poolDebt: 467.777790958346588935 * 1e18, + poolSize: 402.259048741148234756 * 1e18, + pledgedCollateral: 1.256401842870359357 * 1e18, + encumberedCollateral: 4_191_975_396.326293274519167147 * 1e18, + poolDebt: 418.511241535551682100 * 1e18, actualUtilization: 0.750721153846153847 * 1e18, targetUtilization: 0.328577182109433013 * 1e18, minDebtAmount: 0, @@ -904,10 +904,10 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { _assertBorrower({ borrower: _borrower, - borrowerDebt: 467.777790958346588935 * 1e18, - borrowerCollateral: 1.260291114332395208 * 1e18, - borrowert0Np: 78.825721153846153882 * 1e18, - borrowerCollateralization: 0.000000000268979808 * 1e18, + borrowerDebt: 418.511241535551682100 * 1e18, + borrowerCollateral: 1.256401842870359357 * 1e18, + borrowert0Np: 97.486777718699640528 * 1e18, + borrowerCollateralization: 0.000000000299715939 * 1e18, tokenIds: borrowerTokenIds }); @@ -919,8 +919,8 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { from: _lender, borrower: _borrower, maxCollateral: 2 * 1e18, - bondChange: 0.000000046218092021 * 1e18, - givenAmount: 0.000004621809202112 * 1e18, + bondChange: 0.000001231409637086 * 1e18, + givenAmount: 0.000081118713165342 * 1e18, collateralTaken: 1 * 1e18, isReward: true }); @@ -930,10 +930,10 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { _assertBorrower({ borrower: _borrower, - borrowerDebt: 467.777786382755478845 * 1e18, - borrowerCollateral: 0.260291114332395208 * 1e18, - borrowert0Np: 78.825721153846153882 * 1e18, - borrowerCollateralization: 0.000000000055553081 * 1e18, + borrowerDebt: 418.511161648248153847 * 1e18, + borrowerCollateral: 0.256401842870359357 * 1e18, + borrowert0Np: 477.697595423190347016 * 1e18, + borrowerCollateralization: 0.000000000061164932 * 1e18, tokenIds: borrowerTokenIds }); @@ -956,30 +956,30 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { borrower: _borrower, active: true, kicker: address(_lender), - bondSize: 5.907892720203444346 * 1e18, - bondFactor: 0.010 * 1e18, + bondSize: 8.968383112405903325 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - (32 hours + 4210 minutes), - kickMomp: 0.000000099836282890 * 1e18, - totalBondEscrowed: 5.907892720203444346 * 1e18, + referencePrice: 340.236543104248948639 * 1e18, + totalBondEscrowed: 8.968383112405903325 * 1e18, auctionPrice: 0, - debtInAuction: 467.777786382755478845 * 1e18, - thresholdPrice: 1_798.004234437087055097 * 1e18, - neutralPrice: 310.164365384230997074 * 1e18 + debtInAuction: 418.511161648248153847 * 1e18, + thresholdPrice: 1_633.038265299714540882 * 1e18, + neutralPrice: 340.236543104248948639 * 1e18 }) ); _settle({ from: _lender, borrower: _borrower, - maxDepth: 10, - settledDebt: 118.857992573354662400 * 1e18 + maxDepth: 11, + settledDebt: 106.339800629932799697 * 1e18 }); _assertBorrower({ borrower: _borrower, borrowerDebt: 0, borrowerCollateral: 0, - borrowert0Np: 78.825721153846153882 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1.0 * 1e18, tokenIds: borrowerTokenIds }); @@ -996,8 +996,8 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 5.907892720203444346 * 1e18, + referencePrice: 0, + totalBondEscrowed: 8.968383112405903325 * 1e18, auctionPrice: 0, debtInAuction: 0, thresholdPrice: 0, @@ -1007,10 +1007,10 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { _assertBucket({ index: 3060, - lpBalance: 20.202020202020202020 * 1e18, - collateral: 0.245340879650286415 * 1e18, + lpBalance: 20.308286694556134654 * 1e18, + collateral: 0.246630842904997687 * 1e18, deposit: 0, - exchangeRate: 2.873285638503443827 * 1e18 + exchangeRate: 2.873278919579630252 * 1e18 }); _assertLenderLpBalance({ lender: _borrower, @@ -1169,7 +1169,7 @@ contract ERC721PoolCollateralTest is ERC721HelperContract { PoolParams({ htp: 0, lup: MAX_PRICE, - poolSize: 50.000004233778718162 * 1e18, + poolSize: 50.000079544611684526 * 1e18, pledgedCollateral: 0, encumberedCollateral: 0, poolDebt: 0, diff --git a/tests/forge/unit/ERC721Pool/ERC721PoolInterest.t.sol b/tests/forge/unit/ERC721Pool/ERC721PoolInterest.t.sol index d07ff3ac0..c46c23e4c 100644 --- a/tests/forge/unit/ERC721Pool/ERC721PoolInterest.t.sol +++ b/tests/forge/unit/ERC721Pool/ERC721PoolInterest.t.sol @@ -103,7 +103,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_743.173878205128204457 * 1e18, + borrowert0Np: 1_911.763008462438456052 * 1e18, borrowerCollateralization: 1.804973217265326249 * 1e18 }); @@ -127,7 +127,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 4 * 1e18, - borrowert0Np: 1_743.173878205128204457 * 1e18, + borrowert0Np: 1_433.822256346828842039 * 1e18, borrowerCollateralization: 2.403665705362551645 * 1e18 }); @@ -152,7 +152,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_735.667387820512819845 * 1e18, + borrowert0Np: 1_902.683561057818747541 * 1e18, borrowerCollateralization: 1.800750077529217167 * 1e18 }); @@ -176,7 +176,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 3 * 1e18, - borrowert0Np: 2_073.483875782488916529 * 1e18, + borrowert0Np: 2_271.558482861789242177 * 1e18, borrowerCollateralization: 1.500002057800446964 * 1e18 }); @@ -204,7 +204,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: 0, borrowerCollateral: 3 * 1e18, - borrowert0Np: 2_073.483875782488916529 * 1e18, + borrowert0Np: 0.000000000000000000 * 1e18, borrowerCollateralization: 1 * 1e18 }); } @@ -259,7 +259,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedBorrower1Debt, borrowerCollateral: 3 * 1e18, - borrowert0Np: 2_802.692307692307693600 * 1e18, + borrowert0Np: 3_074.429072381702701017 * 1e18, borrowerCollateralization: 1.127999893042434013 * 1e18 }); @@ -292,14 +292,14 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedBorrower1Debt, borrowerCollateral: 3 * 1e18, - borrowert0Np: 2_802.692307692307693600 * 1e18, + borrowert0Np: 3_074.429072381702701017 * 1e18, borrowerCollateralization: 1.122362328272840838 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: expectedBorrower2Debt, borrowerCollateral: 1 * 1e18, - borrowert0Np: 2_904.661507289418461412 * 1e18, + borrowert0Np: 3_170.432595761480458330 * 1e18, borrowerCollateralization: 1.088376197116173336 * 1e18 }); @@ -336,21 +336,21 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedBorrower1Debt, borrowerCollateral: 3 * 1e18, - borrowert0Np: 2_802.692307692307693600 * 1e18, + borrowert0Np: 3_074.429072381702701017 * 1e18, borrowerCollateralization: 1.122336703854666979 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: expectedBorrower2Debt, borrowerCollateral: 1 * 1e18, - borrowert0Np: 2_904.661507289418461412 * 1e18, + borrowert0Np: 3_170.432595761480458330 * 1e18, borrowerCollateralization: 1.088351348628209297 * 1e18 }); _assertBorrower({ borrower: _borrower3, borrowerDebt: expectedBorrower3Debt, borrowerCollateral: 1 * 1e18, - borrowert0Np: 2_640.541083248800813687 * 1e18, + borrowert0Np: 2_882.145647529036115605 * 1e18, borrowerCollateralization: 1.197213816827790670 * 1e18 }); @@ -382,7 +382,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedBorrower1Debt, borrowerCollateral: 3 * 1e18, - borrowert0Np: 2_802.692307692307693600 * 1e18, + borrowert0Np: 3_074.429072381702701017 * 1e18, borrowerCollateralization: 1.122311080021518821 * 1e18 }); @@ -392,7 +392,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower2, borrowerDebt: expectedBorrower2Debt, borrowerCollateral: 1 * 1e18, - borrowert0Np: 2_904.661507289418461412 * 1e18, + borrowert0Np: 3_170.432595761480458330 * 1e18, borrowerCollateralization: 1.088326500707555859 * 1e18 }); @@ -402,7 +402,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower3, borrowerDebt: expectedBorrower3Debt, borrowerCollateral: 1 * 1e18, - borrowert0Np: 2_640.541083248800813687 * 1e18, + borrowert0Np: 2_882.145647529036115605 * 1e18, borrowerCollateralization: 1.197186483491030227 * 1e18 }); @@ -466,7 +466,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_743.173878205128204457 * 1e18, + borrowert0Np: 1_911.763008462438456052 * 1e18, borrowerCollateralization: 1.804973217265326249 * 1e18 }); @@ -481,7 +481,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_743.173878205128204457 * 1e18, + borrowert0Np: 1_911.763008462438456052 * 1e18, borrowerCollateralization: 1.798309619615464420 * 1e18 }); @@ -507,7 +507,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: 0, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_743.173878205128204457 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); @@ -529,7 +529,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_726.979669209494250313 * 1e18, + borrowert0Np: 1_893.159858820699522954 * 1e18, borrowerCollateralization: 1.805129295309881815 * 1e18 }); @@ -554,7 +554,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 4 * 1e18, - borrowert0Np: 1_726.979669209494250313 * 1e18, + borrowert0Np: 1_419.869894115524642215 * 1e18, borrowerCollateralization: 2.404169939255701731 * 1e18 }); @@ -579,7 +579,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_720.257643586910442803 * 1e18, + borrowert0Np: 1_884.589452870960229897 * 1e18, borrowerCollateralization: 1.801327695821111558 * 1e18 }); @@ -603,7 +603,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: expectedDebt, borrowerCollateral: 3 * 1e18, - borrowert0Np: 2_055.969470907112040316 * 1e18, + borrowert0Np: 2_250.568493913377606760 * 1e18, borrowerCollateralization: 1.500545633513497515 * 1e18 }); @@ -631,7 +631,7 @@ contract ERC721PoolSubsetInterestTest is ERC721PoolInterestTest { borrower: _borrower, borrowerDebt: 0, borrowerCollateral: 3 * 1e18, - borrowert0Np: 2_055.969470907112040316 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); diff --git a/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsDepositTake.t.sol b/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsDepositTake.t.sol index 0d31ea0b4..94c574fa8 100644 --- a/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsDepositTake.t.sol +++ b/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsDepositTake.t.sol @@ -128,14 +128,14 @@ contract ERC721PoolLiquidationsDepositTakeTest is ERC721HelperContract { borrower: _borrower, borrowerDebt: 19.819038461538461548 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, + borrowert0Np: 11.413817931217071277 * 1e18, borrowerCollateralization: 1.000773560501591181 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 15.014423076923076930 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 5.255048076923076925 * 1e18, + borrowert0Np: 5.764554510715692564 * 1e18, borrowerCollateralization: 1.981531649793150539 * 1e18 }); @@ -147,10 +147,10 @@ contract ERC721PoolLiquidationsDepositTakeTest is ERC721HelperContract { _kick({ from: _lender, borrower: _borrower, - debt: 23.012828827714740289 * 1e18, + debt: 22.728719829841718804 * 1e18, collateral: 2 * 1e18, - bond: 0.227287198298417188 * 1e18, - transferAmount: 0.227287198298417188 * 1e18 + bond: 0.345029692224734546 * 1e18, + transferAmount: 0.345029692224734546 * 1e18 }); /******************************/ @@ -163,11 +163,11 @@ contract ERC721PoolLiquidationsDepositTakeTest is ERC721HelperContract { lup: 9.917184843435912074 * 1e18, poolSize: 73_004.346887619919714000 * 1e18, pledgedCollateral: 5 * 1e18, - encumberedCollateral: 4.056751649452525709 * 1e18, - poolDebt: 40.231555971534224232 * 1e18, + encumberedCollateral: 4.028103499563389533 * 1e18, + poolDebt: 39.947446973661202747 * 1e18, actualUtilization: 0.000477170706006322 * 1e18, targetUtilization: 0.786051641950380194 * 1e18, - minDebtAmount: 4.023155597153422423 * 1e18, + minDebtAmount: 3.994744697366120275 * 1e18, loans: 1, maxBorrower: address(_borrower2), interestRate: 0.045 * 1e18, @@ -176,41 +176,39 @@ contract ERC721PoolLiquidationsDepositTakeTest is ERC721HelperContract { ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 23.012828827714740290 * 1e18, + borrowerDebt: 22.728719829841718805 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, - borrowerCollateralization: 0.861883162446546169 * 1e18 + borrowert0Np: 11.413817931217071277 * 1e18, + borrowerCollateralization: 0.872656701977127996 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 17.218727143819483943 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 5.255048076923076925 * 1e18, + borrowert0Np: 5.764554510715692564 * 1e18, borrowerCollateralization: 1.727860269914713433 * 1e18 }); } function testDepositTakeNFTAndSettleAuction() external { - - skip(5 hours); + skip(6 hours); _assertAuction( AuctionParams({ borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.227287198298417188 * 1e18, - bondFactor: 0.01 * 1e18, - kickTime: block.timestamp - 5 hours, - kickMomp: 9.917184843435912074 * 1e18, - totalBondEscrowed: 0.227287198298417188 * 1e18, - auctionPrice: 23.865155821333804736 * 1e18, - debtInAuction: 23.012828827714740290 * 1e18, - thresholdPrice: 11.506709959118993145 * 1e18, - neutralPrice: 11.932577910666902372 * 1e18 + bondSize: 0.345029692224734546 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 6 hours, + referencePrice: 13.089508376044532178 * 1e18, + totalBondEscrowed: 0.345029692224734546 * 1e18, + auctionPrice: 13.089508376044532180 * 1e18, + debtInAuction: 22.728719829841718805 * 1e18, + thresholdPrice: 11.364710191686173217 * 1e18, + neutralPrice: 13.089508376044532178 * 1e18 }) ); - assertEq(_poolUtils.momp(address(_pool)), 9.917184843435912074 * 1e18); _addLiquidity({ from: _lender, @@ -222,10 +220,10 @@ contract ERC721PoolLiquidationsDepositTakeTest is ERC721HelperContract { _assertBorrower({ borrower: _borrower, - borrowerDebt: 23.013419918237986290 * 1e18, + borrowerDebt: 22.729420383372346434 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, - borrowerCollateralization: 0.861861025320848319 * 1e18 + borrowert0Np: 11.413817931217071277 * 1e18, + borrowerCollateralization: 0.872629805438488447 * 1e18 }); // before deposit take: NFTs pledged by auctioned borrower are owned by the pool @@ -239,8 +237,8 @@ contract ERC721PoolLiquidationsDepositTakeTest is ERC721HelperContract { index: _i1505_26, collateralArbed: 0.009965031187761219 * 1e18, quoteTokenAmount: 14.999999999999999995 * 1e18, - bondChange: 0.15 * 1e18, - isReward: false, + bondChange: 0, + isReward: true, lpAwardTaker: 0, lpAwardKicker: 0 }); @@ -248,39 +246,39 @@ contract ERC721PoolLiquidationsDepositTakeTest is ERC721HelperContract { _assertAuction( AuctionParams({ borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0.077287198298417188 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 9.624359312514645335 * 1e18, - neutralPrice: 0 + active: true, + kicker: _lender, + bondSize: 0.345029692224734546 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 6 hours, + referencePrice: 13.089508376044532178 * 1e18, + totalBondEscrowed: 0.345029692224734546 * 1e18, + auctionPrice: 13.089508376044532180 * 1e18, + debtInAuction: 8.014051756262951713 * 1e18, + thresholdPrice: 4.027090921445553358 * 1e18, + neutralPrice: 13.089508376044532178 * 1e18 }) ); // borrower is compensated LP for fractional collateral _assertLenderLpBalance({ lender: _borrower, index: 3519, - lpBalance: 23.737330323739529015 * 1e18, - depositTime: block.timestamp + lpBalance: 0 * 1e18, + depositTime: 0 }); _assertBucket({ index: _i1505_26, lpBalance: 15 * 1e18, collateral: 0.009965031187761219 * 1e18, - deposit: 5, + deposit: 0.000000000000000005 * 1e18, exchangeRate: 1.000000000000000001 * 1e18 }); _assertBorrower({ borrower: _borrower, - borrowerDebt: 9.624359312514645335 * 1e18, - borrowerCollateral: 1 * 1e18, - borrowert0Np: 8.769696613728507382 * 1e18, - borrowerCollateralization: 1.030425457052554443 * 1e18 + borrowerDebt: 8.014051756262951713 * 1e18, + borrowerCollateral: 1.990034968812238781 * 1e18, + borrowert0Np: 4.044492274291511923 * 1e18, + borrowerCollateralization: 2.462617566100560496 * 1e18 }); _assertLenderLpBalance({ lender: _taker, @@ -295,17 +293,26 @@ contract ERC721PoolLiquidationsDepositTakeTest is ERC721HelperContract { depositTime: block.timestamp }); - // borrower should be able to repay and pull collateral from the pool - _repayDebtNoLupCheck({ - from: _borrower, - borrower: _borrower, - amountToRepay: 10 * 1e18, - amountRepaid: 10 * 1e18, - collateralToPull: 1 + // borrower cannot repay amidst auction + _assertRepayAuctionActiveRevert({ + from: _borrower, + maxAmount: 4 * 1e18 }); - // after deposit take and pull: NFT taken remains in pool, the pulled one goes to borrower - assertEq(_collateral.ownerOf(3), address(_pool)); - assertEq(_collateral.ownerOf(1), _borrower); + // ensure borrower is not left with fraction of NFT upon settlement + skip(72 hours); + _settle({ + from: _lender, + borrower: _borrower, + maxDepth: 5, + settledDebt: 6.987894865384582852 * 1e18 + }); + _assertBorrower({ + borrower: _borrower, + borrowerDebt: 0 * 1e18, + borrowerCollateral: 1 * 1e18, + borrowert0Np: 0 * 1e18, + borrowerCollateralization: 1 * 1e18 + }); } } diff --git a/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsKick.t.sol b/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsKick.t.sol index abc8f1d3e..6b7e1d1bb 100644 --- a/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsKick.t.sol +++ b/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsKick.t.sol @@ -121,14 +121,14 @@ contract ERC721PoolLiquidationsKickTest is ERC721HelperContract { borrower: _borrower, borrowerDebt: 19.819038461538461548 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, + borrowert0Np: 11.413817931217071277 * 1e18, borrowerCollateralization: 1.000773560501591181 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 15.014423076923076930 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 5.255048076923076925 * 1e18, + borrowert0Np: 5.764554510715692564 * 1e18, borrowerCollateralization: 1.981531649793150539 * 1e18 }); @@ -148,7 +148,7 @@ contract ERC721PoolLiquidationsKickTest is ERC721HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -160,17 +160,17 @@ contract ERC721PoolLiquidationsKickTest is ERC721HelperContract { borrower: _borrower, borrowerDebt: 22.728719829841718805 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, + borrowert0Np: 11.413817931217071277 * 1e18, borrowerCollateralization: 0.872656701977127996 * 1e18 }); _kick({ from: _lender, borrower: _borrower, - debt: 23.012828827714740289 * 1e18, + debt: 22.728719829841718804 * 1e18, collateral: 2 * 1e18, - bond: 0.227287198298417188 * 1e18, - transferAmount: 0.227287198298417188 * 1e18 + bond: 0.345029692224734546 * 1e18, + transferAmount: 0.345029692224734546 * 1e18 }); /******************************/ @@ -183,11 +183,11 @@ contract ERC721PoolLiquidationsKickTest is ERC721HelperContract { lup: 9.917184843435912074 * 1e18, poolSize: 73_004.346887619919714000 * 1e18, pledgedCollateral: 5 * 1e18, - encumberedCollateral: 4.056751649452525709 * 1e18, - poolDebt: 40.231555971534224232 * 1e18, + encumberedCollateral: 4.028103499563389533 * 1e18, + poolDebt: 39.947446973661202747 * 1e18, actualUtilization: 0.000477170706006322 * 1e18, targetUtilization: 0.786051641950380194 * 1e18, - minDebtAmount: 4.023155597153422423 * 1e18, + minDebtAmount: 3.994744697366120275 * 1e18, loans: 1, maxBorrower: address(_borrower2), interestRate: 0.045 * 1e18, @@ -199,38 +199,38 @@ contract ERC721PoolLiquidationsKickTest is ERC721HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.227287198298417188 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.345029692224734546 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.917184843435912074 * 1e18, - totalBondEscrowed: 0.227287198298417188 * 1e18, - auctionPrice: 381.842493141340875904 * 1e18, - debtInAuction: 23.012828827714740290 * 1e18, - thresholdPrice: 11.506414413857370145 * 1e18, - neutralPrice: 11.932577910666902372 * 1e18 + referencePrice: 13.089508376044532178 * 1e18, + totalBondEscrowed: 0.345029692224734546 * 1e18, + auctionPrice: 3_350.914144267400237568 * 1e18, + debtInAuction: 22.728719829841718805 * 1e18, + thresholdPrice: 11.364359914920859402 * 1e18, + neutralPrice: 13.089508376044532178 * 1e18 }) ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 23.012828827714740290 * 1e18, + borrowerDebt: 22.728719829841718805 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, - borrowerCollateralization: 0.861883162446546169 * 1e18 + borrowert0Np: 11.413817931217071277 * 1e18, + borrowerCollateralization: 0.872656701977127996 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 17.218727143819483943 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 5.255048076923076925 * 1e18, + borrowert0Np: 5.764554510715692564 * 1e18, borrowerCollateralization: 1.727860269914713433 * 1e18 }); _assertKicker({ kicker: _lender, claimable: 0, - locked: 0.227287198298417188 * 1e18 + locked: 0.345029692224734546 * 1e18 }); - assertEq(_quote.balanceOf(_lender), 46_999.772712801701582812 * 1e18); + assertEq(_quote.balanceOf(_lender), 46_999.654970307775265454 * 1e18); // kick should fail if borrower in liquidation _assertKickAuctionActiveRevert({ @@ -259,7 +259,7 @@ contract ERC721PoolLiquidationsKickTest is ERC721HelperContract { }); } - function testKickSubsetPoolAndSettleByRepayAndPledge() external tearDown { + function testKickSubsetPoolRepayAndPledgeReverts() external tearDown { // Skip to make borrower undercollateralized skip(1000 days); @@ -271,7 +271,7 @@ contract ERC721PoolLiquidationsKickTest is ERC721HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -283,17 +283,17 @@ contract ERC721PoolLiquidationsKickTest is ERC721HelperContract { borrower: _borrower, borrowerDebt: 22.728719829841718805 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, + borrowert0Np: 11.413817931217071277 * 1e18, borrowerCollateralization: 0.872656701977127996 * 1e18 }); _kick({ from: _lender, borrower: _borrower, - debt: 23.012828827714740289 * 1e18, + debt: 22.728719829841718804 * 1e18, collateral: 2 * 1e18, - bond: 0.227287198298417188 * 1e18, - transferAmount: 0.227287198298417188 * 1e18 + bond: 0.345029692224734546 * 1e18, + transferAmount: 0.345029692224734546 * 1e18 }); _assertAuction( @@ -301,96 +301,34 @@ contract ERC721PoolLiquidationsKickTest is ERC721HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.227287198298417188 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.345029692224734546 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.917184843435912074 * 1e18, - totalBondEscrowed: 0.227287198298417188 * 1e18, - auctionPrice: 381.842493141340875904 * 1e18, - debtInAuction: 23.012828827714740290 * 1e18, - thresholdPrice: 11.506414413857370145 * 1e18, - neutralPrice: 11.932577910666902372 * 1e18 + referencePrice: 13.089508376044532178 * 1e18, + totalBondEscrowed: 0.345029692224734546 * 1e18, + auctionPrice: 3_350.914144267400237568 * 1e18, + debtInAuction: 22.728719829841718805 * 1e18, + thresholdPrice: 11.364359914920859402 * 1e18, + neutralPrice: 13.089508376044532178 * 1e18 }) ); - assertEq(_poolUtils.momp(address(_pool)), 9.917184843435912074 * 1e18); - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 23.012828827714740290 * 1e18, - borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, - borrowerCollateralization: 0.861883162446546169 * 1e18 - }); - - uint256 snapshot = vm.snapshot(); - - // borrower repays debt in order to exit from auction - _repayDebt({ - from: _borrower, - borrower: _borrower, - amountToRepay: 25 * 1e18, - amountRepaid: 23.012828827714740290 * 1e18, - collateralToPull: 0, - newLup: _priceAt(3696) - }); - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0.227287198298417188 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 0, - neutralPrice: 0 - }) - ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 0, + borrowerDebt: 22.728719829841718805 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 0, - borrowerCollateralization: 1 * 1e18 + borrowert0Np: 11.413817931217071277 * 1e18, + borrowerCollateralization: 0.872656701977127996 * 1e18 }); - vm.revertTo(snapshot); - - // borrower pledge one more NFT to exit from auction uint256[] memory tokenIdsToAdd = new uint256[](1); tokenIdsToAdd[0] = 5; - _pledgeCollateral({ - from: _borrower, - borrower: _borrower, - tokenIds: tokenIdsToAdd - }); - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0.227287198298417188 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 7.670942942571580096 * 1e18, - neutralPrice: 0 - }) - ); - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 23.012828827714740290 * 1e18, - borrowerCollateral: 3 * 1e18, - borrowert0Np: 6.989927127403846156 * 1e18, - borrowerCollateralization: 1.292824743669819254 * 1e18 - }); + // should revert if borrower tries to pledge collateral when in auction + _assertPledgeCollateralAuctionActiveRevert(_borrower, tokenIdsToAdd); + + // should revert if borrower tries to repay debt when in auction + _assertRepayDebtAuctionActiveRevert(_borrower, _borrower, type(uint256).max); } } \ No newline at end of file diff --git a/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsSettle.t.sol b/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsSettle.t.sol index c9bcd5b5b..c57f03711 100644 --- a/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsSettle.t.sol +++ b/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsSettle.t.sol @@ -99,14 +99,14 @@ contract ERC721PoolLiquidationsSettleTest is ERC721HelperContract { borrower: _borrower, borrowerDebt: 5_004.807692307692310000 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, + borrowert0Np: 2_882.277255357846282204 * 1e18, borrowerCollateralization: 1.543977154129479546 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 5_004.807692307692310000 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_751.682692307692308500 * 1e18, + borrowert0Np: 1_921.518170238564188136 * 1e18, borrowerCollateralization: 2.315965731194219318 * 1e18 }); @@ -124,18 +124,18 @@ contract ERC721PoolLiquidationsSettleTest is ERC721HelperContract { from: _lender, index: 2500, borrower: _borrower, - debt: 5_067.367788461538463875 * 1e18, + debt: 5_004.80769230769231 * 1e18, collateral: 2 * 1e18, - bond: 1_501.442307692307693000 * 1e18 + bond: 75.974681840800023439 * 1e18 }); _lenderKick({ from: _lender, index: 2500, borrower: _borrower2, - debt: 5_067.367788461538463875 * 1e18, + debt: 5_004.80769230769231 * 1e18, collateral: 3 * 1e18, - bond: 1_501.442307692307693000 * 1e18 + bond: 75.974681840800023439 * 1e18 }); // skip to make loans clearable @@ -146,8 +146,8 @@ contract ERC721PoolLiquidationsSettleTest is ERC721HelperContract { lup: 3_863.654368867279344664 * 1e18, poolSize: 16_000 * 1e18, pledgedCollateral: 5 * 1e18, - encumberedCollateral: 2.624293841728065377 * 1e18, - poolDebt: 10_139.364366784136304617 * 1e18, + encumberedCollateral: 2.591895152324015187 * 1e18, + poolDebt: 10_014.187028922603757647 * 1e18, actualUtilization: 0, targetUtilization: 1e18, minDebtAmount: 0, @@ -159,21 +159,21 @@ contract ERC721PoolLiquidationsSettleTest is ERC721HelperContract { ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 5_069.682183392068152309 * 1e18, + borrowerDebt: 5_007.093514461301878824 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 1.524219558190194493 * 1e18 + borrowert0Np: 2_882.277255357846282204 * 1e18, + borrowerCollateralization: 1.543272302667571924 * 1e18 }); _assertBorrower({ borrower: _borrower2, - borrowerDebt: 5_069.682183392068152309 * 1e18, + borrowerDebt: 5_007.093514461301878824 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 1_751.682692307692308500 * 1e18, - borrowerCollateralization: 2.286329337285291739 * 1e18 + borrowert0Np: 1_921.518170238564188136 * 1e18, + borrowerCollateralization: 2.314908454001357886 * 1e18 }); - assertEq(_quote.balanceOf(address(_pool)), 9_002.884615384615386000 * 1e18); // increased by bonds size - assertEq(_quote.balanceOf(_lender), 100_997.115384615384614000 * 1e18); // decreased by bonds size + assertEq(_quote.balanceOf(address(_pool)), 6_151.949363681600046878 * 1e18); // increased by bonds size + assertEq(_quote.balanceOf(_lender), 103_848.050636318399953122 * 1e18); // decreased by bonds size assertEq(_quote.balanceOf(_borrower), 5_100 * 1e18); assertEq(_quote.balanceOf(_borrower2), 13_000 * 1e18); } @@ -185,15 +185,15 @@ contract ERC721PoolLiquidationsSettleTest is ERC721HelperContract { borrower: _borrower2, active: true, kicker: _lender, - bondSize: 1_501.442307692307693000 * 1e18, - bondFactor: 0.3 * 1e18, + bondSize: 75.974681840800023439 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: _startTime, - kickMomp: 3_863.654368867279344664 * 1e18, - totalBondEscrowed: 3_002.884615384615386000 * 1e18, + referencePrice: 1_921.518170238564188136 * 1e18, + totalBondEscrowed: 151.949363681600046878 * 1e18, auctionPrice: 0, - debtInAuction: 10_134.735576923076927750 * 1e18, - thresholdPrice: 1_689.894061130689384103 * 1e18, - neutralPrice: 1_751.682692307692308500 * 1e18 + debtInAuction: 10_009.615384615384620000 * 1e18, + thresholdPrice: 1_669.031171487100626274 * 1e18, + neutralPrice: 1_921.518170238564188136 * 1e18 }) ); @@ -209,7 +209,7 @@ contract ERC721PoolLiquidationsSettleTest is ERC721HelperContract { from: _lender, borrower: _borrower2, maxDepth: 1, - settledDebt: 5_067.367788461538463875 * 1e18 + settledDebt: 5_004.807692307692310000 * 1e18 }); _assertAuction( @@ -220,10 +220,10 @@ contract ERC721PoolLiquidationsSettleTest is ERC721HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 3_002.884615384615386000 * 1e18, + referencePrice: 0, + totalBondEscrowed: 151.949363681600046878 * 1e18, auctionPrice: 0, - debtInAuction: 5_069.682183392068152309 * 1e18, + debtInAuction: 5_007.093514461301878824 * 1e18, thresholdPrice: 0, neutralPrice: 0 }) @@ -242,14 +242,14 @@ contract ERC721PoolLiquidationsSettleTest is ERC721HelperContract { from: _lender, borrower: _borrower, maxDepth: 5, - settledDebt: 5_067.367788461538463875 * 1e18 + settledDebt: 5_004.807692307692310000 * 1e18 }); _assertPool( PoolParams({ htp: 0, lup: MAX_PRICE, - poolSize: 5_864.570104597764159383 * 1e18, + poolSize: 5_989.698868738532498354 * 1e18, pledgedCollateral: 1 * 1e18, encumberedCollateral: 0, poolDebt: 0, @@ -270,8 +270,8 @@ contract ERC721PoolLiquidationsSettleTest is ERC721HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 3_002.884615384615386000 * 1e18, + referencePrice: 0, + totalBondEscrowed: 151.949363681600046878 * 1e18, auctionPrice: 0, debtInAuction: 0, thresholdPrice: 0, @@ -282,27 +282,27 @@ contract ERC721PoolLiquidationsSettleTest is ERC721HelperContract { borrower: _borrower, borrowerDebt: 0, borrowerCollateral: 0, - borrowert0Np: 2_627.524038461538462750 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 0, borrowerCollateral: 1 * 1e18, - borrowert0Np: 1_751.682692307692308500 * 1e18, + borrowert0Np: 0 * 1e18, borrowerCollateralization: 1 * 1e18 }); // assert bucket used for settle _assertBucket({ index: MAX_FENWICK_INDEX, - lpBalance: 0.000000137345389190 * 1e18, - collateral: 1.375706158271934622 * 1e18, + lpBalance: 0.000000140579953912 * 1e18, + collateral: 1.408104847675984812 * 1e18, deposit: 0, - exchangeRate: 1.000000000005475091 * 1e18 + exchangeRate: 0.999999999995447280 * 1e18 }); - assertEq(_quote.balanceOf(address(_pool)), 9_002.884615384615386000 * 1e18); - assertEq(_quote.balanceOf(_lender), 100_997.115384615384614000 * 1e18); + assertEq(_quote.balanceOf(address(_pool)), 6_151.949363681600046878 * 1e18); + assertEq(_quote.balanceOf(_lender), 103_848.050636318399953122 * 1e18); assertEq(_quote.balanceOf(_borrower), 5_100 * 1e18); assertEq(_quote.balanceOf(_borrower2), 13_000 * 1e18); @@ -311,7 +311,7 @@ contract ERC721PoolLiquidationsSettleTest is ERC721HelperContract { from: _lender, amount: 100 * 1e18, index: MAX_FENWICK_INDEX, - lpAward: 99.999999999452490925 * 1e18, + lpAward: 100.000000000455272058 * 1e18, newLup: MAX_PRICE }); @@ -365,96 +365,11 @@ contract ERC721PoolLiquidationsSettleTest is ERC721HelperContract { _assertBucket({ index: 2500, - lpBalance: 4_863.128335182565063307 * 1e18, + lpBalance: 4_988.244512154526666083 * 1e18, collateral: 0, - deposit: 4_864.324200136395380383 * 1e18, - exchangeRate: 1.000245904461368780 * 1e18 - }); - } - - function testKickAndSettleSubsetPoolByRepay() external tearDown { - // before auction settle: NFTs pledged by auctioned borrower are owned by the pool - assertEq(_collateral.ownerOf(51), address(_pool)); - assertEq(_collateral.ownerOf(53), address(_pool)); - assertEq(_collateral.ownerOf(73), address(_pool)); - - // borrower 2 repays debt and settles auction - _repayDebtNoLupCheck({ - from: _borrower2, - borrower: _borrower2, - amountToRepay: 6_000 * 1e18, - amountRepaid: 0, - collateralToPull: 3 - }); - - _assertAuction( - AuctionParams({ - borrower: _borrower2, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 3_002.884615384615386000 * 1e18, - auctionPrice: 0, - debtInAuction: 5_069.682183392068152309 * 1e18, - thresholdPrice: 0, - neutralPrice: 0 - }) - ); - _assertBorrower({ - borrower: _borrower2, - borrowerDebt: 0, - borrowerCollateral: 0, - borrowert0Np: 0, - borrowerCollateralization: 1 * 1e18 + deposit: 4_989.456000134711482354 * 1e18, + exchangeRate: 1.000242868603821017 * 1e18 }); - - // after settle: NFTs pledged by auctioned borrower are owned by the borrower - assertEq(_collateral.ownerOf(51), address(_borrower2)); - assertEq(_collateral.ownerOf(53), address(_borrower2)); - assertEq(_collateral.ownerOf(73), address(_borrower2)); - - // before auction settle: NFTs pledged by auctioned borrower are owned by the pool - assertEq(_collateral.ownerOf(1), address(_pool)); - assertEq(_collateral.ownerOf(3), address(_pool)); - - // borrower repays debt and settles auction - _repayDebtNoLupCheck({ - from: _borrower, - borrower: _borrower, - amountToRepay: 6_000 * 1e18, - amountRepaid: 0, - collateralToPull: 2 - }); - - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 3_002.884615384615386000 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 0, - neutralPrice: 0 - }) - ); - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 0, - borrowerCollateral: 0, - borrowert0Np: 0, - borrowerCollateralization: 1 * 1e18 - }); - - // after settle: NFTs pledged by auctioned borrower are owned by the borrower - assertEq(_collateral.ownerOf(1), address(_borrower)); - assertEq(_collateral.ownerOf(3), address(_borrower)); } + } diff --git a/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsSettleAuction.t.sol b/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsSettleAuction.t.sol index 453ce67fa..f03a1350a 100644 --- a/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsSettleAuction.t.sol +++ b/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsSettleAuction.t.sol @@ -97,17 +97,17 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { from: _lender, index: 2500, borrower: _borrower, - debt: 10_190.456508610307854461 * 1e18, + debt: 10_064.648403565736152554 * 1e18, collateral: 2 * 1e18, - bond: 100.646484035657361526 * 1e18 + bond: 152.784783614301553735 * 1e18 }); _lenderKick({ from: _lender, index: 2500, borrower: _borrower2, - debt: 10_203.037319114765024653 * 1e18, + debt: 10_064.648403565736152554 * 1e18, collateral: 3 * 1e18, - bond: 1_325.327386341314188042 * 1e18 + bond: 152.784783614301553735 * 1e18 }); } @@ -149,10 +149,10 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { _assertBorrower({ borrower: _borrower, - borrowerDebt: 10_195.576288428866513838 * 1e18, + borrowerDebt: 10_069.704976226041001321 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.757907990596315111 * 1e18 + borrowert0Np: 2_882.277255357846282204 * 1e18, + borrowerCollateralization: 0.767381840478769050 * 1e18 }); // first settle call settles partial borrower debt @@ -160,24 +160,24 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { from: _lender, borrower: _borrower, maxDepth: 1, - settledDebt: 2_485.576684127234225434 * 1e18 + settledDebt: 2_485.570270210405357279 * 1e18 }); // collateral in bucket used to settle auction increased with the amount used to settle debt _assertBucket({ index: 2499, lpBalance: 5_000 * 1e18, - collateral: 1.287929788232333535 * 1e18, + collateral: 1.287926464788484107 * 1e18, deposit: 0, - exchangeRate: 1.000199226172731231 * 1e18 + exchangeRate: 1.000196645204423177 * 1e18 }); // partial borrower debt is settled, borrower collateral decreased with the amount used to settle debt _assertBorrower({ borrower: _borrower, - borrowerDebt: 5_194.580157565210366847 * 1e18, - borrowerCollateral: 0.712070211767666465 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.529627631336027971 * 1e18 + borrowerDebt: 5_068.721750203925124024 * 1e18, + borrowerCollateral: 0.712073535211515893 * 1e18, + borrowert0Np: 4_074.953051699645482676 * 1e18, + borrowerCollateralization: 0.542781032548108438 * 1e18 }); _assertCollateralInvariants(); @@ -199,7 +199,7 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { from: _lender, borrower: _borrower, maxDepth: 1, - settledDebt: 2_258.399659496838434005 * 1e18 + settledDebt: 2_127.089747762669017517 * 1e18 }); // no token id left in borrower token ids array @@ -212,15 +212,15 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { _assertBucket({ index: 2500, lpBalance: 20_036.073477395793018984 * 1e18, - collateral: 0.712070211767666465 * 1e18, - deposit: 30_548.811547417239049073 * 1e18, - exchangeRate: 1.662002526074875972 * 1e18 + collateral: 0.712073535211515893 * 1e18, + deposit: 30_548.712777641352242710 * 1e18, + exchangeRate: 1.661998237353453822 * 1e18 }); _assertBorrower({ borrower: _borrower, - borrowerDebt: 650.665648223383091746 * 1e18, + borrowerDebt: 789.003620205433623214 * 1e18, borrowerCollateral: 0, - borrowert0Np: 2_627.524038461538462750 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 0 }); @@ -228,14 +228,14 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { from: _lender, borrower: _borrower, maxDepth: 5, - settledDebt: 323.391444837465804436 * 1e18 + settledDebt: 392.147674334617935204 * 1e18 }); _assertBorrower({ borrower: _borrower, borrowerDebt: 0, borrowerCollateral: 0, - borrowert0Np: 2_627.524038461538462750 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1.0 * 1e18 }); @@ -245,36 +245,36 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { from: _lender, borrower: _borrower2, maxDepth: 1, - settledDebt: 5_073.623798076923079263 * 1e18 + settledDebt: 5_004.807692307692310000 * 1e18 }); _assertBucket({ index: 2500, lpBalance: 20_036.073477395793018984 * 1e18, - collateral: 3.354170784195916811 * 1e18, - deposit: 19_689.982479544706885705 * 1e18, - exchangeRate: 1.629527817447087792 * 1e18 + collateral: 3.318337971638889847 * 1e18, + deposit: 19_690.004181209877611641 * 1e18, + exchangeRate: 1.622619083494012841 * 1e18 }); _assertBucket({ index: 2499, lpBalance: 5_000 * 1e18, - collateral: 1.287929788232333535 * 1e18, + collateral: 1.287926464788484107 * 1e18, deposit: 0, - exchangeRate: 1.000199226172731231 * 1e18 + exchangeRate: 1.000196645204423177 * 1e18 }); _assertBucket({ index: 7388, - lpBalance: 99.984931542573546395 * 1e18, - collateral: 0.357899427571749654 * 1e18, - deposit: 100.004851122084218862 * 1e18, - exchangeRate: 1.000199226172731231 * 1e18 + lpBalance: 99.984931546150681783 * 1e18, + collateral: 0.393735563572626046 * 1e18, + deposit: 100.004593064144716734 * 1e18, + exchangeRate: 1.000196645204423177 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 0, borrowerCollateral: 0, - borrowert0Np: 1_769.243311298076895206 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); @@ -314,10 +314,10 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { _assertBucket({ index: 2500, - lpBalance: 15_976.708867181974059418 * 1e18, - collateral: 1.642100572428250346 * 1e18, - deposit: 19_689.982479544706885705 * 1e18, - exchangeRate: 1.629527817447087792 * 1e18 + lpBalance: 15_959.417125063160793398 * 1e18, + collateral: 1.606264436427373954 * 1e18, + deposit: 19_690.004181209877611641 * 1e18, + exchangeRate: 1.622619083494012841 * 1e18 }); _assertBucket({ index: 2499, @@ -328,23 +328,23 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { }); _assertBucket({ index: MAX_FENWICK_INDEX, - lpBalance: 99.984931542573546395 * 1e18, - collateral: 0.357899427571749654 * 1e18, - deposit: 100.004851122084218862 * 1e18, - exchangeRate: 1.000199226172731231 * 1e18 + lpBalance: 99.984931546150681783 * 1e18, + collateral: 0.393735563572626046 * 1e18, + deposit: 100.004593064144716734 * 1e18, + exchangeRate: 1.000196645204423177 * 1e18 }); _assertBorrower({ borrower: _borrower, borrowerDebt: 0, borrowerCollateral: 0, - borrowert0Np: 2_627.524038461538462750 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 0, borrowerCollateral: 0, - borrowert0Np: 1_769.243311298076895206 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); @@ -365,7 +365,6 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { } function testDepositTakeAndSettleSubsetPool() external tearDown { - // the 2 token ids are owned by borrower before settle assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 0), 1); assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 1), 3); @@ -379,10 +378,10 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { }); _assertBorrower({ borrower: _borrower, - borrowerDebt: 10_190.456508610307854462 * 1e18, + borrowerDebt: 10_064.648403565736152555 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.747027241552026434 * 1e18 + borrowert0Np: 2_882.277255357846282204 * 1e18, + borrowerCollateralization: 0.756365082071426765 * 1e18 }); skip(32 hours); @@ -400,419 +399,103 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { _assertBucket({ index: 2502, - lpBalance: 3_843.535428786683406029 * 1e18, - collateral: 1.669877888034002475 * 1e18, - deposit: 0, - exchangeRate: 1.661957717681079631 * 1e18 + lpBalance: 3_863.757250427550337858 * 1e18, + collateral: 1.678659796633077181 * 1e18, + deposit: 0.000000000000002754 * 1e18, + exchangeRate: 1.661954009450878778 * 1e18 }); _assertBorrower({ borrower: _borrower, - borrowerDebt: 4_582.063964428011899646 * 1e18, - borrowerCollateral: 0.330122111965997525 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.276978254692862222 * 1e18 + borrowerDebt: 3_742.762708953482933471 * 1e18, + borrowerCollateral: 0.321340203366922819 * 1e18, + borrowert0Np: 6_669.712537943716399889 * 1e18, + borrowerCollateralization: 0.330069182462081655 * 1e18 }); _assertCollateralInvariants(); - // borrower tries to repay remaining debt - _repayDebtNoLupCheck({ - from: _borrower2, - borrower: _borrower2, - amountToRepay: 1000 * 1e18, - amountRepaid: 0, - collateralToPull: 0 - }); - skip(80 hours); + // settle auction 1 _settle({ from: _lender, borrower: _borrower, maxDepth: 2, - settledDebt: 2_278.046992473852091989 * 1e18 + settledDebt: 1_860.774838340588348583 * 1e18 }); - _assertBucket({ index: 2500, lpBalance: 8_000 * 1e18, - collateral: 0.330122111965997525 * 1e18, - deposit: 11_222.172625306604949654 * 1e18, - exchangeRate: 1.562206295682965556 * 1e18 + collateral: 0.321340203366922819 * 1e18, + deposit: 11_084.202409928441579151 * 1e18, + exchangeRate: 1.540718736319969120 * 1e18 }); _assertBucket({ index: 2502, - lpBalance: 3_843.535428786683406029 * 1e18, - collateral: 1.669877888034002475 * 1e18, - deposit: 0, - exchangeRate: 1.661957717681079631 * 1e18 + lpBalance: 3_863.757250427550337858 * 1e18, + collateral: 1.678659796633077181 * 1e18, + deposit: 0.000000000000002755 * 1e18, + exchangeRate: 1.661954009450878778 * 1e18 }); _assertBorrower({ borrower: _borrower, borrowerDebt: 0, borrowerCollateral: 0, - borrowert0Np: 2_627.524038461538462750 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); - // _assertCollateralInvariants(); + _assertCollateralInvariants(); // tokens used to settle auction are moved to pool claimable array assertEq(ERC721Pool(address(_pool)).bucketTokenIds(0), 3); assertEq(ERC721Pool(address(_pool)).bucketTokenIds(1), 1); - // lender merge / removes the other 2 NFTs - uint256[] memory removalIndexes = new uint256[](2); - removalIndexes[0] = 2500; - removalIndexes[1] = 2502; - _mergeOrRemoveCollateral({ - from: _lender, - toIndex: 2502, - noOfNFTsToRemove: 2, - collateralMerged: 2 * 1e18, - removeCollateralAtIndex: removalIndexes, - toIndexLps: 0 - }); - - // the 2 NFTs claimed from pool are owned by lender - assertEq(_collateral.ownerOf(1), _lender); - assertEq(_collateral.ownerOf(3), _lender); - - _assertCollateralInvariants(); - } - - function testDepositTakeAndSettleByPledgeSubsetPool() external tearDown { - - // the 2 token ids are owned by borrower before bucket take - assertEq(ERC721Pool(address(_pool)).totalBorrowerTokens(_borrower), 2); - assertEq(ERC721Pool(address(_pool)).totalBucketTokens(), 0); - assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 0), 1); - assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 1), 3); - - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 10_190.456508610307854462 * 1e18, - borrowerCollateral: 2 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.747027241552026434 * 1e18 - }); - - skip(32 hours); - _addLiquidityNoEventCheck({ - from: _lender, - amount: 3_000 * 1e18, - index: 2502 - }); - - _depositTake({ - from: _lender, - borrower: _borrower, - kicker: _lender, - index: 2502, - collateralArbed: 1.669877888034002475 * 1e18, - quoteTokenAmount: 6_387.793369052686121698 * 1e18, - bondChange: 63.877933690526861217 * 1e18, - isReward: true, - lpAwardTaker: 0, - lpAwardKicker: 38.435354287866834063 * 1e18 - }); - - // after bucket take, token id 3 is moved to pool claimable array (the most recent pledged) - assertEq(ERC721Pool(address(_pool)).totalBorrowerTokens(_borrower), 1); - assertEq(ERC721Pool(address(_pool)).totalBucketTokens(), 1); - assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 0), 1); - assertEq(ERC721Pool(address(_pool)).bucketTokenIds(0), 3); - - _assertBucket({ - index: 2502, - lpBalance: 3_843.535428786683406029 * 1e18, - collateral: 1.669877888034002475 * 1e18, - deposit: 0, - exchangeRate: 1.661957717681079631 * 1e18 - }); - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 4_582.063964428011899646 * 1e18, - borrowerCollateral: 0.330122111965997525 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.276978254692862222 * 1e18 - }); - - _assertCollateralInvariants(); - - // borrower 2 repays entire debt and pulls collateral - _repayDebt({ - from: _borrower2, - borrower: _borrower2, - amountToRepay: 11_000 * 1e18, - amountRepaid: 10_205.087450363250041380 * 1e18, - collateralToPull: 3, - newLup: 3_863.654368867279344664 * 1e18 - }); - - // borrower exits from auction by pledging more collateral - uint256[] memory tokenIdsToAdd = new uint256[](3); - tokenIdsToAdd[0] = 2; - tokenIdsToAdd[1] = 4; - tokenIdsToAdd[2] = 5; - _drawDebtNoLupCheck({ - from: _borrower, - borrower: _borrower, - amountToBorrow: 0, - limitIndex: 0, - tokenIds: tokenIdsToAdd - }); - - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 4_582.063964428011899646 * 1e18, - borrowerCollateral: 3 * 1e18, - borrowert0Np: 801.113192353304652349 * 1e18, - borrowerCollateralization: 2.529637996454456058 * 1e18 - }); - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 1_425.973870376971549568 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 1_527.354654809337299882 * 1e18, - neutralPrice: 0 - }) - ); - - _assertCollateralInvariants(); - - // after settle borrower has 3 token ids (token id 1 saved from auction + pledged token ids 2 and 4) - // most recent token pledged 5 is used to settle the auction hence in pool claimable array - assertEq(ERC721Pool(address(_pool)).totalBorrowerTokens(_borrower), 3); - assertEq(ERC721Pool(address(_pool)).totalBucketTokens(), 2); - assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 0), 1); - assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 1), 2); - assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 2), 4); - assertEq(ERC721Pool(address(_pool)).bucketTokenIds(0), 3); - assertEq(ERC721Pool(address(_pool)).bucketTokenIds(1), 5); - - _assertBucket({ - index: 2502, - lpBalance: 3_843.535428786683406029 * 1e18, - collateral: 1.669877888034002475 * 1e18, - deposit: 0, - exchangeRate: 1.661957717681079631 * 1e18 - }); - _assertBucket({ - index: 6051, - lpBalance: 0.000025941052120484 * 1e18, - collateral: 0.330122111965997525 * 1e18, - deposit: 0, - exchangeRate: 0.999999999999991014 * 1e18 - }); - - // lender adds liquidity in bucket 6051 and merge / removes the other 2 NFTs - _addLiquidityNoEventCheck({ - from: _lender, - amount: 1_000 * 1e18, - index: 6051 - }); - uint256[] memory removalIndexes = new uint256[](2); - removalIndexes[0] = 2502; - removalIndexes[1] = 6051; - _mergeOrRemoveCollateral({ - from: _lender, - toIndex: 6051, - noOfNFTsToRemove: 2, - collateralMerged: 2 * 1e18, - removeCollateralAtIndex: removalIndexes, - toIndexLps: 0 - }); - - // borrower repays entire debt and pulls collateral - _repayDebt({ - from: _borrower, - borrower: _borrower, - amountToRepay: 5_000 * 1e18, - amountRepaid: 4_582.063964428011899646 * 1e18, - collateralToPull: 3, - newLup: MAX_PRICE - }); - // borrower removes tokens from auction price bucket for compensated collateral fraction - _removeAllLiquidity({ - from: _borrower, - amount: 0.000025941052120483 * 1e18, - index: 6051, - newLup: MAX_PRICE, - lpRedeem: 0.000025941052120484 * 1e18 + // settle auction 2 to enable mergeOrRemoveCollateral + _settle({ + from: _lender, + borrower: _borrower2, + maxDepth: 2, + settledDebt: 5_004.80769230769231 * 1e18 }); - - // the 3 NFTs pulled from pool are owned by borrower - assertEq(_collateral.ownerOf(1), _borrower); - assertEq(_collateral.ownerOf(2), _borrower); - assertEq(_collateral.ownerOf(4), _borrower); - // the 2 NFTs claimed from pool are owned by lender - assertEq(_collateral.ownerOf(3), _lender); - assertEq(_collateral.ownerOf(5), _lender); - _assertCollateralInvariants(); - } - - function testDepositTakeAndSettleByRepaySubsetPool() external tearDown { - // the 2 token ids are owned by borrower before bucket take - assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 0), 1); - assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 1), 3); - - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 10_190.456508610307854462 * 1e18, - borrowerCollateral: 2 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.747027241552026434 * 1e18 - }); + // collateral in buckets: + // 2500 - 2.928128325437681102 + // 2502 - 1.678659796633077182 + // 7388 - 0.393211877929241716 - skip(32 hours); + // lender deposits quote token into 7388 to merge from that bucket _addLiquidityNoEventCheck({ from: _lender, - amount: 3_000 * 1e18, - index: 2502 - }); - - _depositTake({ - from: _lender, - borrower: _borrower, - kicker: _lender, - index: 2502, - collateralArbed: 1.669877888034002475 * 1e18, - quoteTokenAmount: 6_387.793369052686121698 * 1e18, - bondChange: 63.877933690526861217 * 1e18, - isReward: true, - lpAwardTaker: 0, - lpAwardKicker: 38.435354287866834063 * 1e18 + amount: 1 * 1e18, + index: 7388 }); - _assertBucket({ - index: 2502, - lpBalance: 3_843.535428786683406029 * 1e18, - collateral: 1.669877888034002475 * 1e18, - deposit: 0, - exchangeRate: 1.661957717681079631 * 1e18 - }); - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 4_582.063964428011899646 * 1e18, - borrowerCollateral: 0.330122111965997525 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.276978254692862222 * 1e18 - }); - - _assertCollateralInvariants(); - - // borrower 2 repays entire debt and pulls collateral - _repayDebt({ - from: _borrower2, - borrower: _borrower2, - amountToRepay: 11_000 * 1e18, - amountRepaid: 10_205.087450363250041380 * 1e18, - collateralToPull: 3, - newLup: 3_863.654368867279344664 * 1e18 - }); - // borrower exits from auction by repaying the debt - _repayDebt({ - from: _borrower, - borrower: _borrower, - amountToRepay: 5_000 * 1e18, - amountRepaid: 4_582.063964428011899646 * 1e18, - collateralToPull: 0, - newLup: MAX_PRICE - }); - - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 0, - borrowerCollateral: 0, - borrowert0Np: 0, - borrowerCollateralization: 1 * 1e18 - }); - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 1_425.973870376971549568 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 0, - neutralPrice: 0 - }) - ); - - _assertCollateralInvariants(); - - // tokens used to settle auction are moved to pool claimable array - assertEq(ERC721Pool(address(_pool)).bucketTokenIds(0), 3); - assertEq(ERC721Pool(address(_pool)).bucketTokenIds(1), 1); - - _assertBucket({ - index: 2502, - lpBalance: 3_843.535428786683406029 * 1e18, - collateral: 1.669877888034002475 * 1e18, - deposit: 0, - exchangeRate: 1.661957717681079631 * 1e18 - }); - _assertBucket({ - index: 6051, - lpBalance: 0.000025941052120484 * 1e18, - collateral: 0.330122111965997525 * 1e18, - deposit: 0, - exchangeRate: 0.999999999999991014 * 1e18 - }); - - // lender adds liquidity in bucket 6051 and merge / removes the other 2 NFTs - _addLiquidityNoEventCheck({ - from: _lender, - amount: 1_000 * 1e18, - index: 6051 - }); - uint256[] memory removalIndexes = new uint256[](2); - removalIndexes[0] = 2502; - removalIndexes[1] = 6051; + // lender merge / removes available NFTs + uint256[] memory removalIndexes = new uint256[](3); + removalIndexes[0] = 2500; + removalIndexes[1] = 2502; + removalIndexes[2] = 7388; _mergeOrRemoveCollateral({ from: _lender, - toIndex: 6051, - noOfNFTsToRemove: 2, - collateralMerged: 2 * 1e18, + toIndex: 7388, + noOfNFTsToRemove: 5, + collateralMerged: 5 * 1e18, removeCollateralAtIndex: removalIndexes, toIndexLps: 0 }); - // the 2 NFTs claimed from pool are owned by lender - assertEq(_collateral.ownerOf(3), _lender); - assertEq(_collateral.ownerOf(1), _lender); + // NFTs claimed from pool are owned by lender + assertEq(_collateral.ownerOf(1), _lender); + assertEq(_collateral.ownerOf(51), _lender); + assertEq(_collateral.ownerOf(53), _lender); + assertEq(_collateral.ownerOf(73), _lender); _assertCollateralInvariants(); - - // borrower removes tokens from auction price bucket for compensated collateral fraction - _removeAllLiquidity({ - from: _borrower, - amount: 0.000025941052120483 * 1e18, - index: 6051, - newLup: MAX_PRICE, - lpRedeem: 0.000025941052120484 * 1e18 - }); - } function testDepositTakeAndSettleByRegularTakeSubsetPool() external tearDown { - // the 2 token ids are owned by borrower before bucket take assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 0), 1); assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 1), 3); @@ -826,10 +509,10 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { }); _assertBorrower({ borrower: _borrower, - borrowerDebt: 10_190.456508610307854462 * 1e18, + borrowerDebt: 10_064.648403565736152555 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.747027241552026434 * 1e18 + borrowert0Np: 2_882.277255357846282204 * 1e18, + borrowerCollateralization: 0.756365082071426765 * 1e18 }); skip(4 hours); @@ -845,8 +528,8 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { kicker: _lender, index: 2000, collateralArbed: 0.021378186081598093 * 1e18, - quoteTokenAmount: 999.9999999999999908 * 1e18, - bondChange: 9.999999999999999908 * 1e18, + quoteTokenAmount: 999.999999999999990800 * 1e18, + bondChange: 15.180339887498947860 * 1e18, isReward: false, lpAwardTaker: 0, lpAwardKicker: 0 @@ -856,45 +539,35 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { index: 2000, lpBalance: 1_000 * 1e18, collateral: 0.021378186081598093 * 1e18, - deposit: 9203, + deposit: 0.000000000000009201 * 1e18, exchangeRate: 1.000000000000000001 * 1e18 }); _assertBorrower({ borrower: _borrower, - borrowerDebt: 9_904.062307087997104829 * 1e18, + borrowerDebt: 9_087.671681713557968897 * 1e18, borrowerCollateral: 1.978621813918401907 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.760412964078541435 * 1e18 + borrowert0Np: 2_630.547032872719470290 * 1e18, + borrowerCollateralization: 0.832868255733566506 * 1e18 }); _assertCollateralInvariants(); assertEq(_quote.balanceOf(_borrower), 5_100 * 1e18); - assertEq(_quote.balanceOf(address(_pool)), 5_425.973870376971549568 * 1e18); + assertEq(_quote.balanceOf(address(_pool)), 4_305.569567228603107470 * 1e18); // borrower exits from auction by regular take _take({ from: _lender, borrower: _borrower, - maxCollateral: 1, - bondChange: 90.646484035657361618 * 1e18, - givenAmount: 9_904.062307087997104828 * 1e18, - collateralTaken: 0.468592638026133319 * 1e18, + maxCollateral: 2, + bondChange: 137.604443726802605875 * 1e18, + givenAmount: 9_299.424314491640485936 * 1e18, + collateralTaken: 0.802193429456335794 * 1e18, isReward: false }); - assertEq(_quote.balanceOf(_borrower), 16_331.699340400048807627 * 1e18); - assertEq(_quote.balanceOf(address(_pool)), 15_330.036177464968654396 * 1e18); - - // borrower 2 repays entire debt and pulls collateral - _repayDebt({ - from: _borrower2, - borrower: _borrower2, - amountToRepay: 11_000 * 1e18, - amountRepaid: 10_203.293562995691294053 * 1e18, - collateralToPull: 3, - newLup: MAX_PRICE - }); + assertEq(_quote.balanceOf(_borrower), 7_393.071925217111242444 * 1e18); + assertEq(_quote.balanceOf(address(_pool)), 13_604.993881720243593406 * 1e18); _assertBorrower({ borrower: _borrower, @@ -903,6 +576,7 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); + // auction 2 still ongoing _assertAuction( AuctionParams({ borrower: _borrower, @@ -911,10 +585,10 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 1_325.327386341314188042 * 1e18, + referencePrice: 0, + totalBondEscrowed: 152.784783614301553735 * 1e18, auctionPrice: 0, - debtInAuction: 0, + debtInAuction: 10064.901171882309537906 * 1e18, thresholdPrice: 0, neutralPrice: 0 }) @@ -925,26 +599,29 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { // remaining token is moved to pool claimable array assertEq(ERC721Pool(address(_pool)).bucketTokenIds(0), 1); + // buckets with collateral + // 2000 - 0.021876321065491412 + // 2279 - 0.978123678934508588 _assertBucket({ index: 2000, lpBalance: 1_000 * 1e18, collateral: 0.021378186081598093 * 1e18, - deposit: 9203, + deposit: 0.000000000000009201 * 1e18, exchangeRate: 1.000000000000000001 * 1e18 }); _assertBucket({ - index: 2159, - lpBalance: 20_712.867160884608174886 * 1e18, + index: 2279, + lpBalance: 11_384.469793445698921143 * 1e18, collateral: 0.978621813918401907 * 1e18, deposit: 0, - exchangeRate: 1.000000000000000001 * 1e18 + exchangeRate: 1 * 1e18 }); // lender adds liquidity in bucket 2159 and merge / removes remaining NFTs _addLiquidityNoEventCheck({ from: _lender, amount: 40_000 * 1e18, - index: 2159 + index: 2279 }); _addLiquidityNoEventCheck({ from: _lender, @@ -953,10 +630,10 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { }); uint256[] memory removalIndexes = new uint256[](2); removalIndexes[0] = 2000; - removalIndexes[1] = 2159; + removalIndexes[1] = 2279; _mergeOrRemoveCollateral({ from: _lender, - toIndex: 2159, + toIndex: 2279, noOfNFTsToRemove: 1, collateralMerged: 1 * 1e18, removeCollateralAtIndex: removalIndexes, @@ -967,108 +644,64 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { assertEq(_collateral.ownerOf(3), _lender); assertEq(_collateral.ownerOf(1), _lender); - _assertCollateralInvariants(); - - // borrower removes tokens from auction price bucket for compensated collateral fraction - _removeAllLiquidity({ - from: _borrower, - amount: 20_712.867160884608174886 * 1e18, - index: 2159, - newLup: MAX_PRICE, - lpRedeem: 20_712.867160884608174886 * 1e18 - }); - } - - function testDepositTakeAndSettleByBucketTakeSubsetPool() external tearDown { - // the 2 token ids are owned by borrower before settle - assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 0), 1); - assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 1), 3); - + // ensure no collateral in buckets _assertBucket({ - index: 2502, - lpBalance: 2_000 * 1e18, + index: 2000, + lpBalance: 40_000.000000000000009178 * 1e18, collateral: 0, - deposit: 3_323.342955252103772000 * 1e18, - exchangeRate: 1.661671477626051886 * 1e18 - }); - - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 10_190.456508610307854462 * 1e18, - borrowerCollateral: 2 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.747027241552026434 * 1e18 - }); - - skip(32 hours); - - _depositTake({ - from: _lender, - borrower: _borrower, - kicker: _lender, - index: 2502, - collateralArbed: 0.877705109111459100 * 1e18, - quoteTokenAmount: 3_357.490338749655817817 * 1e18, - bondChange: 33.574903387496558178 * 1e18, - isReward: true, - lpAwardTaker: 0, - lpAwardKicker: 20.202020202020202017 * 1e18 + deposit: 40_000.000000000000009201 * 1e18, + exchangeRate: 1.000000000000000001 * 1e18 }); - _assertBucket({ - index: 2502, - lpBalance: 2_020.202020202020202017 * 1e18, - collateral: 0.877705109111459100 * 1e18, - deposit: 362, - exchangeRate: 1.661957717681079631 * 1e18 - }); - _assertBorrower({ - borrower: _borrower, - borrowerDebt: 7_582.063964428011900489 * 1e18, - borrowerCollateral: 1.122294890888540900 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.563403610033938441 * 1e18 + index: 2279, + lpBalance: 40_000.000000000000000001 * 1e18, + collateral: 0, + deposit: 40_000.000000000000000000 * 1e18, + exchangeRate: 1 * 1e18 }); _assertCollateralInvariants(); - // borrower 2 repays entire debt and pulls collateral - _repayDebt({ - from: _borrower2, - borrower: _borrower2, - amountToRepay: 11_000 * 1e18, - amountRepaid: 10_205.087450363250041380 * 1e18, - collateralToPull: 3, - newLup: 3_863.654368867279344664 * 1e18 + // borrower removes tokens from auction price bucket for compensated collateral fraction + _removeAllLiquidity({ + from: _borrower, + amount: 11_384.469793445698921142 * 1e18, + index: 2279, + newLup: _priceAt(2000), + lpRedeem: 11_384.469793445698921143 * 1e18 }); - // borrower exits from auction by bucket take: lender adds quote token at a higher priced bucket and calls deposit take - _addLiquidityNoEventCheck({ - from: _lender, - amount: 40_000 * 1e18, - index: 2000 + // borrower2 exits from auction by deposit take + skip(3 hours); + _assertBucket({ + index: 2500, + lpBalance: 8_000.000000000000000000 * 1e18, + collateral: 0 * 1e18, + deposit: 13_293.654327999447280000 * 1e18, + exchangeRate: 1.661706790999930910 * 1e18 }); _depositTake({ from: _lender, - borrower: _borrower, + borrower: _borrower2, kicker: _lender, - index: 2000, - collateralArbed: 0.163728054862748873 * 1e18, - quoteTokenAmount: 7_658.650469119203939887 * 1e18, - bondChange: 76.586504691192039399 * 1e18, + index: 2500, + collateralArbed: 2.645225595891871889 * 1e18, + quoteTokenAmount: 10_220.237430207183199580 * 1e18, + bondChange: 155.146677921483848824 * 1e18, isReward: true, lpAwardTaker: 0, - lpAwardKicker: 76.586504691192039399 * 1e18 + lpAwardKicker: 93.365678971373374698 * 1e18 }); - + _assertCollateralInvariants(); _assertBorrower({ - borrower: _borrower, + borrower: _borrower2, borrowerDebt: 0, borrowerCollateral: 0, borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); + _assertAuction( AuctionParams({ borrower: _borrower, @@ -1077,8 +710,8 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 1_425.973870376971549568 * 1e18, + referencePrice: 0, + totalBondEscrowed: 152.784783614301553735 * 1e18, auctionPrice: 0, debtInAuction: 0, thresholdPrice: 0, @@ -1086,68 +719,68 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { }) ); - _assertCollateralInvariants(); - - // tokens used to settle auction are moved to pool claimable array - assertEq(ERC721Pool(address(_pool)).bucketTokenIds(0), 3); - assertEq(ERC721Pool(address(_pool)).bucketTokenIds(1), 1); - - _assertBucket({ - index: 2000, - lpBalance: 40_076.586504691192039399 * 1e18, - collateral: 0.163728054862748873 * 1e18, - deposit: 32_417.936035571988099513 * 1e18, - exchangeRate: 1.000000000000000001 * 1e18 - }); + // lender removes collateral _assertBucket({ - index: 6051, - lpBalance: 0.000075324346213057 * 1e18, - collateral: 0.958566836025792027 * 1e18, - deposit: 0, - exchangeRate: 0.999999999999996900 * 1e18 + index: 2500, + lpBalance: 8_093.365678971373374698 * 1e18, + collateral: 2.645225595891871889 * 1e18, + deposit: 3_228.588863672794087920 * 1e18, + exchangeRate: 1.661709951994811681 * 1e18 }); - - // lender adds liquidity in bucket 6051 and merge / removes the other 2 NFTs _addLiquidityNoEventCheck({ from: _lender, - amount: 1_000 * 1e18, - index: 6051 + amount: 10_000 * 1e18, + index: 2569 }); - uint256[] memory removalIndexes = new uint256[](3); - removalIndexes[0] = 2000; - removalIndexes[1] = 2502; - removalIndexes[2] = 6051; + _assertBucket({ + index: 2569, + lpBalance: 10_971.610695426638179656 * 1e18, + collateral: 0.354774404108128111 * 1e18, + deposit: 10_000.000000000000000000 * 1e18, + exchangeRate: 1 * 1e18 + }); + removalIndexes[0] = 2500; + removalIndexes[1] = 2569; _mergeOrRemoveCollateral({ from: _lender, - toIndex: 6051, - noOfNFTsToRemove: 2, - collateralMerged: 2 * 1e18, + toIndex: 2569, + noOfNFTsToRemove: 3, + collateralMerged: 3 * 1e18, removeCollateralAtIndex: removalIndexes, toIndexLps: 0 }); - - // the 2 NFTs claimed from pool are owned by lender - assertEq(_collateral.ownerOf(3), _lender); - assertEq(_collateral.ownerOf(1), _lender); - - _assertCollateralInvariants(); - - // borrower removes tokens from auction price bucket for compensated collateral fraction + _assertBucket({ + index: 2500, + lpBalance: 1_942.931652901886597757 * 1e18, + collateral: 0, + deposit: 3_228.588863672794087920 * 1e18, + exchangeRate: 1.661709951994811681 * 1e18 + }); + _assertBucket({ + index: 2569, + lpBalance: 10_000.000000000000000004 * 1e18, + collateral: 0, + deposit: 10_000.000000000000000000 * 1e18, + exchangeRate: 1 * 1e18 + }); + // borrower 2 redeems LP for quote token _removeAllLiquidity({ - from: _borrower, - amount: 0.000075324346213056 * 1e18, - index: 6051, + from: _borrower2, + amount: 971.610695426638179651 * 1e18, + index: 2569, newLup: MAX_PRICE, - lpRedeem: 0.000075324346213057 * 1e18 + lpRedeem: 971.610695426638179652 * 1e18 }); } - function testDepositTakeAndSettleBySettleSubsetPool() external tearDown { - + function testDepositTakeAndSettleByBucketTakeSubsetPool() external tearDown { // the 2 token ids are owned by borrower before settle assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 0), 1); assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower, 1), 3); + // 1 token id is owned by borrower 2 before settle + assertEq(ERC721Pool(address(_pool)).borrowerTokenIds(_borrower2, 2), 73); + _assertBucket({ index: 2502, lpBalance: 2_000 * 1e18, @@ -1158,10 +791,10 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { _assertBorrower({ borrower: _borrower, - borrowerDebt: 10_190.456508610307854462 * 1e18, + borrowerDebt: 10_064.648403565736152555 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.747027241552026434 * 1e18 + borrowert0Np: 2_882.277255357846282204 * 1e18, + borrowerCollateralization: 0.756365082071426765 * 1e18 }); skip(32 hours); @@ -1171,56 +804,57 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { borrower: _borrower, kicker: _lender, index: 2502, - collateralArbed: 0.877705109111459100 * 1e18, - quoteTokenAmount: 3_357.490338749655817817 * 1e18, - bondChange: 33.574903387496558178 * 1e18, + collateralArbed: 0.882320037286956004 * 1e18, + quoteTokenAmount: 3_375.143849709550192592 * 1e18, + bondChange: 51.235830807792639427 * 1e18, isReward: true, lpAwardTaker: 0, - lpAwardKicker: 20.202020202020202017 * 1e18 + lpAwardKicker: 30.828669455613465562 * 1e18 }); _assertBucket({ index: 2502, - lpBalance: 2_020.202020202020202017 * 1e18, - collateral: 0.877705109111459100 * 1e18, - deposit: 362, - exchangeRate: 1.661957717681079631 * 1e18 + lpBalance: 2_030.828669455613465562 * 1e18, + collateral: 0.882320037286956004 * 1e18, + deposit: 0.000000000000000834 * 1e18, + exchangeRate: 1.661954009450878778 * 1e18 }); _assertBorrower({ borrower: _borrower, - borrowerDebt: 7_582.063964428011900489 * 1e18, - borrowerCollateral: 1.122294890888540900 * 1e18, - borrowert0Np: 2_627.524038461538462750 * 1e18, - borrowerCollateralization: 0.563403610033938441 * 1e18 + borrowerDebt: 6_742.762708953482931550 * 1e18, + borrowerCollateral: 1.117679962713043996 * 1e18, + borrowert0Np: 3_454.620119359940588354 * 1e18, + borrowerCollateralization: 0.630927812552385529 * 1e18 }); _assertCollateralInvariants(); - // borrower 2 repays entire debt and pulls collateral - _repayDebt({ - from: _borrower2, - borrower: _borrower2, - amountToRepay: 11_000 * 1e18, - amountRepaid: 10_205.087450363250041380 * 1e18, - collateralToPull: 3, - newLup: 3_863.654368867279344664 * 1e18 + // borrowers exits from auction by bucket take: lender adds quote token at a higher priced bucket and calls deposit take + _addLiquidityNoEventCheck({ + from: _lender, + amount: 60_000 * 1e18, + index: 2000 }); - skip(72 hours); - - // borrower exits from auction by pool debt settle - _settle({ - from: _lender, - borrower: _borrower, - maxDepth: 10, - settledDebt: 3_769.545371910961412793 * 1e18 + // bucket take on borrower + _depositTake({ + from: _lender, + borrower: _borrower, + kicker: _lender, + index: 2000, + collateralArbed: 0.146369981971725896 * 1e18, + quoteTokenAmount: 6_846.697910339464805069 * 1e18, + bondChange: 103.935201385981873520 * 1e18, + isReward: true, + lpAwardTaker: 0, + lpAwardKicker: 103.935201385981873519 * 1e18 }); _assertBorrower({ borrower: _borrower, borrowerDebt: 0, borrowerCollateral: 0, - borrowert0Np: 2_627.524038461538462750 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 1 * 1e18 }); _assertAuction( @@ -1231,53 +865,130 @@ contract ERC721PoolLiquidationsSettleAuctionTest is ERC721HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 1_425.973870376971549568 * 1e18, + referencePrice: 0, + totalBondEscrowed: 305.569567228603107470 * 1e18, + auctionPrice: 0, + debtInAuction: 10_066.670727855240484714 * 1e18, + thresholdPrice: 0, + neutralPrice: 0 + }) + ); + _assertBucket({ + index: 5476, + lpBalance: 0.001343248402621047 * 1e18, + collateral: 0.971309980741318100 * 1e18, + deposit: 0, + exchangeRate: 1.000000000000000249 * 1e18 + }); + + // bucket take on borrower 2 + _depositTake({ + from: _lender, + borrower: _borrower2, + kicker: _lender, + index: 2000, + collateralArbed: 0.218524435242978009 * 1e18, + quoteTokenAmount: 10_221.841760049014997661 * 1e18, + bondChange: 155.171032193774512947 * 1e18, + isReward: true, + lpAwardTaker: 0, + lpAwardKicker: 155.171032193774512946 * 1e18 + }); + + _assertBorrower({ + borrower: _borrower2, + borrowerDebt: 0, + borrowerCollateral: 2 * 1e18, + borrowert0Np: 0, + borrowerCollateralization: 1 * 1e18 + }); + _assertAuction( + AuctionParams({ + borrower: _borrower2, + active: false, + kicker: address(0), + bondSize: 0, + bondFactor: 0, + kickTime: 0, + referencePrice: 0, + totalBondEscrowed: 305.569567228603107470 * 1e18, auctionPrice: 0, debtInAuction: 0, thresholdPrice: 0, neutralPrice: 0 }) ); + _assertBucket({ + index: 5557, + lpBalance: 0.000721544103807183 * 1e18, + collateral: 0.781475564757021991 * 1e18, + deposit: 0, + exchangeRate: 0.999999999999999669 * 1e18 + }); _assertCollateralInvariants(); // tokens used to settle auction are moved to pool claimable array assertEq(ERC721Pool(address(_pool)).bucketTokenIds(0), 3); assertEq(ERC721Pool(address(_pool)).bucketTokenIds(1), 1); + assertEq(ERC721Pool(address(_pool)).bucketTokenIds(2), 73); _assertBucket({ - index: 2500, - lpBalance: 8_000 * 1e18, - collateral: 1.122294890888540900 * 1e18, - deposit: 8_218.389542394611030535 * 1e18, - exchangeRate: 1.569318637591693583 * 1e18 - }); - _assertBucket({ - index: 2502, - lpBalance: 2_020.202020202020202017 * 1e18, - collateral: 0.877705109111459100 * 1e18, - deposit: 362, - exchangeRate: 1.661957717681079631 * 1e18 + index: 2000, + lpBalance: 60_259.106233579756386465 * 1e18, + collateral: 0.364894417214703905 * 1e18, + deposit: 43_190.566563191276548531 * 1e18, + exchangeRate: 1.000000000000000001 * 1e18 }); - // lender merge / removes the other 2 NFTs - uint256[] memory removalIndexes = new uint256[](2); - removalIndexes[0] = 2500; + // lender adds liquidity in bucket 6171 and 6252 and merge / removes the other 3 NFTs + _addLiquidityNoEventCheck({ + from: _lender, + amount: 1_000 * 1e18, + index: 5476 + }); + _addLiquidityNoEventCheck({ + from: _lender, + amount: 1_000 * 1e18, + index: 5557 + }); + uint256[] memory removalIndexes = new uint256[](4); + removalIndexes[0] = 2000; removalIndexes[1] = 2502; + removalIndexes[2] = 5476; + removalIndexes[3] = 5557; + _mergeOrRemoveCollateral({ from: _lender, - toIndex: 2502, - noOfNFTsToRemove: 2, - collateralMerged: 2 * 1e18, + toIndex: 6252, + noOfNFTsToRemove: 3, + collateralMerged: 3 * 1e18, removeCollateralAtIndex: removalIndexes, toIndexLps: 0 }); - // the 2 NFTs claimed from pool are owned by lender + // the 3 NFTs claimed from pool are owned by lender assertEq(_collateral.ownerOf(3), _lender); assertEq(_collateral.ownerOf(1), _lender); + assertEq(_collateral.ownerOf(73), _lender); _assertCollateralInvariants(); + + // remove lps for both borrower and borrower 2 + _removeAllLiquidity({ + from: _borrower, + amount: 0.001343248402621047 * 1e18, + index: 5476, + newLup: MAX_PRICE, + lpRedeem: 0.001343248402621047 * 1e18 + }); + + _removeAllLiquidity({ + from: _borrower2, + amount: 0.000721544103807182 * 1e18, + index: 5557, + newLup: MAX_PRICE, + lpRedeem: 0.000721544103807183 * 1e18 + }); } } diff --git a/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsTake.t.sol b/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsTake.t.sol index 2ad9744f3..3bdd8b0f1 100644 --- a/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsTake.t.sol +++ b/tests/forge/unit/ERC721Pool/ERC721PoolLiquidationsTake.t.sol @@ -126,14 +126,14 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { borrower: _borrower, borrowerDebt: 19.819038461538461548 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, + borrowert0Np: 11.413817931217071277 * 1e18, borrowerCollateralization: 1.000773560501591181 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 15.014423076923076930 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 5.255048076923076925 * 1e18, + borrowert0Np: 5.764554510715692564 * 1e18, borrowerCollateralization: 1.981531649793150539 * 1e18 }); @@ -141,7 +141,6 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { } function testTakeCollateralSubsetPool() external tearDown { - // Skip to make borrower undercollateralized skip(1000 days); @@ -153,7 +152,7 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -166,17 +165,17 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { borrower: _borrower, borrowerDebt: 22.728719829841718805 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, + borrowert0Np: 11.413817931217071277 * 1e18, borrowerCollateralization: 0.872656701977127996 * 1e18 }); _kick({ from: _lender, borrower: _borrower, - debt: 23.012828827714740289 * 1e18, + debt: 22.728719829841718804 * 1e18, collateral: 2 * 1e18, - bond: 0.227287198298417188 * 1e18, - transferAmount: 0.227287198298417188 * 1e18 + bond: 0.345029692224734546 * 1e18, + transferAmount: 0.345029692224734546 * 1e18 }); /******************************/ @@ -189,11 +188,11 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { lup: 9.917184843435912074 * 1e18, poolSize: 73_004.346887619919714000 * 1e18, pledgedCollateral: 5 * 1e18, - encumberedCollateral: 4.056751649452525709 * 1e18, - poolDebt: 40.231555971534224232 * 1e18, + encumberedCollateral: 4.028103499563389533 * 1e18, + poolDebt: 39.947446973661202747 * 1e18, actualUtilization: 0.000477170706006322 * 1e18, targetUtilization: 0.786051641950380194 * 1e18, - minDebtAmount: 4.023155597153422423 * 1e18, + minDebtAmount: 3.994744697366120275 * 1e18, loans: 1, maxBorrower: address(_borrower2), interestRate: 0.045 * 1e18, @@ -202,41 +201,41 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 23.012828827714740290 * 1e18, + borrowerDebt: 22.728719829841718805 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, - borrowerCollateralization: 0.861883162446546169 * 1e18 + borrowert0Np: 11.413817931217071277 * 1e18, + borrowerCollateralization: 0.872656701977127996 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 17.218727143819483943 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 5.255048076923076925 * 1e18, + borrowert0Np: 5.764554510715692564 * 1e18, borrowerCollateralization: 1.727860269914713433 * 1e18 }); - assertEq(_quote.balanceOf(_lender), 46_999.772712801701582812 * 1e18); + assertEq(_quote.balanceOf(_lender), 46_999.654970307775265454 * 1e18); _assertAuction( AuctionParams({ borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.227287198298417188 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.345029692224734546 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.917184843435912074 * 1e18, - totalBondEscrowed: 0.227287198298417188 * 1e18, - auctionPrice: 381.842493141340875904 * 1e18, - debtInAuction: 23.012828827714740290 * 1e18, - thresholdPrice: 11.506414413857370145 * 1e18, - neutralPrice: 11.932577910666902372 * 1e18 + referencePrice: 13.089508376044532178 * 1e18, + totalBondEscrowed: 0.345029692224734546 * 1e18, + auctionPrice: 3350.914144267400237568 * 1e18, + debtInAuction: 22.728719829841718805 * 1e18, + thresholdPrice: 11.364359914920859402 * 1e18, + neutralPrice: 13.089508376044532178 * 1e18 }) ); _assertKicker({ kicker: _lender, claimable: 0, - locked: 0.227287198298417188 * 1e18 + locked: 0.345029692224734546 * 1e18 }); skip(5.5 hours); @@ -246,32 +245,33 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { assertEq(_collateral.ownerOf(1), address(_pool)); // before take: check quote token balances of taker and borrower - assertEq(_quote.balanceOf(_lender), 46_999.772712801701582812 * 1e18); + assertEq(_quote.balanceOf(_lender), 46_999.654970307775265454 * 1e18); assertEq(_quote.balanceOf(_borrower), 119.8 * 1e18); + // threshold price increases slightly due to interest _assertAuction( AuctionParams({ borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.227287198298417188 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.345029692224734546 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 5.5 hours, - kickMomp: 9.917184843435912074 * 1e18, - totalBondEscrowed: 0.227287198298417188 * 1e18, - auctionPrice: 16.875213515338743424 * 1e18, - debtInAuction: 23.012828827714740290 * 1e18, - thresholdPrice: 11.506739514062665877 * 1e18, - neutralPrice: 11.932577910666902372 * 1e18 + referencePrice: 13.089508376044532178 * 1e18, + totalBondEscrowed: 0.345029692224734546 * 1e18, + auctionPrice: 15.566136492679870612 * 1e18, + debtInAuction: 22.728719829841718805 * 1e18, + thresholdPrice: 11.364681001543373706 * 1e18, + neutralPrice: 13.089508376044532178 * 1e18 }) ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 23.013479028125331754 * 1e18, + borrowerDebt: 22.729362003086747412 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, - borrowerCollateralization: 0.861858811639550854 * 1e18 + borrowert0Np: 11.413817931217071277 * 1e18, + borrowerCollateralization: 0.872632046785045240 * 1e18 }); uint256 snapshot = vm.snapshot(); @@ -284,25 +284,26 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { from: _lender, borrower: _borrower, maxCollateral: 1, - bondChange: 0.168752135153387434 * 1e18, - givenAmount: 16.875213515338743424 * 1e18, + bondChange: 0.236299242694081216 * 1e18, + givenAmount: 15.566136492679870612 * 1e18, collateralTaken: 1.0 * 1e18, isReward: false }); + // borrower still under liquidation _assertPool( PoolParams({ - htp: 7.749209044755361553 * 1e18, + htp: 5.739737879567360457 * 1e18, lup: 9.917184843435912074 * 1e18, - poolSize: 73_004.347853838043123634 * 1e18, + poolSize: 73_004.347847014760830891 * 1e18, pledgedCollateral: 4 * 1e18, - encumberedCollateral: 2.517692578855560848 * 1e18, - poolDebt: 24.968422683457442926 * 1e18, - actualUtilization: 0.000411524519658268 * 1e18, + encumberedCollateral: 2.494345764818852289 * 1e18, + poolDebt: 24.736888013150079997 * 1e18, + actualUtilization: 0.000411524083711660 * 1e18, targetUtilization: 0.781984313351887130 * 1e18, - minDebtAmount: 1.248421134172872146 * 1e18, - loans: 2, - maxBorrower: address(_borrower), + minDebtAmount: 2.473688801315008000 * 1e18, + loans: 1, + maxBorrower: address(_borrower2), interestRate: 0.045 * 1e18, interestRateUpdate: block.timestamp - 5.5 hours }) @@ -310,26 +311,26 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { _assertBorrower({ borrower: _borrower, - borrowerDebt: 7.749209044755361554 * 1e18, + borrowerDebt: 7.517674374447998626 * 1e18, borrowerCollateral: 1 * 1e18, - borrowert0Np: 7.061045370627448275 * 1e18, - borrowerCollateralization: 1.279767365438131935 * 1e18 + borrowert0Np: 7.550178184893434284 * 1e18, + borrowerCollateralization: 1.319182548946741612 * 1e18 }); _assertAuction( AuctionParams({ borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0.058535063145029754 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 7.749209044755361554 * 1e18, - neutralPrice: 0 + active: true, + kicker: _lender, + bondSize: 0.108730449530653330 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 5.5 hours, + referencePrice: 13.089508376044532178 * 1e18, + totalBondEscrowed: 0.108730449530653330 * 1e18, + auctionPrice: 15.566136492679870612 * 1e18, + debtInAuction: 7.517674374447998626 * 1e18, + thresholdPrice: 7.517674374447998626 * 1e18, + neutralPrice: 13.089508376044532178 * 1e18 }) ); _assertKicker({ @@ -343,7 +344,7 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { assertEq(_collateral.ownerOf(1), address(_pool)); // after take: check quote token balances of taker and borrower - assertEq(_quote.balanceOf(_lender), 46_982.897499286362839388 * 1e18); + assertEq(_quote.balanceOf(_lender), 46_984.088833815095394842 * 1e18); assertEq(_quote.balanceOf(_borrower), 119.8 * 1e18); // no additional tokens as there is no rounding of collateral taken (1) vm.revertTo(snapshot); @@ -356,9 +357,9 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { from: _lender, borrower: _borrower, maxCollateral: 2, - bondChange: 0.227287198298417188 * 1e18, - givenAmount: 24.624422560094104976 * 1e18, - collateralTaken: 1.459206577606363895 * 1e18, // not a rounded collateral, difference of 2 - 1.16 collateral should go to borrower in quote tokens at auction price + bondChange: 0.345029692224734546 * 1e18, + givenAmount: 23.258980855317575086 * 1e18, + collateralTaken: 1.494203835759460320 * 1e18, // not a rounded collateral, difference of 2 - 1.49 collateral should go to borrower in quote tokens at auction price isReward: false }); @@ -366,11 +367,11 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { PoolParams({ htp: 5.739737879567360457 * 1e18, lup: 9.917184843435912074 * 1e18, - poolSize: 73_004.347853838043123634 * 1e18, + poolSize: 73_004.347847014760830891 * 1e18, pledgedCollateral: 3.0 * 1e18, encumberedCollateral: 1.736300564176668638 * 1e18, poolDebt: 17.219213638702081372 * 1e18, - actualUtilization: 0.000411524519658268 * 1e18, + actualUtilization: 0.000411524083711660 * 1e18, targetUtilization: 0.781984313351887130 * 1e18, minDebtAmount: 1.721921363870208137 * 1e18, loans: 1, @@ -396,7 +397,7 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -415,12 +416,11 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { assertEq(_collateral.ownerOf(1), _lender); // after take: check quote token balances of taker and borrower - assertEq(_quote.balanceOf(_lender), 46_966.022285771024095971 * 1e18); - assertEq(_quote.balanceOf(_borrower), 128.926004470583381865 * 1e18); // borrower gets quote tokens from the difference of rounded collateral (2) and needed collateral (1.16) at auction price (19.8) = 16.6 additional tokens + assertEq(_quote.balanceOf(_lender), 46_968.522697322415524242 * 1e18); + assertEq(_quote.balanceOf(_borrower), 127.673292130042166126 * 1e18); // borrower gets quote tokens from the difference of rounded collateral (2) and needed collateral (1.49) at auction price (15.5) = 7.9 additional tokens } function testTakeCollateralAndSettleSubsetPool() external tearDown { - // Skip to make borrower undercollateralized skip(1000 days); @@ -432,7 +432,7 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -444,17 +444,17 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { borrower: _borrower, borrowerDebt: 22.728719829841718805 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, + borrowert0Np: 11.413817931217071277 * 1e18, borrowerCollateralization: 0.872656701977127996 * 1e18 }); _kick({ from: _lender, borrower: _borrower, - debt: 23.012828827714740289 * 1e18, + debt: 22.728719829841718804 * 1e18, collateral: 2 * 1e18, - bond: 0.227287198298417188 * 1e18, - transferAmount: 0.227287198298417188 * 1e18 + bond: 0.345029692224734546 * 1e18, + transferAmount: 0.345029692224734546 * 1e18 }); /******************************/ @@ -467,11 +467,11 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { lup: 9.917184843435912074 * 1e18, poolSize: 73_004.346887619919714000 * 1e18, pledgedCollateral: 5 * 1e18, - encumberedCollateral: 4.056751649452525709 * 1e18, - poolDebt: 40.231555971534224232 * 1e18, + encumberedCollateral: 4.028103499563389533 * 1e18, + poolDebt: 39.947446973661202747 * 1e18, actualUtilization: 0.000477170706006322 * 1e18, targetUtilization: 0.786051641950380194 * 1e18, - minDebtAmount: 4.023155597153422423 * 1e18, + minDebtAmount: 3.994744697366120275 * 1e18, loans: 1, maxBorrower: address(_borrower2), interestRate: 0.045 * 1e18, @@ -480,41 +480,41 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 23.012828827714740290 * 1e18, + borrowerDebt: 22.728719829841718805 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, - borrowerCollateralization: 0.861883162446546169 * 1e18 + borrowert0Np: 11.413817931217071277 * 1e18, + borrowerCollateralization: 0.872656701977127996 * 1e18 }); _assertBorrower({ borrower: _borrower2, borrowerDebt: 17.218727143819483943 * 1e18, borrowerCollateral: 3 * 1e18, - borrowert0Np: 5.255048076923076925 * 1e18, + borrowert0Np: 5.764554510715692564 * 1e18, borrowerCollateralization: 1.727860269914713433 * 1e18 }); - assertEq(_quote.balanceOf(_lender), 46_999.772712801701582812 * 1e18); + assertEq(_quote.balanceOf(_lender), 46_999.654970307775265454 * 1e18); _assertAuction( AuctionParams({ borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.227287198298417188 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.345029692224734546 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.917184843435912074 * 1e18, - totalBondEscrowed: 0.227287198298417188 * 1e18, - auctionPrice: 381.842493141340875904 * 1e18, - debtInAuction: 23.012828827714740290 * 1e18, - thresholdPrice: 11.506414413857370145 * 1e18, - neutralPrice: 11.932577910666902372 * 1e18 + referencePrice: 13.089508376044532178 * 1e18, + totalBondEscrowed: 0.345029692224734546 * 1e18, + auctionPrice: 3_350.914144267400237568 * 1e18, + debtInAuction: 22.728719829841718805 * 1e18, + thresholdPrice: 11.364359914920859402 * 1e18, + neutralPrice: 13.089508376044532178 * 1e18 }) ); _assertKicker({ kicker: _lender, claimable: 0, - locked: 0.227287198298417188 * 1e18 + locked: 0.345029692224734546 * 1e18 }); skip(10 hours); @@ -524,30 +524,30 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { assertEq(_collateral.ownerOf(1), address(_pool)); // before take: check quote token balances of taker - assertEq(_quote.balanceOf(_lender), 46_999.772712801701582812 * 1e18); + assertEq(_quote.balanceOf(_lender), 46_999.654970307775265454 * 1e18); _assertAuction( AuctionParams({ borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.227287198298417188 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.345029692224734546 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 10 hours, - kickMomp: 9.917184843435912074 * 1e18, - totalBondEscrowed: 0.227287198298417188 * 1e18, - auctionPrice: 0.745786119416681408 * 1e18, - debtInAuction: 23.012828827714740290 * 1e18, - thresholdPrice: 11.507005511971773436 * 1e18, - neutralPrice: 11.932577910666902372 * 1e18 + referencePrice: 13.089508376044532178 * 1e18, + totalBondEscrowed: 0.345029692224734546 * 1e18, + auctionPrice: 3.272377094011133044 * 1e18, + debtInAuction: 22.728719829841718805 * 1e18, + thresholdPrice: 11.364943715527677468 * 1e18, + neutralPrice: 13.089508376044532178 * 1e18 }) ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 23.014011023943546872 * 1e18, + borrowerDebt: 22.729887431055354936 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, - borrowerCollateralization: 0.861838888763733724 * 1e18 + borrowert0Np: 11.413817931217071277 * 1e18, + borrowerCollateralization: 0.872611874873280395 * 1e18 }); /**************************************/ @@ -558,8 +558,8 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { from: _lender, borrower: _borrower, maxCollateral: 2, - bondChange: 0.014915722388333628 * 1e18, - givenAmount: 1.491572238833362816 * 1e18, + bondChange: 0.099351593054310196 * 1e18, + givenAmount: 6.544754188022266088 * 1e18, collateralTaken: 2 * 1e18, isReward: true }); @@ -568,20 +568,20 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { assertEq(_collateral.ownerOf(3), _lender); assertEq(_collateral.ownerOf(1), _lender); - // after take : Taker quote token used for buying collateral - assertEq(_quote.balanceOf(_lender), 46_998.281140562868219996 * 1e18); + // after take: Taker quote token used for buying collateral + assertEq(_quote.balanceOf(_lender), 46_993.110216119752999366 * 1e18); _assertPool( PoolParams({ htp: 5.739870563397816903 * 1e18, lup: 9.917184843435912074 * 1e18, - poolSize: 73_004.348644400449318457 * 1e18, + poolSize: 73_004.348631994338166115 * 1e18, pledgedCollateral: 3 * 1e18, - encumberedCollateral: 4.070504644882883983 * 1e18, - poolDebt: 40.367946969368016673 * 1e18, - actualUtilization: 0.000371338408811493 * 1e18, + encumberedCollateral: 3.378387824288349781 * 1e18, + poolDebt: 33.504096526280849753 * 1e18, + actualUtilization: 0.000371337774626592 * 1e18, targetUtilization: 0.778640404875432888 * 1e18, - minDebtAmount: 4.036794696936801667 * 1e18, + minDebtAmount: 3.350409652628084975 * 1e18, loans: 1, maxBorrower: address(_borrower2), interestRate: 0.045 * 1e18, @@ -592,9 +592,9 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { // Borrower collateral is 0 and some debt is still to be paid _assertBorrower({ borrower: _borrower, - borrowerDebt: 23.148335279174565965 * 1e18, + borrowerDebt: 16.284484836087399045 * 1e18, borrowerCollateral: 0, - borrowert0Np: 10.404995192307692312 * 1e18, + borrowert0Np: 0, borrowerCollateralization: 0 }); _assertAuction( @@ -602,22 +602,22 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.242202920686750816 * 1e18, - bondFactor: 0.010000000000000000 * 1e18, + bondSize: 0.444381285279044742 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 10 hours, - kickMomp: 9.917184843435912074 * 1e18, - totalBondEscrowed: 0.242202920686750816 * 1e18, - auctionPrice: 0.745786119416681408 * 1e18, - debtInAuction: 23.148335279174565965 * 1e18, + referencePrice: 13.089508376044532178 * 1e18, + totalBondEscrowed: 0.444381285279044742 * 1e18, + auctionPrice: 3.272377094011133044 * 1e18, + debtInAuction: 16.284484836087399045 * 1e18, thresholdPrice: 0, - neutralPrice: 11.932577910666902372 * 1e18 + neutralPrice: 13.089508376044532178 * 1e18 }) ); // kicker bond is locked as auction is not cleared _assertKicker({ kicker: _lender, claimable: 0, - locked: 0.242202920686750816 * 1e18 + locked: 0.444381285279044742 * 1e18 }); // settle auction @@ -625,7 +625,7 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { from: _lender, borrower: _borrower, maxDepth: 10, - settledDebt: 20.183898781290497858 * 1e18 + settledDebt: 14.199051019135248430 * 1e18 }); _assertAuction( @@ -636,8 +636,8 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0.242202920686750816 * 1e18, + referencePrice: 0, + totalBondEscrowed: 0.444381285279044742 * 1e18, auctionPrice: 0, debtInAuction: 0, thresholdPrice: 0, @@ -646,7 +646,7 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { ); _assertKicker({ kicker: _lender, - claimable: 0.242202920686750816 * 1e18, + claimable: 0.444381285279044742 * 1e18, locked: 0 }); @@ -658,10 +658,10 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { // Kicker claims remaining bond + reward to his own address _pool.withdrawBonds(_lender, type(uint256).max); - assertEq(_quote.balanceOf(_lender), 46_998.423343483554970812 * 1e18); + assertEq(_quote.balanceOf(_lender), 46_993.454597405032044108 * 1e18); } - function testTakeCollateralSubsetPoolAndSettleByRepayAndPledge() external tearDown { + function testTakeCollateralSubsetPoolAndSettleWithDebt() external tearDown { // Skip to make borrower undercollateralized skip(1000 days); @@ -673,7 +673,7 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { bondSize: 0, bondFactor: 0, kickTime: 0, - kickMomp: 0, + referencePrice: 0, totalBondEscrowed: 0, auctionPrice: 0, debtInAuction: 0, @@ -685,40 +685,40 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { borrower: _borrower, borrowerDebt: 22.728719829841718805 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, + borrowert0Np: 11.413817931217071277 * 1e18, borrowerCollateralization: 0.872656701977127996 * 1e18 - }); + }); _kick({ from: _lender, borrower: _borrower, - debt: 23.012828827714740289 * 1e18, + debt: 22.728719829841718804 * 1e18, collateral: 2 * 1e18, - bond: 0.227287198298417188 * 1e18, - transferAmount: 0.227287198298417188 * 1e18 + bond: 0.345029692224734546 * 1e18, + transferAmount: 0.345029692224734546 * 1e18 }); _assertBorrower({ borrower: _borrower, - borrowerDebt: 23.012828827714740290 * 1e18, + borrowerDebt: 22.728719829841718805 * 1e18, borrowerCollateral: 2 * 1e18, - borrowert0Np: 10.404995192307692312 * 1e18, - borrowerCollateralization: 0.861883162446546169 * 1e18 + borrowert0Np: 11.413817931217071277 * 1e18, + borrowerCollateralization: 0.872656701977127996 * 1e18 }); _assertAuction( AuctionParams({ borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.227287198298417188 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.345029692224734546 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp, - kickMomp: 9.917184843435912074 * 1e18, - totalBondEscrowed: 0.227287198298417188 * 1e18, - auctionPrice: 381.842493141340875904 * 1e18, - debtInAuction: 23.012828827714740290 * 1e18, - thresholdPrice: 11.506414413857370145 * 1e18, - neutralPrice: 11.932577910666902372 * 1e18 + referencePrice: 13.089508376044532178 * 1e18, + totalBondEscrowed: 0.345029692224734546 * 1e18, + auctionPrice: 3_350.914144267400237568 * 1e18, + debtInAuction: 22.728719829841718805 * 1e18, + thresholdPrice: 11.364359914920859402 * 1e18, + neutralPrice: 13.089508376044532178 * 1e18 }) ); @@ -729,8 +729,8 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { from: _lender, borrower: _borrower, maxCollateral: 1, - bondChange: 0.000000000000006781 * 1e18, - givenAmount: 0.000000000000678144 * 1e18, + bondChange: 0.000000000000180719 * 1e18, + givenAmount: 0.000000000011904838 * 1e18, collateralTaken: 1 * 1e18, isReward: true }); @@ -740,107 +740,66 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { borrower: _borrower, active: true, kicker: _lender, - bondSize: 0.227287198298423969 * 1e18, - bondFactor: 0.01 * 1e18, + bondSize: 0.345029692224915265 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, kickTime: block.timestamp - 50 hours, - kickMomp: 9.917184843435912074 * 1e18, - totalBondEscrowed: 0.227287198298423969 * 1e18, - auctionPrice: 0.000000000000678144 * 1e18, - debtInAuction: 24.630052245331353429 * 1e18, - thresholdPrice: 24.630052245331353429 * 1e18, - neutralPrice: 11.932577910666902372 * 1e18 - }) - ); - - uint256 snapshot = vm.snapshot(); - // borrower repays debt in order to exit from auction - _repayDebt({ - from: _borrower, - borrower: _borrower, - amountToRepay: 25 * 1e18, - amountRepaid: 24.630052245331353429 * 1e18, - collateralToPull: 0, - newLup: _priceAt(3696) - }); - - _assertAuction( - AuctionParams({ - borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0.227287198298423969 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 0, - neutralPrice: 0 + referencePrice: 13.089508376044532178 * 1e18, + totalBondEscrowed: 0.345029692224915265 * 1e18, + auctionPrice: 0.000000000011904838 * 1e18, + debtInAuction: 22.734558435739539104 * 1e18, + thresholdPrice: 22.734558435739539104 * 1e18, + neutralPrice: 13.089508376044532178 * 1e18 }) ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 0, + borrowerDebt: 22.734558435739539104 * 1e18, borrowerCollateral: 1 * 1e18, - borrowert0Np: 0, - borrowerCollateralization: 1 * 1e18 - }); - - // borrower should be able to pull collateral from the pool - _repayDebtNoLupCheck({ - from: _borrower, - borrower: _borrower, - amountToRepay: 0, - amountRepaid: 0, - collateralToPull: 1 + borrowert0Np: 22.827635862422370438 * 1e18, + borrowerCollateralization: 0.436216294742093726 * 1e18 }); - vm.revertTo(snapshot); - - // borrower repays part of debt, but not enough to exit from auction - _repayDebt({ - from: _borrower, - borrower: _borrower, - amountToRepay: 5 * 1e18, - amountRepaid: 5 * 1e18, - collateralToPull: 0, - newLup: _priceAt(3696) - }); + // confirm borrower cannot repay while in liquidation + _assertRepayAuctionActiveRevert(_borrower, 25 * 1e18); - // borrower pledge one more NFT to exit from auction + // confirm borrower cannot recollateralize while in liquidation uint256[] memory tokenIdsToAdd = new uint256[](1); tokenIdsToAdd[0] = 5; - _pledgeCollateral({ - from: _borrower, - borrower: _borrower, - tokenIds: tokenIdsToAdd - }); + _assertPledgeCollateralAuctionActiveRevert(_borrower, tokenIdsToAdd); + // ensure auction state did not change _assertAuction( AuctionParams({ borrower: _borrower, - active: false, - kicker: address(0), - bondSize: 0, - bondFactor: 0, - kickTime: 0, - kickMomp: 0, - totalBondEscrowed: 0.227287198298423969 * 1e18, - auctionPrice: 0, - debtInAuction: 0, - thresholdPrice: 9.815026122665676715 * 1e18, - neutralPrice: 0 + active: true, + kicker: _lender, + bondSize: 0.345029692224915265 * 1e18, + bondFactor: 0.015180339887498948 * 1e18, + kickTime: block.timestamp - 50 hours, + referencePrice: 13.089508376044532178 * 1e18, + totalBondEscrowed: 0.345029692224915265 * 1e18, + auctionPrice: 0.000000000011904838 * 1e18, + debtInAuction: 22.734558435739539104 * 1e18, + thresholdPrice: 22.734558435739539104 * 1e18, + neutralPrice: 13.089508376044532178 * 1e18 }) ); _assertBorrower({ borrower: _borrower, - borrowerDebt: 19.630052245331353430 * 1e18, - borrowerCollateral: 2 * 1e18, - borrowert0Np: 8.902861174861655549 * 1e18, - borrowerCollateralization: 1.010408400292926569 * 1e18 + borrowerDebt: 22.734558435739539104 * 1e18, + borrowerCollateral: 1 * 1e18, + borrowert0Np: 22.827635862422370438 * 1e18, + borrowerCollateralization: 0.436216294742093726 * 1e18 }); + // settle the auction with debt + skip(22 hours + 1); + _settle({ + from: _lender, + borrower: _borrower, + maxDepth: 10, + settledDebt: 19.819038461528240952 * 1e18 + }); } function testTakeCollateralWithAtomicSwapSubsetPool() external tearDown { @@ -850,10 +809,10 @@ contract ERC721PoolLiquidationsTakeTest is ERC721HelperContract { _kick({ from: _lender, borrower: _borrower, - debt: 23.012828827714740289 * 1e18, + debt: 22.728719829841718804 * 1e18, collateral: 2 * 1e18, - bond: 0.227287198298417188 * 1e18, - transferAmount: 0.227287198298417188 * 1e18 + bond: 0.345029692224734546 * 1e18, + transferAmount: 0.345029692224734546 * 1e18 }); skip(5.5 hours); diff --git a/tests/forge/unit/ERC721Pool/ERC721PoolReserveAuction.t.sol b/tests/forge/unit/ERC721Pool/ERC721PoolReserveAuction.t.sol index 1959705bc..9e579ef35 100644 --- a/tests/forge/unit/ERC721Pool/ERC721PoolReserveAuction.t.sol +++ b/tests/forge/unit/ERC721Pool/ERC721PoolReserveAuction.t.sol @@ -122,7 +122,7 @@ contract ERC721PoolReserveAuctionTest is ERC721HelperContract { // kick off a new auction _kickReserveAuction({ from: _bidder, - remainingReserves: 823.268887039816613726 * 1e18, + remainingReserves: 831.584734383653145178 * 1e18, price: 1_000_000_000 * 1e18, epoch: 1 }); @@ -193,7 +193,7 @@ contract ERC721PoolReserveAuctionTest is ERC721HelperContract { // kick off a new auction _kickReserveAuction({ from: _bidder, - remainingReserves: 823.268887039816613726 * 1e18, + remainingReserves: 831.584734383653145178 * 1e18, price: 1_000_000_000 * 1e18, epoch: 1 }); @@ -248,10 +248,7 @@ contract ERC721PoolReserveAuctionTest is ERC721HelperContract { // kick off a new auction uint256 expectedPrice = 1_000_000_000 * 1e18; - - uint256 kickAward = Maths.wmul(claimableReserves, 0.01 * 1e18); - uint256 expectedQuoteBalance = _quote.balanceOf(_bidder) + kickAward; - expectedReserves -= kickAward; + uint256 expectedQuoteBalance = _quote.balanceOf(_bidder); _kickReserveAuction({ from: _bidder, @@ -267,14 +264,14 @@ contract ERC721PoolReserveAuctionTest is ERC721HelperContract { timeRemaining: 3 days }); assertEq(_quote.balanceOf(_bidder), expectedQuoteBalance); - + // bid once the price becomes attractive skip(24 hours); expectedPrice = 59.604644775390625 * 1e18; _assertReserveAuction({ reserves: 0.000203758789008448 * 1e18, claimableReserves : 0, - claimableReservesRemaining: 823.268887039816613726 * 1e18, + claimableReservesRemaining: 831.584734383653145178 * 1e18, auctionPrice: expectedPrice, timeRemaining: 2 days }); @@ -282,7 +279,7 @@ contract ERC721PoolReserveAuctionTest is ERC721HelperContract { _takeReserves({ from: _bidder, amount: 300 * 1e18, - remainingReserves: 523.268887039816613726 * 1e18, + remainingReserves: 531.584734383653145178 * 1e18, price: expectedPrice, epoch: 1 }); @@ -319,7 +316,7 @@ contract ERC721PoolReserveAuctionTest is ERC721HelperContract { }); expectedQuoteBalance += expectedReserves; assertEq(_quote.balanceOf(_bidder), expectedQuoteBalance); - assertEq(_ajnaToken.balanceOf(_bidder), 32_679.868870829247225792 * 1e18); + assertEq(_ajnaToken.balanceOf(_bidder), 32_212.025177571105194476 * 1e18); expectedReserves = 0; _assertReserveAuction({ @@ -369,8 +366,6 @@ contract ERC721PoolReserveAuctionTest is ERC721HelperContract { // kick off a new auction uint256 expectedPrice = 1_000_000_000 * 1e18; uint256 expectedReserves = claimableReserves; - uint256 kickAward = Maths.wmul(expectedReserves, 0.01 * 1e18); - expectedReserves -= kickAward; _kickReserveAuction({ from: _bidder, @@ -445,8 +440,7 @@ contract ERC721PoolReserveAuctionTest is ERC721HelperContract { timeRemaining: 0 }); expectedPrice = 1_000_000_000 * 1e18; - kickAward = Maths.wmul(newClaimableReserves, 0.01 * 1e18); - expectedReserves += newClaimableReserves - kickAward; + expectedReserves += newClaimableReserves; _kickReserveAuction({ from: _bidder, remainingReserves: expectedReserves, @@ -460,7 +454,7 @@ contract ERC721PoolReserveAuctionTest is ERC721HelperContract { // ensure entire reserves can still be taken skip(28 hours); - assertEq(expectedReserves, 751.769002239424117961 * 1e18); + assertEq(expectedReserves, 760.372729534771836324 * 1e18); expectedPrice = 3.725290298461914062 * 1e18; _assertReserveAuction({ reserves: 0.000204114705960104 * 1e18, diff --git a/tests/forge/unit/Positions/CodearenaReports.t.sol b/tests/forge/unit/Positions/CodearenaReports.t.sol index 6bfe61eea..d582c4ff5 100644 --- a/tests/forge/unit/Positions/CodearenaReports.t.sol +++ b/tests/forge/unit/Positions/CodearenaReports.t.sol @@ -139,22 +139,22 @@ contract PositionManagerCodeArenaTest is PositionManagerERC20PoolHelperContract _kick({ from: testMinter, borrower: testBorrowerTwo, - debt: 9_976.561670003961916237 * 1e18, + debt: 9_853.394241979221645666 * 1e18, collateral: 1_000 * 1e18, - bond: 98.533942419792216457 * 1e18, - transferAmount: 98.533942419792216457 * 1e18 + bond: 149.577873638769639523 * 1e18, + transferAmount: 149.577873638769639523 * 1e18 }); // skip ahead so take can be called on the loan - skip(10 hours); + skip(9 hours); // take entire collateral _take({ from: testMinter, borrower: testBorrowerTwo, maxCollateral: 1_000 * 1e18, - bondChange: 6.531114528261135360 * 1e18, - givenAmount: 653.111452826113536000 * 1e18, + bondChange: 60.911699561320164197 * 1e18, + givenAmount: 4_012.538586931187076 * 1e18, collateralTaken: 1_000 * 1e18, isReward: true }); @@ -163,7 +163,7 @@ contract PositionManagerCodeArenaTest is PositionManagerERC20PoolHelperContract from: testMinter, borrower: testBorrowerTwo, maxDepth: 10, - settledDebt: 9_891.935520844277346923 * 1e18 + settledDebt: 5_821.65265251164695163 * 1e18 }); // bucket is insolvent, balances are reset diff --git a/tests/forge/unit/Positions/PositionManager.t.sol b/tests/forge/unit/Positions/PositionManager.t.sol index 71f307a05..926f69913 100644 --- a/tests/forge/unit/Positions/PositionManager.t.sol +++ b/tests/forge/unit/Positions/PositionManager.t.sol @@ -918,22 +918,22 @@ contract PositionManagerERC20PoolTest is PositionManagerERC20PoolHelperContract _kick({ from: testMinter, borrower: testBorrowerTwo, - debt: 9_976.561670003961916237 * 1e18, + debt: 9_853.394241979221645666 * 1e18, collateral: 1_000 * 1e18, - bond: 98.533942419792216457 * 1e18, - transferAmount: 98.533942419792216457 * 1e18 + bond: 149.577873638769639523 * 1e18, + transferAmount: 149.577873638769639523 * 1e18 }); // skip ahead so take can be called on the loan - skip(10 hours); + skip(9 hours); // take entire collateral _take({ from: testMinter, borrower: testBorrowerTwo, maxCollateral: 1_000 * 1e18, - bondChange: 6.531114528261135360 * 1e18, - givenAmount: 653.111452826113536000 * 1e18, + bondChange: 60.911699561320164197 * 1e18, + givenAmount: 4012.538586931187076000 * 1e18, collateralTaken: 1_000 * 1e18, isReward: true }); @@ -942,7 +942,7 @@ contract PositionManagerERC20PoolTest is PositionManagerERC20PoolHelperContract from: testMinter, borrower: testBorrowerTwo, maxDepth: 10, - settledDebt: 9_891.935520844277346923 * 1e18 + settledDebt: 5_821.652652511646951630 * 1e18 }); // bucket is insolvent, balances are reset @@ -2807,22 +2807,22 @@ contract PositionManagerERC20PoolTest is PositionManagerERC20PoolHelperContract _kick({ from: testMinter, borrower: testBorrowerTwo, - debt: 9_976.561670003961916237 * 1e18, + debt: 9_853.394241979221645666 * 1e18, collateral: 1_000 * 1e18, - bond: 98.533942419792216457 * 1e18, - transferAmount: 98.533942419792216457 * 1e18 + bond: 149.577873638769639523 * 1e18, + transferAmount: 149.577873638769639523 * 1e18 }); // skip ahead so take can be called on the loan - skip(10 hours); + skip(14 hours); // take entire collateral _take({ from: testMinter, borrower: testBorrowerTwo, maxCollateral: 1_000 * 1e18, - bondChange: 6.531114528261135360 * 1e18, - givenAmount: 653.111452826113536000 * 1e18, + bondChange: 10.767768953351785113 * 1e18, + givenAmount: 709.323311147932380000 * 1e18, collateralTaken: 1_000 * 1e18, isReward: true }); @@ -2831,7 +2831,7 @@ contract PositionManagerERC20PoolTest is PositionManagerERC20PoolHelperContract from: testMinter, borrower: testBorrowerTwo, maxDepth: 10, - settledDebt: 9_891.935520844277346923 * 1e18 + settledDebt: 9_030.334558988288428680 * 1e18 }); // bucket is insolvent, balances are reset @@ -2855,14 +2855,20 @@ contract PositionManagerERC20PoolTest is PositionManagerERC20PoolHelperContract index: _i9_72, lpBalance: 11_000 * 1e18, collateral: 0, - deposit: 8_936.865546659328965469 * 1e18, - exchangeRate: 0.812442322423575361 * 1e18 + deposit: 8_988.841151969900795435 * 1e18, + exchangeRate: 0.817167377451809164 * 1e18 }); assertTrue(_positionManager.isPositionBucketBankrupt(tokenId, testIndex)); assertTrue(_positionManager.isPositionBucketBankrupt(tokenId, _i9_81)); assertFalse(_positionManager.isPositionBucketBankrupt(tokenId, _i9_72)); + // check buckets that are not bankrupt in NFT + uint256[] memory bucketsWithPosition = new uint256[](1); + bucketsWithPosition[0] = _i9_72; + + assertEq(_positionManager.getPositionIndexesFiltered(tokenId), bucketsWithPosition); + // minter two needs to add to their position not on bankruptcy block skip(1 days); @@ -2900,9 +2906,9 @@ contract PositionManagerERC20PoolTest is PositionManagerERC20PoolHelperContract _assertBucketAssets({ index: _i9_91, - lpBalance: 18_936.867676658332708016 * 1e18, + lpBalance: 18_988.843069038537201221 * 1e18, collateral: 0, - deposit: 18_936.867676658332708016 * 1e18, + deposit: 18_988.843069038537201221 * 1e18, exchangeRate: 1.0 * 1e18 }); @@ -2925,10 +2931,10 @@ contract PositionManagerERC20PoolTest is PositionManagerERC20PoolHelperContract // minter one should only be able to withdraw what they moved _removeAllLiquidity({ from: testMinter, - amount: 8_936.867676658332708016 * 1e18, + amount: 8_988.843069038537201221 * 1e18, index: _i9_91, newLup: _p9_91, - lpRedeem: 8_936.867676658332708016 * 1e18 + lpRedeem: 8_988.843069038537201221 * 1e18 }); // minter2 has remaining liquidity in _i9_91 @@ -2940,21 +2946,11 @@ contract PositionManagerERC20PoolTest is PositionManagerERC20PoolHelperContract exchangeRate: 1.0 * 1e18 }); } - } -abstract contract PositionManagerERC721PoolHelperContract is ERC721HelperContract { - +abstract contract PositionManagerHelperContract is ERC721HelperContract { PositionManager internal _positionManager; - - constructor() ERC721HelperContract() { - _positionManager = new PositionManager(new ERC20PoolFactory(_ajna), _poolFactory); - _pool = _deployCollectionPool(); - } - - function setUp() external { - _startTest(); - } + bytes32 internal _subsetHash; function _mintQuoteAndApproveManagerTokens(address operator_, uint256 mintAmount_) internal { deal(address(_quote), operator_, mintAmount_); @@ -2974,7 +2970,7 @@ abstract contract PositionManagerERC721PoolHelperContract is ERC721HelperContrac } } -contract PositionManagerERC721PoolTest is PositionManagerERC721PoolHelperContract { +abstract contract PositionManagerERC721PoolTest is PositionManagerHelperContract { function testPositionFlowForERC721Pool() external { address testAddress1 = makeAddr("testAddress1"); @@ -3007,7 +3003,7 @@ contract PositionManagerERC721PoolTest is PositionManagerERC721PoolHelperContrac }); // mint an NFT to later memorialize existing positions into - uint256 tokenId = _mintNFT(testAddress1, testAddress1, address(_pool), keccak256("ERC721_NON_SUBSET_HASH")); + uint256 tokenId = _mintNFT(testAddress1, testAddress1, address(_pool), _subsetHash); // check LP _assertLenderLpBalance({ @@ -3403,3 +3399,35 @@ contract PositionManagerERC721PoolTest is PositionManagerERC721PoolHelperContrac } } + +contract PositionManagerERC721CollectionPoolTest is PositionManagerERC721PoolTest { + constructor() ERC721HelperContract() { + _positionManager = new PositionManager(new ERC20PoolFactory(_ajna), _poolFactory); + _pool = _deployCollectionPool(); + _subsetHash = keccak256("ERC721_NON_SUBSET_HASH"); + } + + function setUp() external { + _startTest(); + } +} + +contract PositionManagerERC721SubsetPoolTest is PositionManagerERC721PoolTest { + constructor() ERC721HelperContract() { + _positionManager = new PositionManager(new ERC20PoolFactory(_ajna), _poolFactory); + // deploy subset pool + uint256[] memory subsetTokenIds = new uint256[](6); + subsetTokenIds[0] = 1; + subsetTokenIds[1] = 2; + subsetTokenIds[2] = 3; + subsetTokenIds[3] = 4; + subsetTokenIds[4] = 5; + subsetTokenIds[5] = 6; + _pool = _deploySubsetPool(subsetTokenIds); + _subsetHash = keccak256(abi.encode(subsetTokenIds)); + } + + function setUp() external { + _startTest(); + } +} \ No newline at end of file diff --git a/tests/forge/unit/Rewards/ClaimRewards.t.sol b/tests/forge/unit/Rewards/ClaimRewards.t.sol index a54811626..b9d629a83 100644 --- a/tests/forge/unit/Rewards/ClaimRewards.t.sol +++ b/tests/forge/unit/Rewards/ClaimRewards.t.sol @@ -96,7 +96,7 @@ contract ClaimRewardsOnStakeTest is RewardsHelperContract { _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 81.798787696449835897 * 1e18, + tokensToBurn: 82.625038077222056449 * 1e18, borrowAmount: 300 * 1e18, limitIndex: 2555, pool: address(_pool) @@ -114,7 +114,7 @@ contract ClaimRewardsOnStakeTest is RewardsHelperContract { tokenId: tokenIdTwo }); uint256 minterTwoBalance = _ajnaToken.balanceOf(_minterTwo); - assertEq(minterTwoBalance, 4.089939384822486675 * 1e18); + assertEq(minterTwoBalance, 4.131251903861097650 * 1e18); vm.revertTo(stakeSnapshot); @@ -164,11 +164,11 @@ contract ClaimRewardsOnExchangeRateUpdateTest is ClaimRewardsOnStakeTest { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 4.089939384822486675 * 1e18 + reward: 4.131251903861097650 * 1e18 }); uint256 updaterBalance = _ajnaToken.balanceOf(_updater); - assertEq(updaterBalance, 4.089939384822486675 * 1e18); + assertEq(updaterBalance, 4.131251903861097650 * 1e18); vm.revertTo(updateSnapshot); @@ -181,7 +181,7 @@ contract ClaimRewardsOnExchangeRateUpdateTest is ClaimRewardsOnStakeTest { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 4.089939384822486675 * 1e18 + reward: 4.131251903861097650 * 1e18 }); updaterBalance = _ajnaToken.balanceOf(_updater); assertEq(updaterBalance, 1 * 1e18); @@ -197,7 +197,7 @@ contract ClaimRewardsOnExchangeRateUpdateTest is ClaimRewardsOnStakeTest { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 4.089939384822486675 * 1e18 + reward: 4.131251903861097650 * 1e18 }); uint256 updaterBalance = _ajnaToken.balanceOf(_updater); assertEq(updaterBalance, 0); @@ -224,11 +224,11 @@ contract ClaimRewardsTest is ClaimRewardsOnStakeTest { from: _minterOne, tokenId: tokenIdOne, minAmountToReceive: 19 * 1e18, - reward: 24.539636308934920041 * 1e18, + reward: 24.787511423166585895 * 1e18, epochsClaimed: _epochsClaimedArray(1,0) }); uint256 minterOneBalance = _ajnaToken.balanceOf(_minterOne); - assertEq(minterOneBalance, 24.539636308934920041 * 1e18); + assertEq(minterOneBalance, 24.787511423166585895 * 1e18); vm.revertTo(claimSnapshot); @@ -253,7 +253,7 @@ contract ClaimRewardsTest is ClaimRewardsOnStakeTest { from: _minterOne, tokenId: tokenIdOne, minAmountToReceive: 5 * 1e18, - reward: 24.539636308934920041 * 1e18, + reward: 24.787511423166585895 * 1e18, epochsClaimed: _epochsClaimedArray(1,0) }); uint256 minterOneBalance = _ajnaToken.balanceOf(_minterOne); @@ -297,7 +297,7 @@ contract ClaimRewardsTest is ClaimRewardsOnStakeTest { from: _minterOne, tokenId: tokenIdOne, minAmountToReceive: 0, - reward: 24.539636308934920041 * 1e18, + reward: 24.787511423166585895 * 1e18, epochsClaimed: _epochsClaimedArray(1,0) }); uint256 minterOneBalance = _ajnaToken.balanceOf(_minterOne); @@ -319,12 +319,12 @@ contract ClaimRewardsOnUnstakeTest is ClaimRewardsOnStakeTest { pool: address(_pool), tokenId: tokenIdOne, claimedArray: _epochsClaimedArray(1, 0), - reward: 24.539636308934920041 * 1e18, + reward: 24.787511423166585895 * 1e18, indexes: depositIndexes, - updateExchangeRatesReward: 4.089939384822486675 * 1e18 + updateExchangeRatesReward: 4.131251903861097650 * 1e18 }); uint256 minterOneBalance = _ajnaToken.balanceOf(_minterOne); - assertEq(minterOneBalance, 24.539636308934920041 * 1e18); + assertEq(minterOneBalance, 24.787511423166585895 * 1e18); } function testClaimOnUnstakeWithInsufficientFunds() external { diff --git a/tests/forge/unit/Rewards/RewardsDSTestPlus.sol b/tests/forge/unit/Rewards/RewardsDSTestPlus.sol index e4ac29094..b424608ca 100644 --- a/tests/forge/unit/Rewards/RewardsDSTestPlus.sol +++ b/tests/forge/unit/Rewards/RewardsDSTestPlus.sol @@ -101,9 +101,11 @@ abstract contract RewardsDSTestPlus is IRewardsManagerEvents, ERC20HelperContrac // token owner is Rewards manager assertEq(ERC721(address(_positionManager)).ownerOf(tokenId), address(_rewardsManager)); - // when the token is unstaked updateExchangeRates emits - vm.expectEmit(true, true, true, true); - emit UpdateExchangeRates(owner, pool, indexes, updateExchangeRatesReward); + if (updateExchangeRatesReward != 0) { + // when the token is unstaked updateExchangeRates emits + vm.expectEmit(true, true, true, true); + emit UpdateExchangeRates(owner, pool, indexes, updateExchangeRatesReward); + } if (claimedArray.length != 0) { // when the token is unstaked claimRewards emits diff --git a/tests/forge/unit/Rewards/RewardsManager.t.sol b/tests/forge/unit/Rewards/RewardsManager.t.sol index 4edecdc05..cbefbb353 100644 --- a/tests/forge/unit/Rewards/RewardsManager.t.sol +++ b/tests/forge/unit/Rewards/RewardsManager.t.sol @@ -347,7 +347,7 @@ contract RewardsManagerTest is RewardsHelperContract { borrowAmount: 300 * 1e18, limitIndex: 3, pool: address(_pool), - tokensToBurn: 81.799082739441061020 * 1e18 + tokensToBurn: 82.625336100445516170 * 1e18 }); // call update exchange rate to enable claiming rewards @@ -355,7 +355,7 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 4.089954136972052373 * 1e18 + reward: 4.131266805022275123 * 1e18 }); // check only deposit owner can claim rewards @@ -370,7 +370,7 @@ contract RewardsManagerTest is RewardsHelperContract { from: _minterOne, tokenId: tokenId, minAmountToReceive: 0, - reward: 40.899541369720523724 * 1e18, + reward: 41.312668050222751231 * 1e18, epochsClaimed: _epochsClaimedArray(1, 0) }); @@ -387,13 +387,13 @@ contract RewardsManagerTest is RewardsHelperContract { burnEvent: 1, rewardsEarned: 0 }); - assertEq(_ajnaToken.balanceOf(_minterOne), 40.899541369720523724 * 1e18); + assertEq(_ajnaToken.balanceOf(_minterOne), 41.312668050222751231 * 1e18); _assertBurn({ pool: address(_pool), epoch: 1, timestamp: block.timestamp - 24 hours, - burned: 81.799082739441061020 * 1e18, + burned: 82.625336100445516170 * 1e18, tokensToBurn: tokensToBurn, interest: 6.443638300196908069 * 1e18 }); @@ -406,13 +406,10 @@ contract RewardsManagerTest is RewardsHelperContract { ); assertEq(updateRewards, 0); - // check unstake will only emit Unstake and UpdateExchangeRate events - vm.expectEmit(true, true, true, true); - emit UpdateExchangeRates(_minterOne, address(_pool), depositIndexes, 0); + // check unstake will only emit Unstake event since block.timestamp > curBurnTime + UPDATE_PERIOD vm.expectEmit(true, true, true, true); emit Unstake(_minterOne, address(_pool), tokenId); _rewardsManager.unstake(tokenId); - } function testWithdrawAndClaimRewardsNoExchangeRateUpdate() external { @@ -443,7 +440,7 @@ contract RewardsManagerTest is RewardsHelperContract { // first reserve auction happens successfully -> epoch 1 uint256 tokensToBurn = _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 81.799082739441179038 * 1e18, + tokensToBurn: 82.625336100445635379 * 1e18, borrowAmount: 300 * 1e18, limitIndex: 2_555, pool: address(_pool) @@ -454,37 +451,36 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 4.089954136972057005 * 1e18 + reward: 4.131266805022279800 * 1e18 }); _assertBurn({ pool: address(_pool), epoch: 1, timestamp: block.timestamp - 24 hours, - burned: 81.799082739441179038 * 1e18, + burned: 82.625336100445635379 * 1e18, tokensToBurn: tokensToBurn, interest: 6.443638300196908069 * 1e18 }); - // second reserve auction happens successfully -> epoch 2 tokensToBurn += _triggerReserveAuctions({ borrower: _borrower, borrowAmount: 300 * 1e18, limitIndex: 2555, pool: address(_pool), - tokensToBurn: 150.531225765096169950 * 1e18 + tokensToBurn: 152.051743197066838325 * 1e18 }); - + // check owner can withdraw the NFT and rewards will be automatically claimed _unstakeToken({ owner: _minterOne, pool: address(_pool), tokenId: tokenIdOne, claimedArray: _epochsClaimedArray(2, 0), - reward: 78.702220033830793321 * 1e18, + reward: 79.497191953364437697 * 1e18, indexes: depositIndexes, - updateExchangeRatesReward: 3.436607151282747570 * 1e18 + updateExchangeRatesReward: 3.471320354831058155 * 1e18 }); } @@ -519,7 +515,7 @@ contract RewardsManagerTest is RewardsHelperContract { // first reserve auction happens successfully Staker should receive rewards epoch 0 - 1 uint256 tokensToBurn = _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 81.799082739441179038 * 1e18, + tokensToBurn: 82.625336100445635379 * 1e18, borrowAmount: 300 * 1e18, limitIndex: 2555, pool: address(_pool) @@ -530,7 +526,7 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 4.089954136972057005 * 1e18 + reward: 4.131266805022279800 * 1e18 }); skip(2 weeks); @@ -547,7 +543,7 @@ contract RewardsManagerTest is RewardsHelperContract { pool: address(_pool), epoch: 1, timestamp: block.timestamp - (2 weeks + 26 weeks + 24 hours), - burned: 81.799082739441179038 * 1e18, + burned: 82.625336100445635379 * 1e18, tokensToBurn: tokensToBurn, interest: 6.443638300196908069 * 1e18 }); @@ -687,22 +683,22 @@ contract RewardsManagerTest is RewardsHelperContract { _kick({ from: _minterTwo, borrower: _borrower2, - debt: 9_976.561670003961916237 * 1e18, + debt: 9_853.394241979221645666 * 1e18, collateral: 1_000 * 1e18, - bond: 98.533942419792216457 * 1e18, - transferAmount: 98.533942419792216457 * 1e18 + bond: 149.577873638769639523 * 1e18, + transferAmount: 149.577873638769639523 * 1e18 }); // skip ahead so take can be called on the loan - skip(10 hours); + skip(9 hours); // take entire collateral _take({ from: _minterTwo, borrower: _borrower2, maxCollateral: 1_000 * 1e18, - bondChange: 6.531114528261135360 * 1e18, - givenAmount: 653.111452826113536000 * 1e18, + bondChange: 60.911699561320164197 * 1e18, + givenAmount: 4012.538586931187076000 * 1e18, collateralTaken: 1_000 * 1e18, isReward: true }); @@ -711,7 +707,7 @@ contract RewardsManagerTest is RewardsHelperContract { from: _minterTwo, borrower: _borrower2, maxDepth: 10, - settledDebt: 9_891.935520844277346923 * 1e18 + settledDebt: 5_821.652652511646951630 * 1e18 }); // bucket is insolvent, balances are reset @@ -728,8 +724,8 @@ contract RewardsManagerTest is RewardsHelperContract { index: _i9_81, lpBalance: 10_000 * 1e18, collateral: 0, - deposit: 4_886.628561176422153760 * 1e18, - exchangeRate: 0.488662856117642216 * 1e18 + deposit: 8_191.675009896270870814 * 1e18, + exchangeRate: 0.819167500989627088 * 1e18 }); /***********************/ @@ -788,7 +784,7 @@ contract RewardsManagerTest is RewardsHelperContract { }); } - function testNoRewardsToClaimPostBankrupt() external { + function testNoRewardsToClaimPostBankrupt() external { skip(10); /***************************/ @@ -876,15 +872,15 @@ contract RewardsManagerTest is RewardsHelperContract { }); (,, uint256 tokensBurned) = IPool(address(_pool)).burnInfo(IPool(address(_pool)).currentBurnEpoch()); - + // recorder updates the change in exchange rates in the first index _updateExchangeRates({ updater: _updater, pool: address(_pool), indexes: depositIndex1, - reward: 0.007075096372721386 * 1e18 + reward: 0.007146561992635801 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_updater), 0.007075096372721386 * 1e18); + assertEq(_ajnaToken.balanceOf(_updater), 0.007146561992635801 * 1e18); _assertBurn({ pool: address(_pool), @@ -899,7 +895,7 @@ contract RewardsManagerTest is RewardsHelperContract { pool: address(_pool), epoch: 1, timestamp: block.timestamp - 24 hours, - burned: 0.283003854923906684 * 1e18, + burned: 0.285862479721117855 * 1e18, interest: 0.000048562908902619 * 1e18, tokensToBurn: tokensBurned }); @@ -923,13 +919,13 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater2, pool: address(_pool), indexes: depositIndex2, - reward: 0.021225289119669282 * 1e18 + reward: 0.021439685979475985 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_updater2), .021225289119669282 * 1e18); + assertEq(_ajnaToken.balanceOf(_updater2), 0.021439685979475985 * 1e18); // assert minterOne has rewards to be claimed uint256 rewardsEarned = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); - assertEq(rewardsEarned, 0.226403083939125347 * 1e18); + assertEq(rewardsEarned, 0.228689983776894284 * 1e18); _assertBucket({ index: 2770, @@ -1013,16 +1009,16 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndex1, - reward: 3.511985000906831402 * 1e18 + reward: 3.547459596875587275 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_updater), 3.519060097279552788 * 1e18); + assertEq(_ajnaToken.balanceOf(_updater), 3.554606158868223076 * 1e18); _assertBurn({ pool: address(_pool), epoch: 2, timestamp: block.timestamp - 24 hours, - burned: 140.762403891199659050 * 1e18, + burned: 142.184246354747130336 * 1e18, interest: 2.566194585267388219 * 1e18, tokensToBurn: tokensBurned }); @@ -1046,13 +1042,13 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater2, pool: address(_pool), indexes: depositIndex2, - reward: 3.160572158484729706 * 1e18 + reward: 3.192497129782555259 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_updater2), 3.181797447604398988 * 1e18); + assertEq(_ajnaToken.balanceOf(_updater2), 3.213936815762031244 * 1e18); // assert minterOne has more rewards to be claimed rewardsEarned = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); - assertEq(rewardsEarned, 66.951974677854736430 * 1e18); + assertEq(rewardsEarned, 67.628257250358319615 * 1e18); // QT is adeed to a bucket deal(address(_quote), _minterOne, 100 * 1e18 * depositIndexes.length + 6_000.0 * 1e18); @@ -1092,17 +1088,17 @@ contract RewardsManagerTest is RewardsHelperContract { borrower: _borrower, borrowerDebt: 25656.385808102176964640 * 1e18, borrowerCollateral: 25.921751033498703620 * 1e18, - borrowert0Np: 1_004.264567230919901856 * 1e18, + borrowert0Np: 1_101.390902162019364514 * 1e18, borrowerCollateralization: 0.990376081445383032 * 1e18 }); _kick({ from: _minterTwo, borrower: _borrower, - debt: 25_945.020148443326455492 * 1e18, + debt: 25_656.385808102176964640 * 1e18, collateral: 25.921751033498703620 * 1e18, - bond: 256.563858081021769646 * 1e18, - transferAmount: 256.563858081021769646 * 1e18 + bond: 374.752609017118925592 * 1e18, + transferAmount: 374.752609017118925592 * 1e18 }); // skip ahead so take can be called on the loan @@ -1113,8 +1109,8 @@ contract RewardsManagerTest is RewardsHelperContract { from: _minterTwo, borrower: _borrower, maxCollateral: 100.0 * 1e18, - bondChange: 0 * 1e18, - givenAmount: 0 * 1e18, + bondChange: 80, + givenAmount: 5495, collateralTaken: 25.921751033498703620 * 1e18, isReward: true }); @@ -1123,7 +1119,7 @@ contract RewardsManagerTest is RewardsHelperContract { from: _minterTwo, borrower: _borrower, maxDepth: 10, - settledDebt: 26_954.947917202244023854 * 1e18 + settledDebt: 24_911.288118205001229802 * 1e18 }); // bucket is insolvent, balances are reset @@ -1158,7 +1154,7 @@ contract RewardsManagerTest is RewardsHelperContract { claimedArray: _epochsClaimedArray(2, 0), reward: 0 * 1e18, indexes: depositIndexes, - updateExchangeRatesReward: 0 + updateExchangeRatesReward: 0 // updateExchangeRates is not emitted }); } @@ -1256,9 +1252,9 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndex1, - reward: 0.007075096372721386 * 1e18 + reward: 0.007146561992635801 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_updater), 0.007075096372721386 * 1e18); + assertEq(_ajnaToken.balanceOf(_updater), 0.007146561992635801 * 1e18); _assertBurn({ pool: address(_pool), @@ -1273,7 +1269,7 @@ contract RewardsManagerTest is RewardsHelperContract { pool: address(_pool), epoch: 1, timestamp: block.timestamp - 24 hours, - burned: 0.283003854923906684 * 1e18, + burned: 0.285862479721117855 * 1e18, interest: 0.000048562908902619 * 1e18, tokensToBurn: tokensBurned }); @@ -1297,10 +1293,9 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater2, pool: address(_pool), indexes: depositIndex2, - reward: 0.021225289119669282 * 1e18 + reward: 0.021439685979475985 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_updater2), 0.021225289119669282 * 1e18); - + assertEq(_ajnaToken.balanceOf(_updater2), 0.021439685979475985 * 1e18); /*******************************************/ /*** Lender Withdraws And Claims Rewards ***/ @@ -1312,7 +1307,7 @@ contract RewardsManagerTest is RewardsHelperContract { pool: address(_pool), tokenId: tokenIdOne, claimedArray: _epochsClaimedArray(1, 0), - reward: 0.226403083939125347 * 1e18, + reward: 0.228689983776894284 * 1e18, indexes: depositIndexes, updateExchangeRatesReward: 0 }); @@ -1445,16 +1440,16 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndex1, - reward: 0.007075096372721386 * 1e18 + reward: 0.007146561992635801 * 1e18 }); _updateExchangeRates({ updater: _updater, pool: address(_poolTwo), indexes: depositIndex1, - reward: 0.007075096372721386 * 1e18 + reward: 0.007146561992635801 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_updater), 2 * 0.007075096372721386 * 1e18); + assertEq(_ajnaToken.balanceOf(_updater), 2 * 0.007146561992635801 * 1e18); _assertBurn({ pool: address(_pool), @@ -1478,7 +1473,7 @@ contract RewardsManagerTest is RewardsHelperContract { pool: address(_pool), epoch: 1, timestamp: block.timestamp - 24 hours, - burned: 0.283003854923906684 * 1e18, + burned: 0.285862479721117855 * 1e18, interest: 0.000048562908902619 * 1e18, tokensToBurn: tokensBurned }); @@ -1487,7 +1482,7 @@ contract RewardsManagerTest is RewardsHelperContract { pool: address(_poolTwo), epoch: 1, timestamp: block.timestamp - 24 hours, - burned: 0.283003854923906684 * 1e18, + burned: 0.285862479721117855 * 1e18, interest: 0.000048562908902619 * 1e18, tokensToBurn: tokensBurned }); @@ -1515,16 +1510,16 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater2, pool: address(_pool), indexes: depositIndex2, - reward: 0.021225289119669282 * 1e18 + reward: 0.021439685979475985 * 1e18 }); _updateExchangeRates({ updater: _updater2, pool: address(_poolTwo), indexes: depositIndex2, - reward: 0.021225289119669282 * 1e18 + reward: 0.021439685979475985 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_updater2), 2 * 0.021225289119669282 * 1e18); + assertEq(_ajnaToken.balanceOf(_updater2), 2 * 0.021439685979475985 * 1e18); /*******************************************/ @@ -1537,7 +1532,7 @@ contract RewardsManagerTest is RewardsHelperContract { pool: address(_pool), tokenId: tokenIdOne, claimedArray: _epochsClaimedArray(1, 0), - reward: 0.226403083939125347 * 1e18, + reward: 0.228689983776894284 * 1e18, indexes: depositIndexes, updateExchangeRatesReward: 0 }); @@ -1547,7 +1542,7 @@ contract RewardsManagerTest is RewardsHelperContract { pool: address(_poolTwo), tokenId: tokenIdTwo, claimedArray: _epochsClaimedArray(1, 0), - reward: 0.226403083939125347 * 1e18, + reward: 0.228689983776894284 * 1e18, indexes: depositIndexes, updateExchangeRatesReward: 0 }); @@ -1580,7 +1575,7 @@ contract RewardsManagerTest is RewardsHelperContract { _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 81.799082739441179038 * 1e18, + tokensToBurn: 82.625336100445635379 * 1e18, borrowAmount: 300 * 1e18, limitIndex: 2555, pool: address(_pool) @@ -1591,7 +1586,7 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 4.089954136972057005 * 1e18 + reward: 4.131266805022279800 * 1e18 }); // burn rewards manager tokens and leave only 5 tokens available @@ -1599,7 +1594,7 @@ contract RewardsManagerTest is RewardsHelperContract { IERC20Token(address(_ajnaToken)).burn(99_999_990.910045863027949943 * 1e18); uint256 managerBalance = _ajnaToken.balanceOf(address(_rewardsManager)); - assertEq(managerBalance, 4.999999999999993052 * 1e18); + assertEq(managerBalance, 4.958687331949770257 * 1e18); // check reward generated are more than manager token balance uint256 rewards = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); @@ -1614,7 +1609,7 @@ contract RewardsManagerTest is RewardsHelperContract { from: _minterOne, tokenId: tokenIdOne, minAmountToReceive: 0, - reward: 40.899541369720570039 * 1e18, + reward: 41.312668050222798013 * 1e18, epochsClaimed: _epochsClaimedArray(1,0) }); @@ -1663,7 +1658,7 @@ contract RewardsManagerTest is RewardsHelperContract { // bidder takes reserve auctions by providing ajna tokens to be burned totalTokensBurned += _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 408.996298826180042327 * 1e18, + tokensToBurn: 413.127574571899032653 * 1e18, borrowAmount: 1_500 * 1e18, limitIndex: 6000, pool: address(_pool) @@ -1674,12 +1669,12 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 20.449814941309000626 * 1e18 + reward: 20.656378728594950130 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_updater), 20.449814941309000626 * 1e18); + assertEq(_ajnaToken.balanceOf(_updater), 20.656378728594950130 * 1e18); uint256 rewardsEarned = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); - assertEq(rewardsEarned, 204.498149413090006279 * 1e18); + assertEq(rewardsEarned, 206.563787285949501291 * 1e18); assertLt(rewardsEarned, Maths.wmul(totalTokensBurned, 0.800000000000000000 * 1e18)); /******************************/ @@ -1688,7 +1683,7 @@ contract RewardsManagerTest is RewardsHelperContract { // trigger second reserve auction totalTokensBurned += _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 749.938293079404058517 * 1e18, + tokensToBurn: 757.513427352933392466 * 1e18, borrowAmount: 1_500 * 1e18, limitIndex: 6_000, pool: address(_pool) @@ -1699,13 +1694,13 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 17.047099712661199616 * 1e18 + reward: 17.219292639051716786 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_updater), 37.496914653970200242 * 1e18); + assertEq(_ajnaToken.balanceOf(_updater), 37.875671367646666916 * 1e18); // check available rewards rewardsEarned = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); - assertEq(rewardsEarned, 374.969146539702002449 * 1e18); + assertEq(rewardsEarned, 378.756713676466669152 * 1e18); assertLt(rewardsEarned, Maths.wmul(totalTokensBurned, 0.800000000000000000 * 1e18)); /*****************************/ @@ -1715,7 +1710,7 @@ contract RewardsManagerTest is RewardsHelperContract { // trigger third reserve auction totalTokensBurned += _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 1_030.321595435443883599 * 1e18, + tokensToBurn: 1_040.728884278226145090 * 1e18, borrowAmount: 1_500 * 1e18, limitIndex: 6_000, pool: address(_pool) @@ -1723,7 +1718,7 @@ contract RewardsManagerTest is RewardsHelperContract { // skip updating exchange rates and check available rewards uint256 rewardsEarnedNoUpdate = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); - assertEq(rewardsEarnedNoUpdate, 374.969146539702002449* 1e18); + assertEq(rewardsEarnedNoUpdate, 378.756713676466669152* 1e18); assertLt(rewardsEarned, Maths.wmul(totalTokensBurned, 0.800000000000000000 * 1e18)); // snapshot calling update exchange rate @@ -1734,10 +1729,10 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater2, pool: address(_pool), indexes: depositIndexes, - reward: 14.019165117801987582 * 1e18 + reward: 14.160772846264633918 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_updater2), 14.019165117801987582 * 1e18); + assertEq(_ajnaToken.balanceOf(_updater2), 14.160772846264633918 * 1e18); // check available rewards rewardsEarned = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); @@ -1754,7 +1749,7 @@ contract RewardsManagerTest is RewardsHelperContract { // triger fourth reserve auction totalTokensBurned += _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 1_285.690028219559780957 * 1e18, + tokensToBurn: 1_298.676796181373516144 * 1e18, borrowAmount: 1_500 * 1e18, limitIndex: 6_000, pool: address(_pool) @@ -1762,7 +1757,7 @@ contract RewardsManagerTest is RewardsHelperContract { // check rewards earned rewardsEarned = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); - assertEq(rewardsEarned, 374.969146539702002449 * 1e18); + assertEq(rewardsEarned, 378.756713676466669152 * 1e18); // call update exchange rate _updateExchangeRates({ @@ -1775,7 +1770,7 @@ contract RewardsManagerTest is RewardsHelperContract { // check rewards earned won't increase since previous update was missed rewardsEarned = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); - assertEq(rewardsEarned, 374.969146539702002449 * 1e18); + assertEq(rewardsEarned, 378.756713676466669152 * 1e18); /*****************************/ /*** Fifth Reserve Auction ***/ @@ -1784,7 +1779,7 @@ contract RewardsManagerTest is RewardsHelperContract { // triger fifth reserve auction totalTokensBurned += _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 1_518.007030973479132952 * 1e18, + tokensToBurn: 1_533.340435326746598961 * 1e18, borrowAmount: 1_500 * 1e18, limitIndex: 6_000, pool: address(_pool) @@ -1795,12 +1790,12 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater2, pool: address(_pool), indexes: depositIndexes, - reward: 11.615850137695967876 * 1e18 + reward: 11.733181957268654420 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_updater2), 11.615850137695967876 * 1e18); + assertEq(_ajnaToken.balanceOf(_updater2), 11.733181957268654420 * 1e18); rewardsEarned = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); - assertEq(rewardsEarned, 491.127647916661681237 * 1e18); + assertEq(rewardsEarned, 496.088533249153213379 * 1e18); // claim all rewards accrued since deposit _claimRewards({ @@ -1809,7 +1804,7 @@ contract RewardsManagerTest is RewardsHelperContract { tokenId: tokenIdOne, minAmountToReceive: 0, epochsClaimed: _epochsClaimedArray(5,0), - reward: 491.127647916661681237 * 1e18 + reward: 496.088533249153213379 * 1e18 }); assertEq(_ajnaToken.balanceOf(_minterOne), rewardsEarned); assertLt(rewardsEarned, Maths.wmul(totalTokensBurned, 0.800000000000000000 * 1e18)); @@ -1887,7 +1882,7 @@ contract RewardsManagerTest is RewardsHelperContract { _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 133.010720463154931188 * 1e18, + tokensToBurn: 134.354263094095890105 * 1e18, borrowAmount: 300 * 1e18, limitIndex: 2555, pool: address(_pool) @@ -1899,24 +1894,24 @@ contract RewardsManagerTest is RewardsHelperContract { pool: address(_pool), tokenId: tokenIdTwo, claimedArray: _epochsClaimedArray(1, 0), - reward: 39.908147491580588274 * 1e18, + reward: 40.311260092505644727 * 1e18, indexes: depositIndexes, - updateExchangeRatesReward: 6.651023502439564179 * 1e18 + updateExchangeRatesReward: 6.718205558019761798 * 1e18 }); uint256 minterTwoBalance = _ajnaToken.balanceOf(_minterTwo); - assertEq(minterTwoBalance, 39.908147491580588274 * 1e18); + assertEq(minterTwoBalance, 40.311260092505644727 * 1e18); _unstakeToken({ owner: _minterThree, pool: address(_pool), tokenId: tokenIdThree, claimedArray: _epochsClaimedArray(1, 0), - reward: 33.248236242436447412 * 1e18, + reward: 33.584077012562068097 * 1e18, indexes: depositIndexes, updateExchangeRatesReward: 0 }); uint256 minterThreeBalance = _ajnaToken.balanceOf(_minterThree); - assertEq(minterThreeBalance, 33.248236242436447412 * 1e18); + assertEq(minterThreeBalance, 33.584077012562068097 * 1e18); assertGt(minterTwoBalance, minterThreeBalance); } @@ -1959,7 +1954,7 @@ contract RewardsManagerTest is RewardsHelperContract { // borrower takes actions providing reserves enabling reserve auctions uint256 firstTokensToBurn = _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 81.799082739441061020 * 1e18, + tokensToBurn: 82.625336100445516170 * 1e18, borrowAmount: 300 * 1e18, limitIndex: 3, pool: address(_pool) @@ -1983,7 +1978,7 @@ contract RewardsManagerTest is RewardsHelperContract { owner: _minterTwo, tokenId: tokenIdTwo }); - assertEq(_ajnaToken.balanceOf(_minterTwo), 8.171892378490154686 * 1e18); + assertEq(_ajnaToken.balanceOf(_minterTwo), 8.254436745949651197 * 1e18); // calculate rewards earned since exchange rates have been updated uint256 idOneRewardsAtOne = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); @@ -2007,7 +2002,7 @@ contract RewardsManagerTest is RewardsHelperContract { // conduct second reserve auction uint256 secondTokensToBurn = _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 175.885944654845768512 * 1e18, + tokensToBurn: 177.662570358430069210 * 1e18, borrowAmount: 300 * 1e18, limitIndex: 3, pool: address(_pool) @@ -2039,11 +2034,11 @@ contract RewardsManagerTest is RewardsHelperContract { uint256 idOneRewardsAtTwo = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); assertLt(idOneRewardsAtTwo, secondTokensToBurn); assertGt(idOneRewardsAtTwo, 0); - assertEq(idOneRewardsAtTwo, 23.539670861841372334 * 1e18); + assertEq(idOneRewardsAtTwo, 23.777445314991285190 * 1e18); uint256 idTwoRewardsAtTwo = _rewardsManager.calculateRewards(tokenIdTwo, _pool.currentBurnEpoch()); assertLt(idOneRewardsAtTwo + idTwoRewardsAtTwo, secondTokensToBurn); - assertEq(idTwoRewardsAtTwo, 23.507224958013738649 * 1e18); + assertEq(idTwoRewardsAtTwo, 23.744671674761352175 * 1e18); assertGt(idTwoRewardsAtTwo, 0); // minter one claims rewards accrued after second auction @@ -2053,7 +2048,7 @@ contract RewardsManagerTest is RewardsHelperContract { tokenId: tokenIdOne, minAmountToReceive: 0, epochsClaimed: _epochsClaimedArray(1,1), - reward: 23.539670861841372334 * 1e18 + reward: 23.777445314991285190 * 1e18 }); assertEq(_ajnaToken.balanceOf(_minterOne), idOneRewardsAtOne + idOneRewardsAtTwo); @@ -2067,7 +2062,7 @@ contract RewardsManagerTest is RewardsHelperContract { epochsClaimed: _epochsClaimedArray(1,1), reward: idTwoRewardsAtTwo }); - assertEq(_ajnaToken.balanceOf(_minterTwo), 31.679117336503893335 * 1e18); + assertEq(_ajnaToken.balanceOf(_minterTwo), 31.999108420711003372 * 1e18); // check there are no remaining rewards available after claiming uint256 remainingRewards = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); @@ -2139,7 +2134,7 @@ contract RewardsManagerTest is RewardsHelperContract { // auction one uint256 tokensToBurnE1 = _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 81.797607524484463335 * 1e18, + tokensToBurn: 82.623845984327740729 * 1e18, borrowAmount: 300 * 1e18, limitIndex: 2555, pool: address(_pool) @@ -2149,14 +2144,14 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 4.089880376224205350 * 1e18 + reward: 4.131192299216369040 * 1e18 }); _assertBurn({ pool: address(_pool), epoch: 1, timestamp: block.timestamp - 24 hours, - burned: 81.797607524484463335 * 1e18, + burned: 82.623845984327740729 * 1e18, tokensToBurn: tokensToBurnE1, interest: 6.443638300196908069 * 1e18 }); @@ -2164,7 +2159,7 @@ contract RewardsManagerTest is RewardsHelperContract { // auction two uint256 tokensToBurnE2 = _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 308.522250520128650190 * 1e18, + tokensToBurn: 311.638636889018838585 * 1e18, borrowAmount: 1_000 * 1e18, limitIndex: 2555, pool: address(_pool) @@ -2174,14 +2169,14 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 11.336232149782168987 * 1e18 + reward: 11.450739545234514130 * 1e18 }); _assertBurn({ pool: address(_pool), epoch: 2, timestamp: block.timestamp - 24 hours, - burned: 308.522250520128650190 * 1e18, + burned: 311.638636889018838585 * 1e18, tokensToBurn: tokensToBurnE2, interest: 23.938554041534910348 * 1e18 }); @@ -2189,7 +2184,7 @@ contract RewardsManagerTest is RewardsHelperContract { // auction three uint256 tokensToBurnE3 = _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 676.508959571631757977 * 1e18, + tokensToBurn: 683.342383405688644410 * 1e18, borrowAmount: 2_000 * 1e18, limitIndex: 2555, pool: address(_pool) @@ -2199,14 +2194,14 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 18.399335452575176310 * 1e18 + reward: 18.585187325833511425 * 1e18 }); _assertBurn({ pool: address(_pool), epoch: 3, timestamp: block.timestamp - 24 hours, - burned: 676.508959571631757977 * 1e18, + burned: 683.342383405688644410 * 1e18, tokensToBurn: tokensToBurnE3, interest: 52.423541260157607958 * 1e18 }); @@ -2217,7 +2212,7 @@ contract RewardsManagerTest is RewardsHelperContract { pool: address(_pool), tokenId: tokenIdOne, claimedArray: _epochsClaimedArray(3, 0), - reward: 56.375746630969251081 * 1e18, + reward: 56.945198617140657657 * 1e18, indexes: firstIndexes, updateExchangeRatesReward: 0 }); @@ -2227,7 +2222,7 @@ contract RewardsManagerTest is RewardsHelperContract { pool: address(_pool), tokenId: tokenIdTwo, claimedArray: _epochsClaimedArray(3, 0), - reward: 281.878733154846255411 * 1e18, + reward: 284.725993085703288290 * 1e18, indexes: secondIndexes, updateExchangeRatesReward: 0 }); @@ -2260,7 +2255,7 @@ contract RewardsManagerTest is RewardsHelperContract { _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 81.799082739441179038 * 1e18, + tokensToBurn: 82.625336100445635379 * 1e18, borrowAmount: 300 * 1e18, limitIndex: 2555, pool: address(_pool) @@ -2271,7 +2266,7 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 4.089954136972057005 * 1e18 + reward: 4.131266805022279800 * 1e18 }); // _minterOne unstakes staked position @@ -2280,7 +2275,7 @@ contract RewardsManagerTest is RewardsHelperContract { pool: address(_pool), tokenId: tokenIdOne, claimedArray: _epochsClaimedArray(1, 0), - reward: 40.899541369720570039 * 1e18, + reward: 41.312668050222798013 * 1e18, indexes: depositIndexes, updateExchangeRatesReward: 0 }); @@ -2347,7 +2342,6 @@ contract RewardsManagerTest is RewardsHelperContract { }); } - function testWithdrawAndClaimRewards() external { skip(10); @@ -2375,7 +2369,7 @@ contract RewardsManagerTest is RewardsHelperContract { uint256 tokensToBurn = _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 81.799082739441179038 * 1e18, + tokensToBurn: 82.625336100445635379 * 1e18, borrowAmount: 300 * 1e18, limitIndex: 2555, pool: address(_pool) @@ -2386,7 +2380,7 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 4.089954136972057005 * 1e18 + reward: 4.131266805022279800 * 1e18 }); // check owner can withdraw the NFT and rewards will be automatically claimed @@ -2400,7 +2394,7 @@ contract RewardsManagerTest is RewardsHelperContract { IERC20Token(address(_ajnaToken)).burn(99_999_990.910045863027949943 * 1e18); uint256 managerBalance = _ajnaToken.balanceOf(address(_rewardsManager)); - assertEq(managerBalance, 4.999999999999993052 * 1e18); + assertEq(managerBalance, 4.958687331949770257 * 1e18); // check reward generated are more than manager token balance uint256 rewards = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); @@ -2418,13 +2412,13 @@ contract RewardsManagerTest is RewardsHelperContract { pool: address(_pool), tokenId: tokenIdOne, claimedArray: _epochsClaimedArray(1, 0), - reward: 40.899541369720570039 * 1e18, + reward: 41.312668050222798013 * 1e18, indexes: depositIndexes, updateExchangeRatesReward: 0 }); assertEq(PositionManager(address(_positionManager)).ownerOf(tokenIdOne), _minterOne); - assertEq(_ajnaToken.balanceOf(_minterOne), 40.899541369720570039 * 1e18); + assertEq(_ajnaToken.balanceOf(_minterOne), 41.312668050222798013 * 1e18); assertLt(_ajnaToken.balanceOf(_minterOne), tokensToBurn); // check can't claim rewards twice @@ -2462,7 +2456,7 @@ contract RewardsManagerTest is RewardsHelperContract { // trigger ajna burns _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 81.799082739441179038 * 1e18, + tokensToBurn: 82.625336100445635379 * 1e18, borrowAmount: 300 * 1e18, limitIndex: 2555, pool: address(_pool) @@ -2474,7 +2468,7 @@ contract RewardsManagerTest is RewardsHelperContract { from: _minterOne, tokenId: tokenIdOne, minAmountToReceive: 0, - reward: 44.989495506692627044 * 1e18, + reward: 45.443934855245077813 * 1e18, epochsClaimed: _epochsClaimedArray(1, 0) }); @@ -2533,7 +2527,7 @@ contract RewardsManagerTest is RewardsHelperContract { // bidder takes reserve auctions by providing ajna tokens to be burned uint256 tokensToBurn = _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 81.799082739441061020 * 1e18, + tokensToBurn: 82.625336100445516170 * 1e18, borrowAmount: 300 * 1e18, limitIndex: 3, pool: address(_pool) @@ -2562,9 +2556,9 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _minterOne, pool: address(_pool), indexes: firstIndexes, - reward: 4.089954136972052373 * 1e18 + reward: 4.131266805022275123 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_minterOne), 4.089954136972052373 * 1e18); + assertEq(_ajnaToken.balanceOf(_minterOne), 4.131266805022275123 * 1e18); // check owner in pool with accrued interest can properly claim rewards _claimRewards({ @@ -2572,11 +2566,10 @@ contract RewardsManagerTest is RewardsHelperContract { from: _minterOne, tokenId: tokenIdOne, minAmountToReceive: 0, - reward: 40.899541369720523724 * 1e18, + reward: 41.312668050222751231 * 1e18, epochsClaimed: _epochsClaimedArray(1, 0) }); assertLt(_ajnaToken.balanceOf(_minterOne), tokensToBurn); - } function testMultipleUnstakeInSameEpoch() external { @@ -2620,7 +2613,7 @@ contract RewardsManagerTest is RewardsHelperContract { // bidder takes reserve auctions by providing ajna tokens to be burned totalTokensBurned += _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 408.996298826180042327 * 1e18, + tokensToBurn: 413.127574571899032653 * 1e18, borrowAmount: 1_500 * 1e18, limitIndex: 6000, pool: address(_pool) @@ -2631,14 +2624,12 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 20.449814941309000626 * 1e18 + reward: 20.656378728594950130 * 1e18 }); - assertEq(_ajnaToken.balanceOf(_updater), 20.449814941309000626 * 1e18); + assertEq(_ajnaToken.balanceOf(_updater), 20.656378728594950130 * 1e18); uint256 rewardsEarnedFirstEpoch = _rewardsManager.calculateRewards(tokenIdOne, _pool.currentBurnEpoch()); - assertEq(rewardsEarnedFirstEpoch, 204.498149413090006279 * 1e18); - - uint256 totalRewardEarned = 374.969146539702002449 * 1e18; + assertEq(rewardsEarnedFirstEpoch, 206.563787285949501291 * 1e18); uint256 snapshot = vm.snapshot(); @@ -2681,7 +2672,7 @@ contract RewardsManagerTest is RewardsHelperContract { // trigger second reserve auction totalTokensBurned += _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 749.938293079404058517 * 1e18, + tokensToBurn: 757.513427352933392466 * 1e18, borrowAmount: 1_500 * 1e18, limitIndex: 6_000, pool: address(_pool) @@ -2692,10 +2683,11 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 17.047099712661199616 * 1e18 + reward: 17.219292639051716786 * 1e18 }); - uint256 newRewardsEarned = totalRewardEarned - rewardsEarnedFirstEpoch; + uint256 totalRewardEarned = 378.756713676466669152 * 1e18; + uint256 newRewardsEarned = totalRewardEarned - rewardsEarnedFirstEpoch; // 172.192926390517167861 // claim rewards for second epoch _claimRewards({ @@ -2720,7 +2712,7 @@ contract RewardsManagerTest is RewardsHelperContract { // trigger second reserve auction totalTokensBurned += _triggerReserveAuctions({ borrower: _borrower, - tokensToBurn: 749.938293079404058517 * 1e18, + tokensToBurn: 757.513427352933392466 * 1e18, borrowAmount: 1_500 * 1e18, limitIndex: 6_000, pool: address(_pool) @@ -2731,7 +2723,7 @@ contract RewardsManagerTest is RewardsHelperContract { updater: _updater, pool: address(_pool), indexes: depositIndexes, - reward: 17.047099712661199616 * 1e18 + reward: 17.219292639051716786 * 1e18 }); // check available rewards @@ -2750,7 +2742,6 @@ contract RewardsManagerTest is RewardsHelperContract { // ensure total rewards earned are same with and without unstake between epochs assertEq(_ajnaToken.balanceOf(_minterOne), totalRewardEarned); - } /********************/ diff --git a/tests/forge/utils/DSTestPlus.sol b/tests/forge/utils/DSTestPlus.sol index ef8eaa9df..d5b945159 100644 --- a/tests/forge/utils/DSTestPlus.sol +++ b/tests/forge/utils/DSTestPlus.sol @@ -78,7 +78,7 @@ abstract contract DSTestPlus is Test, IPoolEvents { uint256 bondSize; uint256 bondFactor; uint256 kickTime; - uint256 kickMomp; + uint256 referencePrice; uint256 totalBondEscrowed; uint256 auctionPrice; uint256 debtInAuction; @@ -433,7 +433,7 @@ abstract contract DSTestPlus is Test, IPoolEvents { uint256 auctionBondFactor; uint256 auctionBondSize; uint256 auctionKickTime; - uint256 auctionKickMomp; + uint256 auctionReferencePrice; uint256 auctionNeutralPrice; uint256 auctionTotalBondEscrowed; uint256 auctionDebtInAuction; @@ -447,11 +447,10 @@ abstract contract DSTestPlus is Test, IPoolEvents { vars.auctionBondFactor, vars.auctionBondSize, vars.auctionKickTime, - vars.auctionKickMomp, + vars.auctionReferencePrice, vars.auctionNeutralPrice, , , - , ) = _pool.auctionInfo(state_.borrower); (uint256 borrowerDebt, uint256 borrowerCollateral , ) = _poolUtils.borrowerInfo(address(_pool), state_.borrower); @@ -466,11 +465,10 @@ abstract contract DSTestPlus is Test, IPoolEvents { assertEq(vars.auctionBondSize, state_.bondSize); assertEq(vars.auctionBondFactor, state_.bondFactor); assertEq(vars.auctionKickTime, state_.kickTime); - assertEq(vars.auctionKickMomp, state_.kickMomp); + assertEq(vars.auctionReferencePrice, state_.referencePrice); assertEq(vars.auctionTotalBondEscrowed, state_.totalBondEscrowed); assertEq(_auctionPrice( - vars.auctionKickMomp, - vars.auctionNeutralPrice, + vars.auctionReferencePrice, vars.auctionKickTime), state_.auctionPrice); assertEq(vars.auctionDebtInAuction, state_.debtInAuction); assertEq(vars.auctionNeutralPrice, state_.neutralPrice); @@ -662,8 +660,8 @@ abstract contract DSTestPlus is Test, IPoolEvents { assertEq(t0Np, borrowert0Np); assertEq( _collateralization( - borrowerDebt, - borrowerCollateral, + debt, + col, lup ), borrowerCollateralization @@ -844,24 +842,24 @@ abstract contract DSTestPlus is Test, IPoolEvents { _pool.bucketTake(borrower, false, index); } - function _assertArbTakeAuctionInCooldownRevert( + function _assertArbTakeAuctionInsufficientLiquidityRevert( address from, address borrower, uint256 index ) internal { changePrank(from); - vm.expectRevert(abi.encodeWithSignature('TakeNotPastCooldown()')); - _pool.bucketTake(borrower, false, index); + vm.expectRevert(IPoolErrors.InsufficientLiquidity.selector); + _pool.bucketTake(borrower,false, index); } - function _assertArbTakeAuctionInsufficientLiquidityRevert( + function _assertArbTakeAuctionNotTakeableRevert( address from, address borrower, uint256 index ) internal { changePrank(from); - vm.expectRevert(IPoolErrors.InsufficientLiquidity.selector); - _pool.bucketTake(borrower,false, index); + vm.expectRevert(IPoolErrors.AuctionNotTakeable.selector); + _pool.bucketTake(borrower, false, index); } function _assertArbTakeAuctionPriceGreaterThanBucketPriceRevert( @@ -904,14 +902,14 @@ abstract contract DSTestPlus is Test, IPoolEvents { _pool.bucketTake(borrower, false, index); } - function _assertDepositTakeAuctionInCooldownRevert( + function _assertArbTakeZeroBidRevert( address from, address borrower, uint256 index ) internal { changePrank(from); - vm.expectRevert(abi.encodeWithSignature('TakeNotPastCooldown()')); - _pool.bucketTake(borrower, true, index); + vm.expectRevert(IPoolErrors.InvalidAmount.selector); + _pool.bucketTake(borrower, false, index); } function _assertDepositTakeAuctionInsufficientLiquidityRevert( @@ -924,6 +922,16 @@ abstract contract DSTestPlus is Test, IPoolEvents { _pool.bucketTake(borrower, true, index); } + function _assertDepositTakeAuctionNotTakeableRevert( + address from, + address borrower, + uint256 index + ) internal { + changePrank(from); + vm.expectRevert(IPoolErrors.AuctionNotTakeable.selector); + _pool.bucketTake(borrower, true, index); + } + function _assertDepositTakeAuctionPriceGreaterThanBucketPriceRevert( address from, address borrower, @@ -964,6 +972,16 @@ abstract contract DSTestPlus is Test, IPoolEvents { _pool.bucketTake(borrower, true, index); } + function _assertDepositTakeZeroBidRevert( + address from, + address borrower, + uint256 index + ) internal { + changePrank(from); + vm.expectRevert(IPoolErrors.InvalidAmount.selector); + _pool.bucketTake(borrower, true, index); + } + function _assertStampLoanAuctionActiveRevert( address borrower ) internal { @@ -1326,14 +1344,11 @@ abstract contract DSTestPlus is Test, IPoolEvents { _pool.moveQuoteToken(amount, fromIndex, toIndex, type(uint256).max, true); } - function _assertTakeAuctionInCooldownRevert( + function _assertRepayAuctionActiveRevert( address from, - address borrower, - uint256 maxCollateral - ) internal { - changePrank(from); - vm.expectRevert(abi.encodeWithSignature('TakeNotPastCooldown()')); - _pool.take(borrower, maxCollateral, from, new bytes(0)); + uint256 maxAmount + ) internal virtual { + // to be overidden by ERC20/ERC721DSTestPlus } function _assertTakeDebtUnderMinPoolDebtRevert( @@ -1378,6 +1393,16 @@ abstract contract DSTestPlus is Test, IPoolEvents { _pool.kickReserveAuction(); } + function _assertTakeZeroBidRevert( + address from, + address borrower, + uint256 maxCollateral + ) internal { + changePrank(from); + vm.expectRevert(IPoolErrors.InvalidAmount.selector); + _pool.take(borrower, maxCollateral, from, new bytes(0)); + } + function _lup() internal view returns (uint256 lup_) { ( , , , , lup_, ) = _poolUtils.poolPricesInfo(address(_pool)); }