_collateralToWithdraw Parameter in unwindPosition Is Completely UnusedunwindPosition accepts _collateralToWithdraw as its second parameter (line 238) and stores it in UnwindParams.collateralToWithdraw (line 245).
However, _executeUnwindOperation never reads unwindParams.collateralToWithdraw. Instead, it independently calculates the withdrawal amount from oracle prices and Aave's liquidation threshold:
Likelihood:
Every call to unwindPosition is affected — the dead parameter exists on every invocation
Users who call the companion calculateUnwindParams() to get the "correct" collateralToWithdraw value will pass it in, believing it controls the withdrawal amount
Impact:
Users have a false sense of control over position unwinding — the parameter they provide has zero effect
The actual withdrawal amount is determined entirely by oracle prices and Aave's liquidation threshold at execution time, which may differ significantly from when the user computed their parameters
This creates a trust assumption gap: the user believes they are specifying how much collateral to withdraw, but the protocol ignores their input entirely
How the issue manifests:
Owner calls calculateUnwindParams(collateralToken, borrowToken) which returns (collateralToWithdraw, debtAmount)
Owner calls unwindPosition(collateralToken, collateralToWithdraw, debtToken, debtAmount, swapData, minReturn) with the calculated value
Inside _executeUnwindOperation, the collateralToWithdraw from the user is completely ignored
A fresh calculation using current oracle prices determines the actual withdrawal amount
If prices have moved between the calculateUnwindParams call and the unwindPosition execution, the actual withdrawal amount differs from what the user expected — with no warning or revert
PoC code:
Expected outcome: Both calls execute identically — the _collateralToWithdraw parameter has no effect on the withdrawal amount or any other behavior.
The root cause is that the parameter was added to the function signature but the internal logic was never updated to use it (or vice versa — the internal logic was changed to calculate dynamically but the parameter was never removed).
Option A (Recommended) — Remove the dead parameter:
Why this works: Removing the unused parameter eliminates confusion and aligns the function signature with its actual behavior. This also fixes the interface mismatch (H-003) since IStratax.unwindPosition already has 5 parameters.
Option B — Use the user-provided value:
Tradeoff: Option B gives the user explicit control but requires them to calculate correctly. Option A is simpler and lets the protocol always compute the optimal amount. Option A is preferred for safety and simplicity.
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.