Skip to content

Commit df71eeb

Browse files
SidestreamSweatyPumpkinyondonfu
authored andcommitted
refactor: streamline fee validation methods and enhance reward scenario tests
1 parent 14e8f9c commit df71eeb

2 files changed

Lines changed: 30 additions & 96 deletions

File tree

src/test/BondingManagerRetroactiveRewardCalculationFix.sol

Lines changed: 11 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -27,98 +27,22 @@ contract BondingManagerRetroactiveRewardCalculationFix is BondingManagerRetroact
2727
assertEq(infoAddr, address(newBondingManagerTarget));
2828
}
2929

30-
function _delta(uint256 a, uint256 b) internal pure returns (int256) {
31-
return a >= b ? int256(a - b) : -int256(b - a);
32-
}
33-
34-
function _abs(int256 x) internal pure returns (uint256) {
35-
return uint256(x >= 0 ? x : -x);
36-
}
37-
38-
function testFeeFactorEqualityAfterUpgrade() public {
39-
// Pre-upgrade measurement
40-
CHEATS.revertToState(baselineSnapshot);
41-
FeeMetrics memory baselineConsecutive = _scenarioConsecutive();
42-
CHEATS.revertToState(baselineSnapshot);
43-
FeeMetrics memory baselineMissed = _scenarioMissed();
44-
int256 preUpgradeDelta = _delta(
45-
baselineMissed.cumulativeFeeFactorInc,
46-
baselineConsecutive.cumulativeFeeFactorInc
47-
);
48-
49-
// Post-upgrade measurement
50-
CHEATS.revertToState(baselineSnapshot);
51-
_deployUpgrade();
52-
FeeMetrics memory postConsecutive = _scenarioConsecutive();
53-
CHEATS.revertToState(baselineSnapshot);
30+
function _scenarioConsecutive() internal override returns (FeeMetrics memory) {
5431
_deployUpgrade();
55-
FeeMetrics memory postMissed = _scenarioMissed();
56-
int256 postUpgradeDelta = _delta(postMissed.cumulativeFeeFactorInc, postConsecutive.cumulativeFeeFactorInc);
57-
58-
// Sanity: identical commission parameters preserved
59-
assertEq(postConsecutive.feeShare, postMissed.feeShare, "feeShare mismatch");
60-
assertEq(postConsecutive.commission, postMissed.commission, "commission mismatch");
61-
62-
// Post-upgrade delta less than 1% of pre-upgrade delta
63-
uint256 deltaTolerance = _abs(preUpgradeDelta) / 100000;
64-
if (deltaTolerance == 0) deltaTolerance = 1;
65-
66-
assertTrue(_abs(postUpgradeDelta) <= deltaTolerance, "fee factor deflation persists");
67-
68-
emit log_named_uint("preUpgrade_cumulativeFeeFactor_missed", baselineMissed.cumulativeFeeFactor);
69-
emit log_named_uint("preUpgrade_cumulativeFeeFactor_consec", baselineConsecutive.cumulativeFeeFactor);
70-
emit log_named_uint("aftUpgrade_cumulativeFeeFactor_missed", postMissed.cumulativeFeeFactor);
71-
emit log_named_uint("aftUpgrade_cumulativeFeeFactor_consec", postConsecutive.cumulativeFeeFactor);
72-
emit log_named_int("preUpgrade_cumulativeFeeFactor_delta", preUpgradeDelta);
73-
emit log_named_int("aftUpgrade_cumulativeFeeFactor_delta", postUpgradeDelta);
32+
return super._scenarioConsecutive();
7433
}
7534

76-
function testDelegatorNoFeeLossAfterUpgrade() public {
77-
// Pre-upgrade measurement
78-
CHEATS.revertToState(baselineSnapshot);
79-
_bondDelegator(testDelegator, 1 ether);
80-
_scenarioConsecutive();
81-
CHEATS.prank(testDelegator);
82-
BONDING_MANAGER.claimEarnings(type(uint256).max);
83-
(, uint256 baseFeesCons, , , , , ) = BONDING_MANAGER.getDelegator(testDelegator);
84-
85-
CHEATS.revertToState(baselineSnapshot);
86-
_bondDelegator(testDelegator, 1 ether);
87-
_scenarioMissed();
88-
CHEATS.prank(testDelegator);
89-
BONDING_MANAGER.claimEarnings(type(uint256).max);
90-
(, uint256 baseFeesMiss, , , , , ) = BONDING_MANAGER.getDelegator(testDelegator);
91-
int256 preUpgradeDeltaFees = _delta(baseFeesMiss, baseFeesCons);
92-
93-
// Post-upgrade measurement
94-
CHEATS.revertToState(baselineSnapshot);
35+
function _scenarioMissed() internal override returns (FeeMetrics memory) {
9536
_deployUpgrade();
96-
_bondDelegator(testDelegator, 1 ether);
97-
_scenarioConsecutive();
98-
CHEATS.prank(testDelegator);
99-
BONDING_MANAGER.claimEarnings(type(uint256).max);
100-
(, uint256 postFeesCons, , , , , ) = BONDING_MANAGER.getDelegator(testDelegator);
101-
102-
CHEATS.revertToState(baselineSnapshot);
103-
_deployUpgrade();
104-
_bondDelegator(testDelegator, 1 ether);
105-
_scenarioMissed();
106-
CHEATS.prank(testDelegator);
107-
BONDING_MANAGER.claimEarnings(type(uint256).max);
108-
(, uint256 postFeesMiss, , , , , ) = BONDING_MANAGER.getDelegator(testDelegator);
109-
int256 postUpgradeDeltaFees = _delta(postFeesMiss, postFeesCons);
110-
111-
// Post-upgrade delta less than 1% of pre-upgrade delta
112-
uint256 deltaToleranceFees = _abs(preUpgradeDeltaFees) / 100000;
113-
if (deltaToleranceFees == 0) deltaToleranceFees = 1;
37+
return super._scenarioMissed();
38+
}
11439

115-
assertTrue(_abs(postUpgradeDeltaFees) <= deltaToleranceFees, "delegator fee loss not mitigated sufficiently");
40+
function _validateFeeFactor(uint256 consecutive, uint256 missed) internal override {
41+
// We use 1e12 as a safe tolerance for rounding noise
42+
assertApproxEqAbs(consecutive, missed, 1e12, "Fee factor deflation persists");
43+
}
11644

117-
emit log_named_uint("preUpgrade_delegatorFees_consec", baseFeesCons);
118-
emit log_named_uint("preUpgrade_delegatorFees_missed", baseFeesMiss);
119-
emit log_named_uint("aftUpgrade_delegatorFees_consec", postFeesCons);
120-
emit log_named_uint("aftUpgrade_delegatorFees_missed", postFeesMiss);
121-
emit log_named_int("preUpgrade_delegatorFees_delta", preUpgradeDeltaFees);
122-
emit log_named_int("aftUpgrade_delegatorFees_delta", postUpgradeDeltaFees);
45+
function _validateDelegatorFees(uint256 consecutive, uint256 missed) internal override {
46+
assertEq(consecutive, missed, "Delegator fee loss persists");
12347
}
12448
}

src/test/BondingManagerRetroactiveRewardCalculationPoC.sol

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ contract BondingManagerRetroactiveRewardCalculationPoC is GovernorBaseTest {
5858
uint256 rewardFactorBefore; // cumulativeRewardFactor Previous round
5959
}
6060

61-
function _scenarioConsecutive() internal returns (FeeMetrics memory m) {
61+
function _scenarioConsecutive() internal virtual returns (FeeMetrics memory m) {
6262
_nextRound(); // R1, normal reward claim
6363
CHEATS.prank(transcoder);
6464
BONDING_MANAGER.reward();
@@ -96,7 +96,7 @@ contract BondingManagerRetroactiveRewardCalculationPoC is GovernorBaseTest {
9696
m.rewardFactorBefore = rewardFactorBefore;
9797
}
9898

99-
function _scenarioMissed() internal returns (FeeMetrics memory m) {
99+
function _scenarioMissed() internal virtual returns (FeeMetrics memory m) {
100100
_nextRound(); // R1, normal reward claim
101101
CHEATS.prank(transcoder);
102102
BONDING_MANAGER.reward();
@@ -135,7 +135,18 @@ contract BondingManagerRetroactiveRewardCalculationPoC is GovernorBaseTest {
135135
m.rewardFactorBefore = rewardFactorBefore;
136136
}
137137

138-
function testCompareConsecutiveAndMissedRewardClaims() public {
138+
function _validateFeeFactor(uint256 consecutive, uint256 missed) internal virtual {
139+
// Assert the bug exists (deflation is huge > 1e16)
140+
uint256 deflation = consecutive - missed;
141+
assertGt(deflation, 1e16, "Large fee deflation NOT detected");
142+
}
143+
144+
function _validateDelegatorFees(uint256 consecutive, uint256 missed) internal virtual {
145+
// Assert delegator fee loss exists
146+
assertNotEq(consecutive, missed, "Delegator fee loss NOT detected");
147+
}
148+
149+
function testCompareConsecutiveAndMissedRewardClaims() public virtual {
139150
FeeMetrics memory consecutive = _scenarioConsecutive();
140151
CHEATS.revertToState(baselineSnapshot);
141152
FeeMetrics memory missed = _scenarioMissed();
@@ -145,7 +156,7 @@ contract BondingManagerRetroactiveRewardCalculationPoC is GovernorBaseTest {
145156
assertEq(consecutive.commission, missed.commission, "commission mismatch");
146157

147158
// Missed reward path deflates fee factor increment for identical fee update
148-
assertLt(missed.cumulativeFeeFactorInc, consecutive.cumulativeFeeFactorInc, "fee not deflated");
159+
_validateFeeFactor(consecutive.cumulativeFeeFactorInc, missed.cumulativeFeeFactorInc);
149160
}
150161

151162
function _bondDelegator(address delegator, uint256 amount) internal {
@@ -158,22 +169,21 @@ contract BondingManagerRetroactiveRewardCalculationPoC is GovernorBaseTest {
158169
CHEATS.stopPrank();
159170
}
160171

161-
function testDelegatorFeeLossOnMissedReward() public {
172+
function testDelegatorFeeLossOnMissedReward() public virtual {
162173
_bondDelegator(testDelegator, 1 ether);
163-
FeeMetrics memory cons = _scenarioConsecutive();
174+
_scenarioConsecutive();
164175
CHEATS.prank(testDelegator);
165176
BONDING_MANAGER.claimEarnings(type(uint256).max);
166177
(, uint256 feesAfterCons, , , , , ) = BONDING_MANAGER.getDelegator(testDelegator);
167178

168179
CHEATS.revertToState(baselineSnapshot);
169180

170181
_bondDelegator(testDelegator, 1 ether);
171-
FeeMetrics memory miss = _scenarioMissed();
182+
_scenarioMissed();
172183
CHEATS.prank(testDelegator);
173184
BONDING_MANAGER.claimEarnings(type(uint256).max);
174185
(, uint256 feesAfterMiss, , , , , ) = BONDING_MANAGER.getDelegator(testDelegator);
175186

176-
assertLt(miss.cumulativeFeeFactorInc, cons.cumulativeFeeFactorInc, "fees not deflated");
177-
assertLt(feesAfterMiss, feesAfterCons, "delegator not losing fees");
187+
_validateDelegatorFees(feesAfterCons, feesAfterMiss);
178188
}
179189
}

0 commit comments

Comments
 (0)