Open sherlock-admin4 opened 5 months ago
1 comment(s) were left on this issue during the judging contest.
takarez commented:
this seems valid valid medium; medium(2)
The protocol team fixed this issue in the following PRs/commits: https://github.com/equilibria-xyz/perennial-v2/pull/302
The Lead Senior Watson signed off on the fix.
panprog
medium
If referral or liquidator is the same address as the account, then liquidation/referral fees will be lost due to local storage being overwritten after the
claimable
amount is credited to liquidator or referralSummary
Any user (address) can be liquidator and/or referral, including account's own address (the user can self-liquidate or self-refer). During the market settlement, liquidator and referral fees are credited to liquidator/referral's
local.claimable
storage. The issue is that the account's local storage is held in the memory during the settlement process, and is saved into storage after settlement/update. This means thatlocal.claimable
storage changes for the account are not reflected in the in-memory cached copy and discarded when the cached copy is saved after settlement.This leads to liquidator and referral fees being lost when these are the account's own address.
Vulnerability Detail
During market account settlement process, in the
_processOrderLocal
, liquidator and referral fees are credited to corresponding accounts via:However, for the account the cached copy of
_locals[account]
is stored after the settlement in_storeContext
:The order of these actions is:
_locals[account]
into memory (context.local
)_locals[account].claimable
is increased for liquidator and referral. Note: this is not reflected incontext.local
_locals[account]
is overwritten with thecontext.local
, losingclaimable
increased during settlement.Impact
If user self-liquidates or self-refers, the liquidation and referral fees are lost by the user (and are stuck in the contract, because they're still subtracted from the user's collateral).
Proof of concept
The scenario above is demonstrated in the test, add this to test/unit/market/Market.test.ts:
Console log:
Code Snippet
Market._credit
modifieslocal.claimable
storage for the account: https://github.com/sherlock-audit/2024-02-perennial-v2-3/blob/main/perennial-v2/packages/perennial/contracts/Market.sol#L678-L684Tool used
Manual Review
Recommendation
Modify
Market._credit
function to increasecontext.local.claimable
if account to be credited matches account which is being updated.