Closed sherlock-admin4 closed 1 month ago
This is clearly specified in the scope...
"wipeAll and wipe do not drip because it is actually not convenient for the user to do a drip call on wipping. Then, if we force the drip, we are incentivizing users to repay directly to the vat (which is possible) instead of using the engine for that. We are mimicking the old proxy actions behaviour, where we drip for drawing, as otherwise the user can lose money, but not forcing the drip on wiping so users actually use this function."
ZeroTrust
Medium
In LockstakeEngine.sol, the functions wipe(), wipeAll(), and free() lack the call to jug.drip(ilk)
Summary
In LockstakeEngine.sol, the functions wipe(), wipeAll(), and free() lack the call to jug.drip(ilk). The absence of jug.drip(ilk) in wipe() and wipeAll() results in users paying fewer fees, while the absence of jug.drip(ilk) in free() causes the collateral value to fall below the debt value after users withdraw collateral, leading to a loss for the protocol.
Root Cause
https://docs.makerdao.com/smart-contract-modules/rates-module/jug-detailed-documentation From the MakerDAO documentation, we know that The primary function of the Jug smart contract is to accumulate stability fees for a particular collateral type whenever its drip() method is called. This effectively updates the accumulated debt for all Vaults of that collateral type as well as the total accumulated debt as tracked by the Vat (global) and the amount of Dai surplus (represented as the amount of Dai owned by the Vow).
https://github.com/sherlock-audit/2024-06-makerdao-endgame/blob/main/lockstake/src/LockstakeEngine.sol#L391
However, in both wipe() and wipeAll(), an outdated rate is used. In wipe(), dart will increase, allowing users to repay more debt. In wipeAll(), wad will decrease, meaning that less Dai is used to repay all the debt.
The lost stability fees depend on the time since the last call to jug.drip. The longer the current time is from the last call to jug.drip, the greater the lost stability fees.
https://github.com/sherlock-audit/2024-06-makerdao-endgame/blob/main/lockstake/src/LockstakeEngine.sol#L340
In the free() function, using an outdated rate might allow users to withdraw more collateral, resulting in the collateral value being less than the debt value.
https://github.com/makerdao/dss/blob/fa4f6630afb0624d04a003e920b0d71a00331d98/src/vat.sol#L142C2-L180C6
In the frob function, the user’s debt in USD is _mul(ilk.rate, urn.art), and the value of the collateral in USD is _mul(urn.ink, ilk.spot). The user’s debt in USD needs to be less than the value of the collateral in USD. However, due to the use of an outdated rate, the debt value calculation is inaccurate. The actual debt value may already be greater than the collateral value.
Internal pre-conditions
No response
External pre-conditions
Attack Path
Impact
The protocol suffers a financial loss.
PoC
No response
Mitigation
Add the jug.drip() call in the wipe(), wipeAll(), and free() functions.