-
Notifications
You must be signed in to change notification settings - Fork 27
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
fix partial redemption stake update #789
Changes from all commits
b84d323
5a44f60
4361708
c45acde
06ca316
28ef54a
394e181
1d9c933
96b13f1
8490e1e
4022621
e58c1f3
d423cea
24d5a29
e841fbc
5dc6669
e5703ed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -287,6 +287,8 @@ abstract contract TargetFunctions is Properties { | |
lt(cdpManager.lastEBTCDebtErrorRedistribution(), cdpManager.totalStakes(), L_17); | ||
totalCdpDustMaxCap += cdpManager.getActiveCdpsCount(); | ||
} | ||
|
||
_checkStakeInvariants(); | ||
} else if (vars.sortedCdpsSizeBefore > _i) { | ||
assertRevertReasonNotEqual(returnData, "Panic(17)"); | ||
} | ||
|
@@ -379,6 +381,27 @@ abstract contract TargetFunctions is Properties { | |
} | ||
} | ||
|
||
function _checkStakeInvariants() private { | ||
if (vars.cdpCollAfter < vars.cdpCollBefore) { | ||
lt(vars.cdpStakeAfter, vars.cdpStakeBefore, CDPM_07); | ||
} | ||
|
||
if (vars.cdpCollAfter > vars.cdpCollBefore) { | ||
gt(vars.cdpStakeAfter, vars.cdpStakeBefore, CDPM_08); | ||
} | ||
|
||
if (vars.totalCollateralSnapshotAfter > 0) { | ||
eq( | ||
vars.cdpStakeAfter, | ||
(vars.cdpCollAfter * vars.totalStakesSnapshotAfter) / | ||
vars.totalCollateralSnapshotAfter, | ||
CDPM_09 | ||
); | ||
} else { | ||
eq(vars.cdpStakeAfter, vars.cdpCollAfter, CDPM_09); | ||
} | ||
} | ||
Comment on lines
+384
to
+403
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
|
||
|
||
/** Active Pool TWAP Revert Checks */ | ||
function observe() public { | ||
// We verify that any observation will never revert | ||
|
@@ -473,6 +496,8 @@ abstract contract TargetFunctions is Properties { | |
lt(cdpManager.lastEBTCDebtErrorRedistribution(), cdpManager.totalStakes(), L_17); | ||
totalCdpDustMaxCap += cdpManager.getActiveCdpsCount(); | ||
} | ||
|
||
_checkStakeInvariants(); | ||
} else if (vars.sortedCdpsSizeBefore > _n) { | ||
if (_atLeastOneCdpIsLiquidatable(cdpsBefore, vars.isRecoveryModeBefore)) { | ||
assertRevertReasonNotEqual(returnData, "Panic(17)"); | ||
|
@@ -492,6 +517,7 @@ abstract contract TargetFunctions is Properties { | |
_partialRedemptionHintNICR, | ||
false, | ||
false, | ||
false, | ||
_maxFeePercentage, | ||
_maxIterations | ||
); | ||
|
@@ -503,6 +529,7 @@ abstract contract TargetFunctions is Properties { | |
uint256 _partialRedemptionHintNICRFromMedusa, | ||
bool useProperFirstHint, | ||
bool useProperPartialHint, | ||
bool failPartialRedemption, | ||
uint _maxFeePercentage, | ||
uint _maxIterations | ||
) public setup { | ||
|
@@ -512,6 +539,7 @@ abstract contract TargetFunctions is Properties { | |
_partialRedemptionHintNICRFromMedusa, | ||
useProperFirstHint, | ||
useProperPartialHint, | ||
failPartialRedemption, | ||
_maxFeePercentage, | ||
_maxIterations | ||
); | ||
|
@@ -523,9 +551,12 @@ abstract contract TargetFunctions is Properties { | |
uint256 _partialRedemptionHintNICRFromMedusa, | ||
bool useProperFirstHint, | ||
bool useProperPartialHint, | ||
bool failPartialRedemption, | ||
uint _maxFeePercentage, | ||
uint _maxIterations | ||
) internal { | ||
require(cdpManager.getActiveCdpsCount() > 1, "Cannot redeem last CDP"); | ||
|
||
_EBTCAmount = between(_EBTCAmount, 0, eBTCToken.balanceOf(address(actor))); | ||
|
||
_maxIterations = between(_maxIterations, 0, 10); | ||
|
@@ -568,7 +599,7 @@ abstract contract TargetFunctions is Properties { | |
_firstRedemptionHintFromMedusa, | ||
bytes32(0), | ||
bytes32(0), | ||
_partialRedemptionHintNICRFromMedusa, | ||
failPartialRedemption ? 0 : _partialRedemptionHintNICRFromMedusa, | ||
_maxIterations, | ||
_maxFeePercentage | ||
) | ||
|
@@ -614,6 +645,8 @@ abstract contract TargetFunctions is Properties { | |
if (vars.isRecoveryModeBefore && !vars.isRecoveryModeAfter) { | ||
t(!vars.lastGracePeriodStartTimestampIsSetAfter, L_16); | ||
} | ||
|
||
_checkStakeInvariants(); | ||
} | ||
|
||
/////////////////////////////////////////////////////// | ||
|
@@ -671,6 +704,8 @@ abstract contract TargetFunctions is Properties { | |
if (vars.isRecoveryModeBefore && !vars.isRecoveryModeAfter) { | ||
t(!vars.lastGracePeriodStartTimestampIsSetAfter, L_16); | ||
} | ||
|
||
_checkStakeInvariants(); | ||
} | ||
|
||
/////////////////////////////////////////////////////// | ||
|
@@ -725,6 +760,8 @@ abstract contract TargetFunctions is Properties { | |
if (vars.isRecoveryModeBefore && !vars.isRecoveryModeAfter) { | ||
t(!vars.lastGracePeriodStartTimestampIsSetAfter, L_16); | ||
} | ||
|
||
_checkStakeInvariants(); | ||
} | ||
|
||
function openCdp(uint256 _col, uint256 _EBTCAmount) public setup returns (bytes32 _cdpId) { | ||
|
@@ -808,6 +845,8 @@ abstract contract TargetFunctions is Properties { | |
gte(_EBTCAmount, borrowerOperations.MIN_CHANGE(), GENERAL_16); | ||
gte(vars.cdpDebtAfter, borrowerOperations.MIN_CHANGE(), GENERAL_15); | ||
require(invariant_BO_09(cdpManager, priceFeedMock.getPrice(), _cdpId), BO_09); | ||
|
||
_checkStakeInvariants(); | ||
} else { | ||
assertRevertReasonNotEqual(returnData, "Panic(17)"); /// Done | ||
} | ||
|
@@ -908,6 +947,8 @@ abstract contract TargetFunctions is Properties { | |
} | ||
|
||
gte(_coll, borrowerOperations.MIN_CHANGE(), GENERAL_16); | ||
|
||
_checkStakeInvariants(); | ||
} else { | ||
assertRevertReasonNotEqual(returnData, "Panic(17)"); | ||
} | ||
|
@@ -978,6 +1019,8 @@ abstract contract TargetFunctions is Properties { | |
} | ||
|
||
gte(_amount, borrowerOperations.MIN_CHANGE(), GENERAL_16); | ||
|
||
_checkStakeInvariants(); | ||
} else { | ||
assertRevertReasonNotEqual(returnData, "Panic(17)"); | ||
} | ||
|
@@ -1050,6 +1093,8 @@ abstract contract TargetFunctions is Properties { | |
|
||
gte(_amount, borrowerOperations.MIN_CHANGE(), GENERAL_16); | ||
gte(vars.cdpDebtAfter, borrowerOperations.MIN_CHANGE(), GENERAL_15); | ||
|
||
_checkStakeInvariants(); | ||
} else { | ||
assertRevertReasonNotEqual(returnData, "Panic(17)"); | ||
} | ||
|
@@ -1122,6 +1167,8 @@ abstract contract TargetFunctions is Properties { | |
|
||
gte(_amount, borrowerOperations.MIN_CHANGE(), GENERAL_16); | ||
gte(vars.cdpDebtAfter, borrowerOperations.MIN_CHANGE(), GENERAL_15); | ||
|
||
_checkStakeInvariants(); | ||
} else { | ||
assertRevertReasonNotEqual(returnData, "Panic(17)"); | ||
} | ||
|
@@ -1198,6 +1245,8 @@ abstract contract TargetFunctions is Properties { | |
if (vars.isRecoveryModeBefore && !vars.isRecoveryModeAfter) { | ||
t(!vars.lastGracePeriodStartTimestampIsSetAfter, L_16); | ||
} | ||
|
||
_checkStakeInvariants(); | ||
} else { | ||
assertRevertReasonNotEqual(returnData, "Panic(17)"); | ||
} | ||
|
@@ -1285,6 +1334,8 @@ abstract contract TargetFunctions is Properties { | |
} | ||
} | ||
gte(vars.cdpDebtAfter, borrowerOperations.MIN_CHANGE(), GENERAL_15); | ||
|
||
_checkStakeInvariants(); | ||
} | ||
|
||
/////////////////////////////////////////////////////// | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The addition of
_updateStakeAndTotalStakes
before marking a partial redemption as cancelled is a critical change to ensure accurate stake accounting during partial redemptions. This adjustment appears to address the identified issue effectively. However, it's essential to consider a few aspects:_updateStakeAndTotalStakes
function does not introduce reentrancy vulnerabilities. Given the context, it seems unlikely, but it's always good practice to review the function's implementation for any external calls or state changes that could be exploited.Overall, the change seems necessary and well-justified based on the PR objectives. However, a thorough review of the mentioned aspects is recommended to ensure the contract's integrity and security.