The PerpetualVault contract’s multi-step withdrawal process allows attackers to inflate the withdrawn amount by injecting extra collateral tokens into the contract during GMX’s asynchronous settlement. By relying solely on balance differentials (collateralToken.balanceOf(this) - prevCollateralBalance) to measure what was “returned” from GMX, the contract cannot distinguish legitimate GMX settlements from unauthorized external transfers. This enables malicious actors to artificially boost final withdrawal amounts.
The issue comes from when the vault initiates a withdrawal and awaits a GMX MarketDecrease settlement. During this time window, the contract simply stores its balance as prevCollateralBalance, then later calculates how much was withdrawn from GMX by doing:
Because there is no validation on where new tokens come from, an attacker can directly transfer additional collateral tokens into the vault’s address after prevCollateralBalance is recorded but before _finalize() runs. The contract then naively interprets any net balance increase as legitimate settlement proceeds:
Attacker requests a legitimate withdrawal, which triggers a GMX settlement and logs prevCollateralBalance.
Before GMX’s order callback calls _finalize(), attacker sends extra tokens to the vault address.
The vault computes withdrawn as the entire difference of collateral balance, erroneously boosting the final withdrawal.
The problem grows more severe in partial withdrawals, where _handleReturn calculates share-based amounts from the vault’s "old” and newly credited balances:
Because withdrawn effectively includes the attacker’s unauthorized transfer, the user’s share calculation is also inflated. Repeated exploits can systematically pull more collateral from the vault than legitimately owed.
This vulnerability enables theft of vault collateral by artificially inflating a withdrawal’s final token count. Attackers can repeatedly exploit each GMX settlement window to manipulate the vault’s balance calculation and extract more value than entitled, potentially draining a significant portion of stored collateral.
Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.
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.