Skip to content
This repository has been archived by the owner on May 26, 2023. It is now read-only.

Latest commit

 

History

History
60 lines (30 loc) · 3.18 KB

119.md

File metadata and controls

60 lines (30 loc) · 3.18 KB

141345

high

steal pool profit by timing the unlock transaction

Summary

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.

Vulnerability Detail

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:

  1. 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 mins lockupPeriod passed, nothing happens during this period.
  2. 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.
  3. 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.
  4. keeper's tx executed. The pool now has totalSupply of 6000, USDC balance of 800, lockedPremium 100, totalTokenXBalance() 700.
  5. 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.

Impact

The pool will lose some portion of the profits from premiums.

Code Snippet

The mint and withdraw amount is based on totalSupply() and totalTokenXBalance()

https://github.com/sherlock-audit/2022-11-buffer/blob/main/contracts/contracts/core/BufferBinaryPool.sol#L216-L231

https://github.com/sherlock-audit/2022-11-buffer/blob/main/contracts/contracts/core/BufferBinaryPool.sol#L291-L307

totalTokenXBalance() is based on tokenX balance and lockedPremium.

https://github.com/sherlock-audit/2022-11-buffer/blob/main/contracts/contracts/core/BufferBinaryPool.sol#L405-L412

lockedPremium will be changed immediately after unlock():

https://github.com/sherlock-audit/2022-11-buffer/blob/main/contracts/contracts/core/BufferBinaryPool.sol#L328-L333

Tool used

Manual Review

Recommendation

Consider add some time delay in withdraw(). Calculate the withdraw amount not based on the spot balance, but after some time window.