The calculateUnwindParams() and _executeUnwindOperation() use different formulas to calculate collateralToWithdraw (15.4% discrepancy). Additionally, the user-provided collateralToWithdraw parameter is completely ignored — a local variable shadows the struct field.
calculateUnwindParams() (L464-468) uses debtValue × 1.05 (5% buffer), while _executeUnwindOperation() (L575-577) uses debtValue × (10000 / liqThreshold) ≈ × 1.212 for ETH — a 15.4% difference between preview and execution.
The _collateralToWithdraw parameter in unwindPosition() is stored in the UnwindParams struct and passed through the flash loan, but at line 575, a local variable uint256 collateralToWithdraw = (...) shadows unwindParams.collateralToWithdraw — the struct field is never read.
Likelihood: This inconsistency exists in every unwind call flow. The local variable shadowing is deterministic.
Impact: No direct fund loss — the contract uses its own calculation. However, the API parameter is functionally useless (wastes gas, misleads integrators), and frontends show previews that differ ~15% from execution.
For ETH (liqThreshold=8250): calculateUnwindParams returns debtValue × 1.05, while _executeUnwindOperation computes debtValue × 1.2121 — a 15.4% gap. The user parameter traces through encoding → flash loan → decoding, but the struct field is shadowed at line 575 and never referenced.
Either use the user-provided value (Option A) to align execution with the preview, or remove the unused parameter (Option B) to clean up the API.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.