From c64106392ff289437183d866486e71e76a9934e4 Mon Sep 17 00:00:00 2001 From: Ed Noepel Date: Fri, 10 Nov 2023 10:50:12 -0500 Subject: [PATCH] revert CRA kick if a liquidation awaits settlement --- src/base/Pool.sol | 3 ++ .../ERC20Pool/ERC20PoolReserveAuction.t.sol | 41 +++++++++++++++++++ tests/forge/utils/DSTestPlus.sol | 5 +++ 3 files changed, 49 insertions(+) diff --git a/src/base/Pool.sol b/src/base/Pool.sol index 07a95ab61..4c6990a5b 100644 --- a/src/base/Pool.sol +++ b/src/base/Pool.sol @@ -406,10 +406,13 @@ abstract contract Pool is Clone, ReentrancyGuard, Multicall, IPool { * @dev update `reserveAuction.latestBurnEventEpoch` and burn event `timestamp` state * @dev === Reverts on === * @dev 2 weeks not passed `ReserveAuctionTooSoon()` + * @dev unsettled liquidation `AuctionNotCleared()` * @dev === Emit events === * @dev - `KickReserveAuction` */ function kickReserveAuction() external override nonReentrant { + _revertIfAuctionClearable(auctions, loans); + // start a new claimable reserve auction, passing in relevant parameters such as the current pool size, debt, balance, and inflator value KickerActions.kickReserveAuction( auctions, diff --git a/tests/forge/unit/ERC20Pool/ERC20PoolReserveAuction.t.sol b/tests/forge/unit/ERC20Pool/ERC20PoolReserveAuction.t.sol index 6d68900b4..6d7647582 100644 --- a/tests/forge/unit/ERC20Pool/ERC20PoolReserveAuction.t.sol +++ b/tests/forge/unit/ERC20Pool/ERC20PoolReserveAuction.t.sol @@ -272,4 +272,45 @@ contract ERC20PoolReserveAuctionNoFundsTest is ERC20HelperContract { assertEq(_availableQuoteToken(), initialAvailableAmount - claimableTokens); } + function testReserveAuctionUnsettledLiquidation() external { + // add reserves to the pool + changePrank(_actor2); + _quote.transfer(address(_pool), 1_000 * 1e18); + _assertReserveAuction({ + reserves: 1_000 * 1e18, + claimableReserves : 1_000 * 1e18, + claimableReservesRemaining: 0, + auctionPrice: 0, + timeRemaining: 0 + }); + skip(2 hours); + + // create an unsettled liquidation + _addInitialLiquidity({ + from: _actor2, + amount: 12_000 * 1e18, + index: _i100_33 + }); + _drawDebt({ + from: _actor3, + borrower: _actor3, + amountToBorrow: 8_000 * 1e18, + limitIndex: _i100_33, + collateralToPledge: 100 * 1e18, + newLup: _p100_33 + }); + _lenderKick({ + from: _actor2, + index: _i100_33, + borrower: _actor3, + debt: 8_007.692307692307696000 * 1e18, + collateral: 100 * 1e18, + bond: 121.559490945280037502 * 1e18 + }); + skip(73 hours); + + // confirm reserve auction may not be kicked + _assertReserveAuctionUnsettledLiquidation(); + } + } diff --git a/tests/forge/utils/DSTestPlus.sol b/tests/forge/utils/DSTestPlus.sol index d5b945159..62cd33600 100644 --- a/tests/forge/utils/DSTestPlus.sol +++ b/tests/forge/utils/DSTestPlus.sol @@ -778,6 +778,11 @@ abstract contract DSTestPlus is Test, IPoolEvents { _pool.kickReserveAuction(); } + function _assertReserveAuctionUnsettledLiquidation() internal { + vm.expectRevert(IPoolErrors.AuctionNotCleared.selector); + _pool.kickReserveAuction(); + } + /**********************/ /*** Revert asserts ***/ /**********************/