sherlock-audit / 2023-12-ubiquity-judging

2 stars 2 forks source link

bitsurfer - `setPool` open for front-run issue (swap, add liquidity), resulting TWAP oracle failed to initialized #196

Closed sherlock-admin2 closed 6 months ago

sherlock-admin2 commented 6 months ago

bitsurfer

high

setPool open for front-run issue (swap, add liquidity), resulting TWAP oracle failed to initialized

Summary

setPool open for front-run issue, making protocol unable to initialize the metapool thus TWAP oracle failed to initialized

Vulnerability Detail

Looking at following function in LibTWAPOracle, specifically on line 51, require(_reserve0 == _reserve1, "TWAPOracle: PAIR_UNBALANCED"); is open for a front-run attack, thus making owner unable to initialize the metapool for TWAP oracle usage.

File: LibTWAPOracle.sol
31:     function setPool(address _pool, address _curve3CRVToken1) internal {
...
45:         uint256 _reserve0 = uint112(IMetaPool(_pool).balances(0));
46:         uint256 _reserve1 = uint112(IMetaPool(_pool).balances(1));
47:
48:         // ensure that there's liquidity in the pair
49:         require(_reserve0 != 0 && _reserve1 != 0, "TWAPOracle: NO_RESERVES");
50:         // ensure that pair balance is perfect
51:         require(_reserve0 == _reserve1, "TWAPOracle: PAIR_UNBALANCED");
...
59:     }

This exact comparison of balance between Dollar and 3CRV LP definitely will raise issues.

Someone can front-run the setPool, and manipulate these balances, resulting revert on it.

There are several cases to manipulate these balance, for example, swapping one token of 3pool (DAI-USDC-USDT) to Dollar (UbiquityDollar) which is _reserve0, or increase the _reserve1 balance by minting LP via adding liquidity or deposit 3pool (DAI-USDC-USDT)

This means, when Ubiquity protocol deploy the metapool in Curve, initialize, then before calling setPool, it's possible to front-run the transaction.

The front-run could change the balance of either reserve0 or reserve1, thus revert will raise and TWAP oracle will not be initialized correctly.

On a note, metapool allows a single coin to be pooled with all the coins in another (base) pool without diluting its liquidity, means that in the Dollar/3Pool Metapool we can deposit the following:

  • Dollar (UbiquityDollar)
  • Any of the 3Pool (DAI-USDC-USDT)
  • 3Pool LP token (3crv)

Impact

Unable to register or call setPool, thus TWAP oracle failed to initialized.

Since TWAP oracle is not initialized, the LibTWAPOracle.update(); which is crucial in mintDollar and redeemDollar it will break this functionality, thus this can be considered as high issue.

Code Snippet

https://github.com/sherlock-audit/2023-12-ubiquity/blob/main/ubiquity-dollar/packages/contracts/src/dollar/libraries/LibTWAPOracle.sol#L51

Tool used

Manual Review

Recommendation

Consider to remove the require(_reserve0 == _reserve1, "TWAPOracle: PAIR_UNBALANCED"); and give the relative adjustment to the price average based on current balance.

Duplicate of #14

sherlock-admin2 commented 6 months ago

1 comment(s) were left on this issue during the judging contest.

auditsea commented:

The issue describes about DOSing setPool function by manipulating the Curve pool, but it's assumed that the Curve pool deployment, LP deposit, and setPool will be handled in one tx using multicall structure

sherlock-admin2 commented 6 months ago

1 comment(s) were left on this issue during the judging contest.

auditsea commented:

The issue describes about DOSing setPool function by manipulating the Curve pool, but it's assumed that the Curve pool deployment, LP deposit, and setPool will be handled in one tx using multicall structure