Skip to content

Commit

Permalink
Merge branch 'invariant-code-cleanup' into failing-regressions
Browse files Browse the repository at this point in the history
  • Loading branch information
prateek105 committed Dec 12, 2023
2 parents 07c08db + 396bcf6 commit 089922a
Show file tree
Hide file tree
Showing 14 changed files with 660 additions and 319 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ test-swap-load-erc20 :; FOUNDRY_INVARIANT_SHRINK_SEQUENCE=false RUST

# Regression Tests
test-regression-all : test-regression-erc20 test-regression-erc721 test-regression-prototech
test-regression-erc20 :; forge t --mt test_regression --mc ERC20 --nmc "RealWorldRegression|Prototech"
test-regression-erc721 :; forge t --mt test_regression --mc ERC721 --nmc "RealWorldRegression|Prototech"
test-regression-erc20 :; forge t --mt test_regression --mc ERC20 --nmc "RealWorldRegression|Prototech|Position"
test-regression-erc721 :; forge t --mt test_regression --mc ERC721 --nmc "RealWorldRegression|Prototech|Position"
test-regression-rewards :; forge t --mt test_regression --mc Rewards --nmc "RealWorldRegression|Prototech"
test-regression-position :; forge t --mt test_regression --mc Position --nmc "RealWorldRegression|Prototech"
test-regression-prototech :; forge t --mt test_regression --mc Prototech
Expand Down
44 changes: 26 additions & 18 deletions tests/forge/invariants/ERC20Pool/handlers/BasicERC20PoolHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ contract BasicERC20PoolHandler is UnboundedBasicERC20PoolHandler, BasicPoolHandl
numberOfCalls['BBasicHandler.pledgeCollateral']++;

// borrower cannot make any action when in auction
(uint256 kickTime,,,,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor);
if (kickTime != 0) return;
if (_getAuctionInfo(_actor).kickTime != 0) return;

// Prepare test phase
uint256 boundedAmount = _prePledgeCollateral(amountToPledge_);
Expand All @@ -92,8 +91,7 @@ contract BasicERC20PoolHandler is UnboundedBasicERC20PoolHandler, BasicPoolHandl
numberOfCalls['BBasicHandler.pullCollateral']++;

// borrower cannot make any action when in auction
(uint256 kickTime,,,,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor);
if (kickTime != 0) return;
if (_getAuctionInfo(_actor).kickTime != 0) return;

// Prepare test phase
uint256 boundedAmount = _prePullCollateral(amountToPull_);
Expand All @@ -110,8 +108,7 @@ contract BasicERC20PoolHandler is UnboundedBasicERC20PoolHandler, BasicPoolHandl
numberOfCalls['BBasicHandler.drawDebt']++;

// borrower cannot make any action when in auction
(uint256 kickTime,,,,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor);
if (kickTime != 0) return;
if (_getAuctionInfo(_actor).kickTime != 0) return;

// Prepare test phase
uint256 boundedAmount = _preDrawDebt(amountToBorrow_);
Expand All @@ -128,8 +125,7 @@ contract BasicERC20PoolHandler is UnboundedBasicERC20PoolHandler, BasicPoolHandl
numberOfCalls['BBasicHandler.repayDebt']++;

// borrower cannot make any action when in auction
(uint256 kickTime,,,,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor);
if (kickTime != 0) return;
if (_getAuctionInfo(_actor).kickTime != 0) return;

// Prepare test phase
uint256 boundedAmount = _preRepayDebt(amountToRepay_);
Expand All @@ -145,35 +141,46 @@ contract BasicERC20PoolHandler is UnboundedBasicERC20PoolHandler, BasicPoolHandl
function _preAddCollateral(
uint256 amountToAdd_
) internal view returns (uint256 boundedAmount_) {
boundedAmount_ = constrictToRange(amountToAdd_, MIN_COLLATERAL_AMOUNT, MAX_COLLATERAL_AMOUNT);
boundedAmount_ = constrictToRange(
amountToAdd_, MIN_COLLATERAL_AMOUNT, MAX_COLLATERAL_AMOUNT
);
}

function _preRemoveCollateral(
uint256 amountToRemove_
) internal returns (uint256 boundedAmount_) {
boundedAmount_ = constrictToRange(amountToRemove_, MIN_COLLATERAL_AMOUNT, MAX_COLLATERAL_AMOUNT);
boundedAmount_ = constrictToRange(
amountToRemove_, MIN_COLLATERAL_AMOUNT, MAX_COLLATERAL_AMOUNT
);

// ensure actor has collateral to remove
(uint256 lpBalanceBefore, ) = _pool.lenderInfo(_lenderBucketIndex, _actor);
if (lpBalanceBefore == 0) _addCollateral(boundedAmount_, _lenderBucketIndex);
if (_getLenderInfo(_lenderBucketIndex, _actor).lpBalance == 0) {
_addCollateral(boundedAmount_, _lenderBucketIndex);
}
}

function _prePledgeCollateral(
uint256 amountToPledge_
) internal view returns (uint256 boundedAmount_) {
boundedAmount_ = constrictToRange(amountToPledge_, _erc20Pool.collateralScale(), MAX_COLLATERAL_AMOUNT);
boundedAmount_ = constrictToRange(
amountToPledge_, _erc20Pool.collateralScale(), MAX_COLLATERAL_AMOUNT
);
}

function _prePullCollateral(
uint256 amountToPull_
) internal view returns (uint256 boundedAmount_) {
boundedAmount_ = constrictToRange(amountToPull_, MIN_COLLATERAL_AMOUNT, MAX_COLLATERAL_AMOUNT);
boundedAmount_ = constrictToRange(
amountToPull_, MIN_COLLATERAL_AMOUNT, MAX_COLLATERAL_AMOUNT
);
}

function _preDrawDebt(
uint256 amountToBorrow_
) internal override returns (uint256 boundedAmount_) {
boundedAmount_ = constrictToRange(amountToBorrow_, MIN_DEBT_AMOUNT, MAX_DEBT_AMOUNT);
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);
Expand Down Expand Up @@ -218,11 +225,12 @@ contract BasicERC20PoolHandler is UnboundedBasicERC20PoolHandler, BasicPoolHandl
function _preRepayDebt(
uint256 amountToRepay_
) internal returns (uint256 boundedAmount_) {
boundedAmount_ = constrictToRange(amountToRepay_, Maths.max(_pool.quoteTokenScale(), MIN_QUOTE_AMOUNT), MAX_QUOTE_AMOUNT);
boundedAmount_ = constrictToRange(
amountToRepay_, Maths.max(_pool.quoteTokenScale(), MIN_QUOTE_AMOUNT), MAX_QUOTE_AMOUNT
);

// ensure actor has debt to repay
(uint256 debt, , ) = PoolInfoUtils(_poolInfo).borrowerInfo(address(_pool), _actor);
if (debt == 0) {
if (_getBorrowerInfo(_actor).debt == 0) {
boundedAmount_ = _preDrawDebt(boundedAmount_);
_drawDebt(boundedAmount_);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,12 @@ contract PanicExitERC20PoolHandler is UnboundedLiquidationPoolHandler, Unbounded
) external useTimestamps skipTime(skippedTime_) writeLogs {
numberOfCalls['BPanicExitPoolHandler.withdrawBonds']++;

kickerIndex_ = constrictToRange(kickerIndex_, 0, LENDERS - 1);
address kicker = _lenders[kickerIndex_];

(uint256 kickerClaimable, ) = _pool.kickerInfo(kicker);
kickerIndex_ = constrictToRange(kickerIndex_, 0, LENDERS - 1);
address kicker = _lenders[kickerIndex_];

_actor = kicker;
changePrank(_actor);
_withdrawBonds(kicker, kickerClaimable);
_withdrawBonds(kicker, _getKickerInfo(kicker).claimableBond);
}

function settleHeadAuction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ contract BasicERC721PoolHandler is UnboundedBasicERC721PoolHandler, BasicPoolHan
numberOfCalls['BBasicHandler.pledgeCollateral']++;

// borrower cannot make any action when in auction
(uint256 kickTime,,,,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor);
if (kickTime != 0) return;
if (_getAuctionInfo(_actor).kickTime != 0) return;

// Prepare test phase
uint256 boundedAmount = _prePledgeCollateral(amountToPledge_);
Expand All @@ -106,8 +105,7 @@ contract BasicERC721PoolHandler is UnboundedBasicERC721PoolHandler, BasicPoolHan
numberOfCalls['BBasicHandler.pullCollateral']++;

// borrower cannot make any action when in auction
(uint256 kickTime,,,,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor);
if (kickTime != 0) return;
if (_getAuctionInfo(_actor).kickTime != 0) return;

// Prepare test phase
uint256 boundedAmount = _prePullCollateral(amountToPull_);
Expand All @@ -124,8 +122,7 @@ contract BasicERC721PoolHandler is UnboundedBasicERC721PoolHandler, BasicPoolHan
numberOfCalls['BBasicHandler.drawDebt']++;

// borrower cannot make any action when in auction
(uint256 kickTime,,,,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor);
if (kickTime != 0) return;
if (_getAuctionInfo(_actor).kickTime != 0) return;

// Prepare test phase
uint256 boundedAmount = _preDrawDebt(amountToBorrow_);
Expand All @@ -142,8 +139,7 @@ contract BasicERC721PoolHandler is UnboundedBasicERC721PoolHandler, BasicPoolHan
numberOfCalls['BBasicHandler.repayDebt']++;

// borrower cannot make any action when in auction
(uint256 kickTime,,,,,,,,) = _poolInfo.auctionStatus(address(_pool), _actor);
if (kickTime != 0) return;
if (_getAuctionInfo(_actor).kickTime != 0) return;

// Prepare test phase
uint256 boundedAmount = _preRepayDebt(amountToRepay_);
Expand All @@ -159,17 +155,22 @@ contract BasicERC721PoolHandler is UnboundedBasicERC721PoolHandler, BasicPoolHan
function _preAddCollateral(
uint256 amountToAdd_
) internal view returns (uint256 boundedAmount_) {
boundedAmount_ = constrictToRange(amountToAdd_, MIN_COLLATERAL_AMOUNT, MAX_COLLATERAL_AMOUNT);
boundedAmount_ = constrictToRange(
amountToAdd_, MIN_COLLATERAL_AMOUNT, MAX_COLLATERAL_AMOUNT
);
}

function _preRemoveCollateral(
uint256 amountToRemove_
) internal returns (uint256 boundedAmount_) {
boundedAmount_ = constrictToRange(amountToRemove_, MIN_COLLATERAL_AMOUNT, MAX_COLLATERAL_AMOUNT);
boundedAmount_ = constrictToRange(
amountToRemove_, MIN_COLLATERAL_AMOUNT, MAX_COLLATERAL_AMOUNT
);

// ensure actor has collateral to remove
(uint256 lpBalanceBefore, ) = _pool.lenderInfo(_lenderBucketIndex, _actor);
if (lpBalanceBefore == 0) _addCollateral(boundedAmount_, _lenderBucketIndex);
if (_getLenderInfo(_lenderBucketIndex, _actor).lpBalance == 0) {
_addCollateral(boundedAmount_, _lenderBucketIndex);
}
}

function _preMergeCollateral() internal returns(uint256 NFTAmount_, uint256[] memory bucketIndexes_) {
Expand All @@ -179,12 +180,16 @@ contract BasicERC721PoolHandler is UnboundedBasicERC721PoolHandler, BasicPoolHan
uint256 bucketIndex = bucketIndexes_[i];

// Add Quote token in each bucket such that user has enough lps in each bucket to merge collateral
uint256 price = _poolInfo.indexToPrice(bucketIndex);
_addQuoteToken(price, bucketIndex);
_addQuoteToken(
_poolInfo.indexToPrice(bucketIndex),
bucketIndex
);

uint256 collateralAmount = _poolInfo.lpToCollateral(
address(_erc721Pool), _getLenderInfo(bucketIndex, _actor).lpBalance, bucketIndex
);

(uint256 lenderLps, ) = _erc721Pool.lenderInfo(bucketIndex, _actor);
uint256 collateralAmount =_poolInfo.lpToCollateral(address(_erc721Pool), lenderLps, bucketIndex);
NFTAmount_ += collateralAmount;
NFTAmount_ += collateralAmount;
}

// Round collateral amount
Expand All @@ -194,31 +199,35 @@ contract BasicERC721PoolHandler is UnboundedBasicERC721PoolHandler, BasicPoolHan
function _prePledgeCollateral(
uint256 amountToPledge_
) internal view returns (uint256 boundedAmount_) {
boundedAmount_ = constrictToRange(amountToPledge_, MIN_COLLATERAL_AMOUNT, MAX_COLLATERAL_AMOUNT);
boundedAmount_ = constrictToRange(
amountToPledge_, MIN_COLLATERAL_AMOUNT, MAX_COLLATERAL_AMOUNT
);
}

function _prePullCollateral(
uint256 amountToPull_
) internal view returns (uint256 boundedAmount_) {
boundedAmount_ = constrictToRange(amountToPull_, 0, MAX_COLLATERAL_AMOUNT);
boundedAmount_ = constrictToRange(
amountToPull_, 0, MAX_COLLATERAL_AMOUNT
);
}

function _preDrawDebt(
uint256 amountToBorrow_
) internal override returns (uint256 boundedAmount_) {
boundedAmount_ = constrictToRange(amountToBorrow_, MIN_DEBT_AMOUNT, MAX_DEBT_AMOUNT);
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_;
if (_getAuctionInfo(_actor).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
(debt, collateral, ) = _poolInfo.borrowerInfo(address(_pool), _actor);
(uint256 minDebt, , , ) = _poolInfo.poolUtilizationInfo(address(_pool));

if (boundedAmount_ < minDebt && minDebt < MAX_DEBT_AMOUNT) boundedAmount_ = minDebt + 1;
Expand All @@ -235,27 +244,30 @@ contract BasicERC721PoolHandler is UnboundedBasicERC721PoolHandler, BasicPoolHan
(uint256 currentPoolDebt, , , ) = _pool.debtInfo();
uint256 nextPoolDebt = currentPoolDebt + boundedAmount_;
uint256 newLup = _priceAt(_pool.depositIndex(nextPoolDebt));
(debt, collateral, ) = _poolInfo.borrowerInfo(address(_pool), _actor);

BorrowerInfo memory borrowerInfo = _getBorrowerInfo(_actor);
// repay debt if borrower becomes undercollateralized with new debt at new lup
if (!_isCollateralized(debt + boundedAmount_, collateral, newLup, _pool.poolType())) {
if (!_isCollateralized(
borrowerInfo.debt + boundedAmount_, borrowerInfo.collateral, newLup, _pool.poolType())
) {
_repayDebt(type(uint256).max);

(debt, collateral, ) = _poolInfo.borrowerInfo(address(_pool), _actor);
_pullCollateral(collateral);
borrowerInfo = _getBorrowerInfo(_actor);
_pullCollateral(borrowerInfo.collateral);

require(debt == 0, "borrower has debt");
require(borrowerInfo.debt == 0, "borrower has debt");
}
}

function _preRepayDebt(
uint256 amountToRepay_
) internal returns (uint256 boundedAmount_) {
boundedAmount_ = constrictToRange(amountToRepay_, Maths.max(_pool.quoteTokenScale(), MIN_QUOTE_AMOUNT), MAX_QUOTE_AMOUNT);
boundedAmount_ = constrictToRange(
amountToRepay_, Maths.max(_pool.quoteTokenScale(), MIN_QUOTE_AMOUNT), MAX_QUOTE_AMOUNT
);

// ensure actor has debt to repay
(uint256 debt, , ) = PoolInfoUtils(_poolInfo).borrowerInfo(address(_pool), _actor);
if (debt == 0) {
if (_getBorrowerInfo(_actor).debt == 0) {
boundedAmount_ = _preDrawDebt(boundedAmount_);
_drawDebt(boundedAmount_);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,12 @@ contract PanicExitERC721PoolHandler is UnboundedLiquidationPoolHandler, Unbounde
) external useTimestamps skipTime(skippedTime_) writeLogs {
numberOfCalls['BPanicExitPoolHandler.withdrawBonds']++;

kickerIndex_ = constrictToRange(kickerIndex_, 0, LENDERS - 1);
address kicker = _lenders[kickerIndex_];

(uint256 kickerClaimable, ) = _pool.kickerInfo(kicker);
kickerIndex_ = constrictToRange(kickerIndex_, 0, LENDERS - 1);
address kicker = _lenders[kickerIndex_];

_actor = kicker;
changePrank(_actor);
_withdrawBonds(kicker, kickerClaimable);
_withdrawBonds(kicker, _getKickerInfo(kicker).claimableBond);
}

function settleHeadAuction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,19 @@ abstract contract BaseERC721PoolHandler is BaseHandler {
, , ,
) = _poolInfo.auctionStatus(address(_erc721Pool), borrower_);

try _erc721Pool.repayDebt(borrower_, amount_, 0, borrower_, 7388) {

try _erc721Pool.repayDebt(
borrower_,
amount_,
0,
borrower_,
7388
) {
_recordSettleBucket(
borrower_,
borrowerCollateralBefore,
kickTimeBefore,
auctionPrice
);

} catch (bytes memory err) {
_ensurePoolError(err);
}
Expand Down
Loading

0 comments on commit 089922a

Please sign in to comment.