141345
high
The mint and withdraw amount is based on totalSupply()
and totalTokenXBalance()
, which based on tokenX balance and lockedPremium
. But if the pool makes a profit with OTM option, the lockedPremium
will be unlocked immediately, changing the mint and withdraw denominator, so the exchange rate for mint and withdraw will change accordingly. A malicious user can abuse this by timing the keeper's transaction for pool profits. The lockupPeriod
can be circumvented by using 2 different wallets.
As a result, some portion of the pool profits will be stolen.
Assuming now a USDC pool has totalSupply of 2000, USDC balance of 400, lockedPremium
is 200. totalTokenXBalance()
should be 200.
A malicious user can do the following:
- prepare 2 wallets A and B, using wallet A to
provide()
200 USDC first, now the pool has totalSupply of 4000, USDC balance of 600,lockedPremium
200,totalTokenXBalance()
should be 400. Waiting until 10 minslockupPeriod
passed, nothing happens during this period. - watch the mempool, a keeper send tx to
unlock()
some option with profit of 100 USDC (OTM), the locked premium of 100 USDC should be unlocked. - the malicious user will front run the tx from the keeper,
provide()
200 USDC with wallet B before the locked premium is unlocked. Wallet B should have pool supply of 2000. The pool now has totalSupply of 6000, USDC balance of 800,lockedPremium
200,totalTokenXBalance()
600. - keeper's tx executed. The pool now has totalSupply of 6000, USDC balance of 800,
lockedPremium
100,totalTokenXBalance()
700. - the user will use wallet A to call
withdraw()
right after keeper's tx. The pool now has totalSupply of 4000, USDC balance of 567.67,lockedPremium
100,totalTokenXBalance()
467.67.
In this example, the user uses 2 wallets, sandwiched the keeper's tx, provide()
200 USDC with wallet B, withdraw()
233.33 USDC with wallet A, total profit 33.33 USDC.
With 2 wallets the lockupPeriod
can be circumvented. After 10 mins, wallet B will be ready to withdraw, it could be done over and over by utilizing 2 different wallets. And pool will lose some portion of the profits from premiums.
The pool will lose some portion of the profits from premiums.
The mint and withdraw amount is based on totalSupply()
and totalTokenXBalance()
totalTokenXBalance()
is based on tokenX balance and lockedPremium
.
lockedPremium
will be changed immediately after unlock()
:
Manual Review
Consider add some time delay in withdraw()
. Calculate the withdraw amount not based on the spot balance, but after some time window.