Closed sherlock-admin2 closed 1 month ago
The Maker liquidation system always assumed that the tip and chip parameters are set carefuly by governance, so the protocol does not accumulate bad debt.
This is stated in the contest readme: "As with other collaterals, "tip" and "chip" are assumed to be chosen very carefuly, while taking into account the dust parameter and with having in mind incentive farming risks."
In any case, the discussed logic is unchanged from the original clippers, so out of scope.
chaduke
High
LockstakeClipper.kick() does not add incentives for keepers to tab, the amount of fund to be raised in the auction. As a result, the Vow contract might get into insolvent state eventually.
Summary
LockstakeClipper.kick() does not add incentives for keepers to tab, the amount of fund to be raised in the auction. As a result, the Vow contract might get into insolvent state eventually. This is because the Vow will accumulate more debt in
Vat.sin
than the fund raised during auction, which is supposed to cover the increased debt. It also might lead to overflow and then stalk the protocol, the user's fund might get stuck in the protocol.This will occur for each
kick()
call and loss of funds for the protocol each time, therefore I mark this as high.Root Cause
The following code in
kick()
will increasevat.sin(vow)
by the incentive amount, however, such incentive (coin
) is never added totab
. As a result,tab
amount of fund will be raised, but it might not be sufficient to coverdue + coin
, wheredue = mul(dart, rate)
andcoin
is the incentive for the keeper.https://github.com/sherlock-audit/2024-06-makerdao-endgame/blob/dba30d7a676c20dfed3bda8c52fd6702e2e85bb1/lockstake/src/LockstakeClipper.sol#L229-L271
One might hope that the incentive part will be covered by
tab
as well since additional penalty has been included intab = mul(mul(dart, rate), milk.chop) / WAD
. This assumption might not be true since it is possible thatdue + coin > tab
. In other words, the raised fundtab`` might not cover the increased debt for
vowin
vat.sin(vow), which is
due + coin```.Internal pre-conditions
When
due + coin > tab
wheretab = mul(due, milk.chop) / WAD
. In other words, the raised fundtab`` does not cover the increased debt for
vowin
vat.sin(vow), which is
due + coin```.External pre-conditions
None.
Attack Path
When
due + coin > tab
, each time we liquidate a position, we might have a deficit inVow
. The call workflow is:Dog.bark() -> LockstakeClipper.kick()
, we then call clip.take(). See more in the following POC.Impact
LockstakeClipper.kick() does not add incentives for keepers to tab, the amount of fund to be raised in the auction. As a result, the Vow contract might get into insolvent state eventually. Since vat.sin(vow) will keep increase due to deficit, there might be an overflow and the protocol might stalk, user's funds might get stuck.
PoC
We show that due to not adjusting
tab
according to the incentivecoin
to keepers. Finally, there is a deficit forVow
. This might occur frequently and as a result, the Vow contract might become insolvent.vat.sin(vow)
increases bydue + coin = 202200000000000000000000000000000000000000000000
.tab
amount will be raised, as a result, we have a deficit of 92200000000000000000000000000000000000000000000.Vow
accumulates more debt and become insolvent or leading to overflow and stalk the protocol (users' fund might get stuck in the protocol).The POC is as follows. Run
forge test --match-test testTake1 -vv
to verify all numbers and deficit.Mitigation
We need to add incentive for the keeper to
tab
so that we will raise more fund to cover all debt: