58336 sc medium additive update to survival accumulator causing overflow
Description
Brief/Intro
Vulnerability Details
// ============================================ // IN redeem() - Uses MULTIPLICATION // ============================================ function redeem(uint256 amount) external onlyTransmuter { _earmark();
uint256 liveEarmarked = cumulativeEarmarked;
if (amount > liveEarmarked) amount = liveEarmarked;
uint256 transmuterBal = TokenUtils.safeBalanceOf(myt, address(transmuter));
uint256 deltaYield = transmuterBal > lastTransmuterTokenBalance ? transmuterBal - lastTransmuterTokenBalance : 0;
uint256 coverDebt = convertYieldTokensToDebt(deltaYield);
uint256 coverToApplyDebt = amount + coverDebt > liveEarmarked ? (liveEarmarked - amount) : coverDebt;
uint256 redeemedDebtTotal = amount + coverToApplyDebt;
// LOOK HERE: _survivalAccumulator is MULTIPLIED
if (liveEarmarked != 0 && redeemedDebtTotal != 0) {
uint256 survival = ((liveEarmarked - redeemedDebtTotal) << 128) / liveEarmarked;
_survivalAccumulator = _mulQ128(_survivalAccumulator, survival); // ← MULTIPLICATION
_redemptionWeight += PositionDecay.WeightIncrement(redeemedDebtTotal, cumulativeEarmarked);
}
// ... rest of redemption logic
}
// ============================================ // IN _earmark() - Uses ADDITION (BUG!) // ============================================ function _earmark() internal { if (totalDebt == 0) return; if (block.number <= lastEarmarkBlock) return;
uint256 transmuterCurrentBalance = TokenUtils.safeBalanceOf(myt, address(transmuter));
uint256 transmuterDifference = transmuterCurrentBalance > lastTransmuterTokenBalance ? transmuterCurrentBalance - lastTransmuterTokenBalance : 0;
uint256 amount = ITransmuter(transmuter).queryGraph(lastEarmarkBlock + 1, block.number);
uint256 coverInDebt = convertYieldTokensToDebt(transmuterDifference);
amount = amount > coverInDebt ? amount - coverInDebt : 0;
lastTransmuterTokenBalance = transmuterCurrentBalance;
uint256 liveUnearmarked = totalDebt - cumulativeEarmarked;
if (amount > liveUnearmarked) amount = liveUnearmarked;
if (amount > 0 && liveUnearmarked != 0) {
uint256 previousSurvival = PositionDecay.SurvivalFromWeight(_earmarkWeight);
if (previousSurvival == 0) previousSurvival = ONE_Q128;
uint256 earmarkedFraction = _divQ128(amount, liveUnearmarked);
// BUG HERE: _survivalAccumulator uses ADDITION instead of MULTIPLICATION
_survivalAccumulator += _mulQ128(previousSurvival, earmarkedFraction); // ← ADDITION (WRONG!)
_earmarkWeight += PositionDecay.WeightIncrement(amount, liveUnearmarked);
cumulativeEarmarked += amount;
}
lastEarmarkBlock = block.number;
}
Impact Details
Recommended Mitigation
References
Proof of Concept
Proof of Concept
Previous58081 sc medium missing check in function alchemistv3 setminimumcollateralization could lead to set minimumcollateralization globalminimumcollateralization Next58181 sc medium a griefer can cause a permanent dos in tokeautoeth tokeautousdcstrategy allocate
Was this helpful?