58658 sc high cumulativeearmarked not updated
Submitted on Nov 3rd 2025 at 21:05:19 UTC by @emmac002 for Audit Comp | Alchemix V3
Report ID: #58658
Report Type: Smart Contract
Report severity: High
Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol
Impacts:
Contract fails to deliver promised returns, but doesn't lose value
Description
Brief/Intro
The _forceRepay function does not update the global cumulativeEarmarked when repaying debt, unlike the standard repay function which correctly decrements both the individual and global earmarked balances. This discrepancy can lead to an inflated global cumulativeEarmarked and cause miscalculations in liveUnearmarked (totalDebt - cumulativeEarmarked).
Vulnerability Details
In the repay function, it reduces the earmarkToRemove from the individual (account.earmarked) and global variables (cumulativeEarmarked).
// Repay debt from earmarked amount of debt first
uint256 earmarkToRemove = credit > account.earmarked ? account.earmarked : credit;
account.earmarked -= earmarkToRemove;
uint256 earmarkPaidGlobal = cumulativeEarmarked > earmarkToRemove ? earmarkToRemove : cumulativeEarmarked;
cumulativeEarmarked -= earmarkPaidGlobal;But in the _forceRepay function, it only reduces the earmarkToRemove from the individual (account.earmarked) and fails to adjust the global running total:
Impact Details
Since cumulativeEarmarked is used in critical functions like _earmark and _calculateUnrealizedDebt to track system-wide earmarked debt and determine unearmarked debt for yield allocation and redemption, this discrepancy can inflate the global earmarked value and makes liveUnearmarked smaller. _earmark() can’t earmark as much as it should. _calculateUnrealizedDebt() shows each token less debt than it actually has.
References
https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol?utm_source=immunefi#L522-L526 https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistV3.sol?utm_source=immunefi#L761-L762
Proof of Concept
POC
Output:
Change the forcePay function to external:
Output:
Was this helpful?