hats-finance / Fenix-Finance-0x83dbe5aa378f3ce160ed084daf85f621289fb92f

0 stars 0 forks source link

`AlgebraPool.initialize` can be frontrun, preventing a new pool from being redeployed with the correct initial price #20

Open hats-bug-reporter[bot] opened 4 months ago

hats-bug-reporter[bot] commented 4 months ago

Github username: -- Twitter username: -- Submission hash (on-chain): 0xd761239566dffec6bfa8f4f57e6b91bf17d2395cf40d05fbda57ae4f37d3fe2f Severity: medium

Description:

Description

so the salt is calculated based on the encoded token0,token1 addresses, and once these token pair has been added to poolByPair; they can't be overwritten:

```javascript
require(poolByPair[token0][token1] == address(0));
```
//@notice: AlgebraPool.initialize function:
  function initialize(uint160 initialPrice) external override {
    int24 tick = TickMath.getTickAtSqrtRatio(initialPrice); // getTickAtSqrtRatio checks validity of initialPrice inside
    if (globalState.price != 0) revert alreadyInitialized(); // after initialization, the price can never become zero
    globalState.price = initialPrice;

Code Snippet

AlgebraFactory.createPool function

function createPool(address tokenA, address tokenB) external override returns (address pool) {
    if (!isPublicPoolCreationMode) {
      _checkRole(POOLS_CREATOR_ROLE);
    }
    require(tokenA != tokenB);
    (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
    require(token0 != address(0));
    require(poolByPair[token0][token1] == address(0));

    address defaultPlugin;
    if (address(defaultPluginFactory) != address(0)) {
      defaultPlugin = defaultPluginFactory.createPlugin(computePoolAddress(token0, token1), token0, token1);
    }

    pool = IAlgebraPoolDeployer(poolDeployer).deploy(defaultBlastGovernor, defaultPlugin, token0, token1);

    poolByPair[token0][token1] = pool; // to avoid future addresses comparison we are populating the mapping twice
    poolByPair[token1][token0] = pool;
    emit Pool(token0, token1, pool);

    if (address(vaultFactory) != address(0)) {
      vaultFactory.createVaultForPool(pool);
    }
  }

AlgebraFactory.initialize function

 function initialize(uint160 initialPrice) external override {
    int24 tick = TickMath.getTickAtSqrtRatio(initialPrice); // getTickAtSqrtRatio checks validity of initialPrice inside
    if (globalState.price != 0) revert alreadyInitialized(); // after initialization, the price can never become zero

Tool used

Manual Review

Recommendation

Update AlgebraFactory.createPool function to initialize the deployed pool:

-function createPool(address tokenA, address tokenB) external override returns (address pool) {
+function createPool(address tokenA, address tokenB,uint256 initialPrice) external override returns (address pool) {
    if (!isPublicPoolCreationMode) {
      _checkRole(POOLS_CREATOR_ROLE);
    }
    require(tokenA != tokenB);
    (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
    require(token0 != address(0));
    require(poolByPair[token0][token1] == address(0));

    address defaultPlugin;
    if (address(defaultPluginFactory) != address(0)) {
      defaultPlugin = defaultPluginFactory.createPlugin(computePoolAddress(token0, token1), token0, token1);
    }

    pool = IAlgebraPoolDeployer(poolDeployer).deploy(defaultBlastGovernor, defaultPlugin, token0, token1);

    poolByPair[token0][token1] = pool; // to avoid future addresses comparison we are populating the mapping twice
    poolByPair[token1][token0] = pool;
    emit Pool(token0, token1, pool);

    if (address(vaultFactory) != address(0)) {
      vaultFactory.createVaultForPool(pool);
    }
+   IAlgebraPool(pool).initialize(initialPrice);
  }
BohdanHrytsak commented 4 months ago

The submission mentions two problems:

This approach is standard and the behaviour is expected. There are also the following points:

  1. The specified problem is located and refers to the code that is OOS
  2. It is also possible to create pools through PoolInitializer.createAndInitialisePoolIfNecessary to prevent this situation
  3. Initialising a pool with an unexpected price does not cause any significant problems