The run() function in the PerpetualVault contract lacks the gmxLock modifier, while its companion function runNextAction() implements it. This inconsistency allows the run() function to be called during ongoing GMX operations, potentially corrupting position states and breaking core vault invariants.
The vulnerability stems from the fact that position management operations with GMX are asynchronous, requiring a callback. During the period between initiating a GMX operation and receiving its callback, the run() function can be invoked again due to missing the protective gmxLock modifier.
The two functions:
Manual code review
Foundry testing framework
The vulnerability can lead to:
Position state corruption
Violation of vault leverage consistency
Incorrect next action execution
Potential loss of funds due to mismanaged positions
Breaking of core protocol invariants, specifically:
"After all actions are completed, nextAction should be empty"
"The leverage of each vault will stay consistent from start to finish"
This test demonstrates the vulnerability by:
Setting up a test environment with a user and keeper
Making an initial deposit
Attempting to open a long position
Verifying the GMX lock is active
Attempting a second position change while the first is in progress
Completing the first position
Verifying the final position state
The test proves that the gmxLock modifier prevents concurrent position changes, which is crucial for maintaining position state integrity and preventing potential financial losses.
Add the gmxLock modifier to the run() function:
This ensures position management operations cannot overlap with ongoing GMX operations, maintaining state consistency and protocol invariants.
The missing gmxLock modifier on the run() function represents a critical vulnerability in the position management system. While runNextAction() is properly protected, the unprotected run() function creates a window where position states can be corrupted during GMX operations. This inconsistency in protection mechanisms could lead to significant issues with position management and potential financial losses. The fix is straightforward - adding the gmxLock modifier to match the protection level of runNextAction().
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.