A vulnerability exists in the fee calculation mechanism of the PerpetualVault contract. The contract calculates withdrawal amounts and fees based on the total collateral balance of the vault. An attacker can artificially inflate this balance by directly transferring tokens into the vault, which then triggers fee calculations on an inflated "profit" during withdrawals. This manipulation can cause higher fees to be charged to all users, draining the vault’s funds over time.
Mechanism:
The contract computes a user’s withdrawal amount as a share of the current vault balance using:
Fee Trigger:
A fee is applied if:
This means any increase in the vault balance—even from unauthorized injections—will be treated as profit.
Attack Vector:
An attacker injects extra collateral tokens directly into the vault. This inflates the vault’s balance and forces the fee condition to trigger when a withdrawal occurs.
Impact on Withdrawals:
Both the attacker and honest users will have a fee calculated on an artificially inflated profit, resulting in a net reduction of the withdrawal amounts relative to the true deposit value.
For Attackers:
Although they might not profit directly—since they lose on the extra tokens injected—they can force the system to impose high fees on every withdrawal.
For Honest Users:
The inflated vault balance causes higher fees on withdrawals, effectively draining funds from the vault and diluting the value of each depositor's shares.
Overall Risk:
Over time, repeated exploitation can significantly undermine the vault’s financial integrity, leading to systemic losses for all users.
Manual review
Implement an internal variable to track user deposits rather than relying solely on the raw token balance obtained via collateralToken.balanceOf(address(this)).
Prevent tokens from getting stuck. This is a simple donation to every shareholder, and therefore, every share has more value (profit), leading to fewer shares for future users. If this is not intended by the user, it is merely a mistake! For totalAmountBefore > amount * totalShares, Here is the worst-case scenario (with the minimum amount): first deposit 0.001000 (e4) USDC → 1e12 shares. Second deposit: 0.001 (e4) USDC * 1e12 / 0.001 (e4) USDC. So, the attacker would need to donate 1e16 tokens, meaning 1e10 USDC → 10 billion $. Even in the worst case, it's informational.
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.