Skip to content

fix(credit): honour USE_SAFE_PRICES_FLAG in partial-liquidation collateral check - #313

Closed
SashaMIT wants to merge 1 commit into
Gearbox-protocol:mainfrom
SashaMIT:fix/partial-liquidation-safe-prices
Closed

fix(credit): honour USE_SAFE_PRICES_FLAG in partial-liquidation collateral check#313
SashaMIT wants to merge 1 commit into
Gearbox-protocol:mainfrom
SashaMIT:fix/partial-liquidation-safe-prices

Conversation

@SashaMIT

@SashaMIT SashaMIT commented Aug 7, 2026

Copy link
Copy Markdown

Problem

partiallyLiquidateCreditAccount does the two things that, everywhere else in this facade, switch the final collateral check onto safe prices:

  1. _tryWithdrawPhantomToken routes an adapter call into an arbitrary registered target contract via _externalCall (L421).
  2. Two collateral withdrawals (L427-428).

It captures the returned flags — but reads them only for EXTERNAL_CONTRACT_WAS_CALLED_FLAG (L424) and then passes a hardcoded useSafePrices: false into _fullCollateralCheck (L434). L434 is the only hardcoded false in the facade; the multicall path reacts to the identical condition with useSafePrices: flags & USE_SAFE_PRICES_FLAG != 0 (L648).

Safe pricing is materially stricter, not cosmetically: PriceOracleV3._getSafePrice returns min(main, reserve), and returns zero for any token with no reserve feed configured. So a check that should have failed on safe prices can pass on a manipulated main-feed price.

The git history supports this being an omission, not a decision: the useSafePrices: false literal entered this function in e3ff71e (feat: partial liquidations), while the phantom-token adapter call was grafted into the same function later, in 4c7d434 (feat: phantom token withdrawals). The safe-price decision predates the introduction of the external call it was meant to guard against.

Fix

Pass flags & USE_SAFE_PRICES_FLAG != 0 instead of false, matching the multicall path's handling of the identical condition.

Verification

forge build is clean (all lint warnings pre-exist in contracts/test/). One-line change inside the existing flags plumbing; no interface or signature changes.

Made with Cursor

Made with Cursor

…teral check

partiallyLiquidateCreditAccount captures the flags returned by
_tryWithdrawPhantomToken - which routes an adapter call into an
external contract whose state a main price feed can read - but reads
them only for EXTERNAL_CONTRACT_WAS_CALLED_FLAG and then hardcodes
useSafePrices: false in the final _fullCollateralCheck. The multicall
path reacts to the same condition by switching the final collateral
check to safe prices (flags & USE_SAFE_PRICES_FLAG). Safe pricing is
materially stricter: PriceOracleV3._getSafePrice returns
min(main, reserve) and ZERO for a token with no reserve feed, so a
check that should have failed on safe prices can pass on a manipulated
main-feed price.

The useSafePrices:false literal predates the phantom-token call itself
(introduced in e3ff71e; phantom withdrawals grafted in later in
4c7d434), which supports this being an omission rather than a decision.
Honour the flag.
@SashaMIT

SashaMIT commented Aug 8, 2026

Copy link
Copy Markdown
Author

Superseded by a stronger fix: always use safe prices after partial-liquidation withdrawals (matches multicall withdraw semantics; #313 only forwarded the phantom adapter flag). Closing in favor of the new PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant