Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memorialize borrower threshold price on kick #976

Merged
merged 9 commits into from
Nov 17, 2023
1 change: 1 addition & 0 deletions src/interfaces/pool/commons/IPoolState.sol
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ struct Liquidation {
address next; // next liquidated borrower in auctions queue
uint160 bondSize; // [WAD] liquidation bond size
uint96 neutralPrice; // [WAD] Neutral Price when liquidation was started
uint256 thresholdPrice; // [WAD] Threshold Price when liquidation was started
}

/// @dev Struct holding kicker state.
Expand Down
4 changes: 3 additions & 1 deletion src/libraries/external/KickerActions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import {
import {
MAX_INFLATED_PRICE,
_bondParams,
_bpf,
_claimableReserves,
_isCollateralized,
_priceAt,
Expand Down Expand Up @@ -334,6 +333,9 @@ library KickerActions {
vars.neutralPrice
);

// store borrower Threshold price
liquidation.thresholdPrice = Maths.wdiv(vars.borrowerDebt, vars.borrowerCollateral);
prateek105 marked this conversation as resolved.
Show resolved Hide resolved

// update escrowed bonds balances and get the difference needed to cover bond (after using any kick claimable funds if any)
kickResult_.amountToCoverBond = _updateEscrowedBonds(auctions_, vars.bondSize);

Expand Down
7 changes: 1 addition & 6 deletions src/libraries/external/TakerActions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,6 @@ library TakerActions {
vars_ = _prepareTake(
liquidation,
borrower_.t0Debt,
borrower_.collateral,
params_.inflator
);

Expand Down Expand Up @@ -428,7 +427,6 @@ library TakerActions {
vars_= _prepareTake(
liquidation,
borrower_.t0Debt,
borrower_.collateral,
params_.inflator
);

Expand Down Expand Up @@ -681,14 +679,12 @@ library TakerActions {
* - loan is not in auction NoAuction()
* @param liquidation_ Liquidation struct holding auction details.
* @param t0Debt_ Borrower t0 debt.
* @param collateral_ Borrower collateral.
* @param inflator_ The pool's inflator, used to calculate borrower debt.
* @return vars The prepared vars for take action.
*/
function _prepareTake(
Liquidation memory liquidation_,
uint256 t0Debt_,
uint256 collateral_,
uint256 inflator_
) internal view returns (TakeLocalVars memory vars) {

Expand All @@ -704,8 +700,7 @@ library TakerActions {
vars.auctionPrice = _auctionPrice(liquidation_.referencePrice, kickTime);
vars.bondFactor = liquidation_.bondFactor;
vars.bpf = _bpf(
vars.borrowerDebt,
collateral_,
liquidation_.thresholdPrice,
neutralPrice,
liquidation_.bondFactor,
vars.auctionPrice
Expand Down
20 changes: 8 additions & 12 deletions src/libraries/helpers/PoolHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -372,32 +372,28 @@ import { Maths } from '../internal/Maths.sol';
/**
* @notice Calculates bond penalty factor.
* @dev Called in kick and take.
* @param debt_ Borrower debt.
* @param collateral_ Borrower collateral.
* @param neutralPrice_ `NP` of auction.
* @param bondFactor_ Factor used to determine bondSize.
* @param auctionPrice_ Auction price at the time of call.
* @return bpf_ Factor used in determining bond `reward` (positive) or `penalty` (negative).
* @param thresholdPrice_ Borrower tp at time of kick.
* @param neutralPrice_ `NP` of auction.
* @param bondFactor_ Factor used to determine bondSize.
* @param auctionPrice_ Auction price at the time of call.
* @return bpf_ Factor used in determining bond `reward` (positive) or `penalty` (negative).
*/
function _bpf(
uint256 debt_,
uint256 collateral_,
uint256 thresholdPrice_,
uint256 neutralPrice_,
uint256 bondFactor_,
uint256 auctionPrice_
) pure returns (int256) {
int256 thresholdPrice = int256(Maths.wdiv(debt_, collateral_));

int256 sign;
if (thresholdPrice < int256(neutralPrice_)) {
if (int256(thresholdPrice_) < int256(neutralPrice_)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to wrap int256(thresholdPrice_) here and on line 396? or can we just wrap it once at the begginging of the method logic?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need int conversion in the if block. fixing this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done here 1aed6df

// BPF = BondFactor * min(1, max(-1, (neutralPrice - price) / (neutralPrice - thresholdPrice)))
sign = Maths.minInt(
1e18,
Maths.maxInt(
-1 * 1e18,
PRBMathSD59x18.div(
int256(neutralPrice_) - int256(auctionPrice_),
int256(neutralPrice_) - thresholdPrice
int256(neutralPrice_) - int256(thresholdPrice_)
)
)
);
Expand Down
13 changes: 7 additions & 6 deletions tests/forge/unit/Auctions.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ contract AuctionsTest is DSTestPlus {
uint256 collateral = 1000 * 1e18;
uint256 neutralPrice = 15 * 1e18;
uint256 bondFactor = 0.1 * 1e18;
uint256 thresholdPrice = Maths.wdiv(debt, collateral);

assertEq(_bpf(debt, collateral, neutralPrice, bondFactor, price), 0.1 * 1e18);
assertEq(_bpf(9000 * 1e18, collateral, neutralPrice, bondFactor, price), 0.083333333333333333 * 1e18);
assertEq(_bpf(debt, collateral, neutralPrice, bondFactor, 9.5 * 1e18), 0.1 * 1e18);
assertEq(_bpf(9000 * 1e18, collateral, neutralPrice, bondFactor, 9.5 * 1e18), 0.091666666666666667 * 1e18);
assertEq(_bpf(9000 * 1e18, collateral, 10 * 1e18, bondFactor, 10.5 * 1e18), -0.05 * 1e18);
assertEq(_bpf(debt, collateral, 5 * 1e18, bondFactor, 10.5 * 1e18), -0.1 * 1e18);
assertEq(_bpf(Maths.wdiv(debt, collateral), neutralPrice, bondFactor, price), 0.1 * 1e18);
assertEq(_bpf(Maths.wdiv(9000 * 1e18, collateral), neutralPrice, bondFactor, price), 0.083333333333333333 * 1e18);
assertEq(_bpf(Maths.wdiv(debt, collateral), neutralPrice, bondFactor, 9.5 * 1e18), 0.1 * 1e18);
assertEq(_bpf(Maths.wdiv(9000 * 1e18, collateral), neutralPrice, bondFactor, 9.5 * 1e18), 0.091666666666666667 * 1e18);
assertEq(_bpf(Maths.wdiv(9000 * 1e18, collateral), 10 * 1e18, bondFactor, 10.5 * 1e18), -0.05 * 1e18);
assertEq(_bpf(Maths.wdiv(debt, collateral), 5 * 1e18, bondFactor, 10.5 * 1e18), -0.1 * 1e18);
}

/**
Expand Down
26 changes: 13 additions & 13 deletions tests/forge/unit/ERC20Pool/ERC20PoolLiquidationsTake.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract {
from: _lender,
borrower: _borrower2,
maxCollateral: 577 * 1e18,
bondChange: 27.337468146252670459 * 1e18,
bondChange: 27.331814713911545819 * 1e18,
givenAmount: 6_281.628773838729840580 * 1e18,
collateralTaken: 577 * 1e18,
isReward: true
Expand All @@ -755,23 +755,23 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract {
borrower: _borrower2,
active: true,
kicker: _lender,
bondSize: 176.453206233100261662 * 1e18,
bondSize: 176.447552800759137022 * 1e18,
bondFactor: 0.015180339887498948 * 1e18,
kickTime: block.timestamp - 22000 seconds,
referencePrice: 11.314108592233961587 * 1e18,
totalBondEscrowed: 176.453206233100261662 * 1e18,
totalBondEscrowed: 176.447552800759137022 * 1e18,
auctionPrice: 10.886704980656377540 * 1e18,
debtInAuction: 3_653.993019025148320626 * 1e18,
thresholdPrice: 8.638281368853778535 * 1e18,
debtInAuction: 3_653.994432383233602314 * 1e18,
thresholdPrice: 8.638284710125847759 * 1e18,
neutralPrice: 11.314108592233961587 * 1e18
})
);
_assertBorrower({
borrower: _borrower2,
borrowerDebt: 3_653.993019025148320626 * 1e18,
borrowerDebt: 3_653.994432383233602314 * 1e18,
borrowerCollateral: 423.000000000000000000 * 1e18,
borrowert0Np: 9.813927120521769770 * 1e18,
borrowerCollateralization: 1.136655711572588218 * 1e18
borrowert0Np: 9.813930916531551927 * 1e18,
borrowerCollateralization: 1.136655271916324406 * 1e18
});
}

Expand Down Expand Up @@ -1129,9 +1129,9 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract {
from: _lender,
borrower: _borrower2,
maxCollateral: 1_001 * 1e18,
bondChange: 43.529168844258845077 * 1e18,
givenAmount: 10_002.172770738542860841 * 1e18,
collateralTaken: 918.751154597329341626 * 1e18,
bondChange: 43.520176912520187399 * 1e18,
givenAmount: 10_002.175062202988939757 * 1e18,
collateralTaken: 918.751365080156804231 * 1e18,
isReward: true
});

Expand All @@ -1145,7 +1145,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract {
bondFactor: 0,
kickTime: 0,
referencePrice: 0,
totalBondEscrowed: 192.644906931106436280 * 1e18,
totalBondEscrowed: 192.635914999367778602 * 1e18,
auctionPrice: 0,
debtInAuction: 0,
thresholdPrice: 0,
Expand All @@ -1155,7 +1155,7 @@ contract ERC20PoolLiquidationsTakeTest is ERC20HelperContract {
_assertBorrower({
borrower: _borrower2,
borrowerDebt: 0,
borrowerCollateral: 81.248845402670658374 * 1e18,
borrowerCollateral: 81.248634919843195769 * 1e18,
borrowert0Np: 0,
borrowerCollateralization: 1 * 1e18
});
Expand Down
Loading