A user could withdraw collateral right before executing createMarketOrder
.
The race condition occurs because the contract validates the user’s margin balance before actually actually finalizing the trade
Attacker calls createMarketOrder
The function first fetches the attacker’s margin balance
The function validates that the user has enough collateral to cover the required margin.
Before the trade is finalized, the Attacker Withdraws Funds
Since the function does not lock collateral, the attacker can call a separate function that can withdraw the collateral in the same transaction (flashbot/private mempool) or in the next block.
This reduces the account balance below the required margin after validation but before trade execution
Trade Still Executes Without Sufficient Collateral
The order continues execution based outdated margin validation results.
Since margin is no longer available the position is now under-collateralized or completely unbacked
This can trigger unfair liquidations, or worse. let the attacker executes a trade without actually posting any margin.
Meanwhile, the liquidationKeeper
contract is responsible for automating liquidations in the perpsEngine
. However, it's current design allow traders to manipulate their margin balances leading to potential exploits
The checkUpkeep()
function still sees it as solvent since margin was valid at trade time
But by the time performUpkeep()
executes their margin is too low
They avoid liquidation temporarily, potentially allowing bad debt building
Breaking the system logic
Users can execute trade under-collateralized
Manual Review
Lock Collateral until Trade execution completes
Only release the collateral after successful trade execution.
Recheck margin balances inside performUpkeep()
and checkUpkeep()
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.