DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: low
Invalid

Reentrancy Vulnerability in `PerpetualVault:: _transferToken Function`

Summary

The _transferToken() function in PerpetualVault.sol transfers tokens to the user and treasury without proper reentrancy protection. This could allow an attacker to re-enter the contract during the transfer and manipulate the state.

Vulnerability Details

The function uses collateralToken.transfer and collateralToken.safeTransfer, which could trigger a callback to the contract if the recipient is a malicious contract.
If the attacker re-enters the contract during the transfer, they could manipulate the state (e.g., withdraw additional funds or bypass checks).

Scenario

Alice: A legitimate user who deposits funds into the PerpetualVault contract.

Bob: A malicious attacker who exploits the reentrancy vulnerability.

PerpetualVault: The vulnerable smart contract that allows users to deposit and withdraw funds.

Step 1: Alice Deposits Funds

Alice deposits 100 tokens into the PerpetualVault contract. The contract records her deposit and assigns her a depositId.

Step 2: Bob Prepares for the Attack

Bob notices that the _transferToken function in the PerpetualVault contract lacks reentrancy protection. He decides to exploit this vulnerability.
Bob deploys a malicious contract (let's call it MaliciousWithdrawer) that is designed to exploit the reentrancy bug. This contract has a receive or fallback function that will be triggered when it receives tokens.

Step 3: Bob Deposits Funds

Bob deposits a small amount of tokens (e.g., 1 token) into the PerpetualVault contract. This gives him a valid depositId and makes him eligible to withdraw funds.

Step 4: Bob Initiates the Attack

Bob calls the withdraw function on the PerpetualVault contract, specifying his depositId and setting the recipient address to his MaliciousWithdrawer contract.
The withdraw function calls the vulnerable _transferToken function, which attempts to transfer tokens to Bob's MaliciousWithdrawer contract.

Step 5: Reentrancy Exploit

When the _transferToken function sends tokens to Bob's MaliciousWithdrawer contract, the contract's receive or fallback function is triggered.
Inside this function, Bob's contract re-enters the PerpetualVault contract by calling the withdraw function again before the initial transfer is completed.
Because the _transferToken function has not yet updated the state (e.g., reducing Bob's balance or marking the withdrawal as complete), the contract allows Bob to withdraw funds multiple times.

Step 6: Draining the Contract

Bob's MaliciousWithdrawer contract repeatedly re-enters the PerpetualVault contract, each time withdrawing more funds.
Since the contract's state is not updated until the _transferToken function completes, Bob can drain a significant portion of the contract's funds (e.g., Alice's 100 tokens and any other deposits) before the reentrancy loop is stopped.

Step 7: Bob Escapes with the Funds

Once the attack is complete, Bob transfers the stolen funds from his MaliciousWithdrawer contract to his personal wallet.
Alice and other users are left with significantly reduced or no funds in the PerpetualVault contract

Impact

An attacker could drain funds from the contract or manipulate the state to their advantage.

Tools Used

Manual code review.

Recommendations

Use a reentrancy guard (ReentrancyGuard) for the _transferToken function.

Alternatively, use the checks-effects-interactions pattern to ensure state changes are finalized before external calls.

Updates

Lead Judging Commences

n0kto Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational or Gas

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.

Suppositions

There is no real proof, concrete root cause, specific impact, or enough details in those submissions. Examples include: "It could happen" without specifying when, "If this impossible case happens," "Unexpected behavior," etc. Make a Proof of Concept (PoC) using external functions and realistic parameters. Do not test only the internal function where you think you found something.

n0kto Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational or Gas

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.

Suppositions

There is no real proof, concrete root cause, specific impact, or enough details in those submissions. Examples include: "It could happen" without specifying when, "If this impossible case happens," "Unexpected behavior," etc. Make a Proof of Concept (PoC) using external functions and realistic parameters. Do not test only the internal function where you think you found something.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.