A vulnerability in the _transferToken function of PerpetualVault.sol decrements the totalDepositAmount state variable even when token transfers fail and funds are redirected to the treasury, creating a discrepancy between the actual amount of funds in the system and the recorded total.
This vulnerability does not lead to direct theft of funds but breaks an important system invariant, potentially allowing deposits beyond the configured limit.
In the _transferToken function, when a transfer to a user fails, the funds are correctly redirected to the treasury address. However, the totalDepositAmount is still decremented, creating an accounting discrepancy. This breaks the system's invariant that totalDepositAmount should accurately reflect the total funds deposited in the system.
The vulnerability occurs in the following code:
The issue is that the line totalDepositAmount -= depositInfo[depositId].amount is executed regardless of whether the transfer succeeds or fails. When the transfer fails and funds are sent to the treasury, they still remain in the system but are no longer accounted for in totalDepositAmount.
The following PoC demonstrates the vulnerability:
The PoC demonstrates that when a withdrawal fails and tokens are sent to the treasury, the system incorrectly decrements totalDepositAmount. This allows user2 to deposit funds which, when combined with the treasury balance, exceed the maximum deposit cap.
When run, the test outputs:
This vulnerability can have several impacts:
Deposit Cap Bypass: The system can accumulate more funds than intended, potentially exceeding the maximum deposit cap set for risk management.
Incorrect Accounting: The totalDepositAmount variable no longer accurately reflects the total user funds in the system, breaking an important invariant.
Governance Decisions: Decisions based on totalDepositAmount (such as fee calculations, risk assessments, or protocol upgrades) may be made using incorrect information.
Audit Discrepancies: Regular accounting audits would show a discrepancy between the recorded deposit amount and the actual funds in the treasury and the vault.
Foundry for creating and testing the proof of concept
Manual code analysis
The fix for this vulnerability is straightforward. The totalDepositAmount should only be decremented if the transfer to the user succeeds:
Alternatively, if there's a need to track funds redirected to the treasury due to failed transfers, a separate variable could be introduced to account for these funds:
This way, the system could maintain accurate accounting while still recording the amount of funds that have been redirected due to failed transfers.
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.