The _transferToken() function in the PerpetualVault contract uses inconsistent token transfer safety patterns, using safeTransfer() for fee transfers but standard transfer() for user withdrawals. This can lead to issues when handling the specific token implementations of WETH, WBTC, LINK, and USDC.
The current implementation looks like this:
The issue is that different ERC20 tokens behave differently on failure:
USDC and WBTC: These tokens typically revert on transfer failure
WETH: Returns false on failure without reverting
LINK: Behavior can depend on the implementation version
Using transfer() directly is problematic because:
For tokens that return false on failure (like WETH), the failure is silently ignored
Even in the catch block, another transfer() is used instead of safeTransfer()
The inconsistent pattern could result in:
Silent failures: With tokens like WETH that return false instead of reverting, a failed transfer might not trigger the catch block, resulting in lost tokens
Treasury transfer failures: If the fallback transfer to treasury also fails, there's no further handling
Given the specific tokens used (WETH, WBTC, LINK, and USDC), this inconsistency creates unpredictable behavior depending on which token is being used as collateral.
Manual code review
The simplest and most reliable solution is to use safeTransfer() consistently throughout the function:
Using SafeERC20's safeTransfer() is particularly important for WETH, which doesn't revert on failure and would otherwise silently fail with the current implementation.
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.
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.
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.