MEDIUM severity: The `GoatV1Factory.sol#createPair()` function is vulnerable to a front-running attack when used in c. The `GoatV1Factory.sol#createPair()` function is vulnerable to a front-running attack when used in conjunction with the `GoatRouterV1.sol#addLiquidity()` function. This vulnerability arises when a new pool is created for a token and liquidity is added using the `addLiquidity()` function.\n\nWhen a p...

Vulnerable code:
```\nfunction _addLiquidity(\n    address token,\n    uint256 tokenDesired,\n    uint256 wethDesired,\n    uint256 tokenMin,\n    uint256 wethMin,\n    GoatTypes.InitParams memory initParams\n) internal returns (uint256, uint256, bool) {\n    GoatTypes.LocalVariables_AddLiquidity memory vars;\n    GoatV1Pair pair = GoatV1Pair(GoatV1Factory(FACTORY).getPool(token));\n    if (address(pair) == address(0)) {\n        pair = GoatV1Pair(GoatV1Factory(FACTORY).createPair(token, initParams));\n        vars.isNewPair = true;\n    }\n\n    if (vars.isNewPair) {\n        // rest of code\n    } else {\n        (uint256 wethReserve, uint256 tokenReserve) = pair.getReserves();\n        uint256 tokenAmountOptimal = GoatLibrary.quote(wethDesired, wethReserve, tokenReserve);\n        if (tokenAmountOptimal <= tokenDesired) {\n            if (tokenAmountOptimal < tokenMin) {\n                revert GoatErrors.InsufficientTokenAmount();\n            }\n            (vars.tokenAmount, vars.wethAmount) = (tokenAmountOptimal, wethDesired);\n        } else {\n            uint256 wethAmountOptimal = GoatLibrary.quote(tokenDesired, tokenReserve, wethReserve);\n            assert(wethAmountOptimal <= wethDesired);\n            if (wethAmountOptimal < wethMin) {\n                revert GoatErrors.InsufficientWethAmount();\n            }\n            (vars.tokenAmount, vars.wethAmount) = (tokenDesired, wethAmountOptimal);\n        }\n    }\n    return (vars.tokenAmount, vars.wethAmount, vars.isNewPair);\n```\n```\nfunction addLiquidity(\n    address token,\n    uint256 tokenDesired,\n    uint256 wethDesired,\n    uint256 tokenMin,\n    uint256 wethMin,\n    address to,\n    uint256 deadline,\n    GoatTypes.InitParams memory initParams\n) external nonReentrant ensure(deadline) returns (uint256, uint256, uint256) {\n    IERC20(token).safeTransferFrom(msg.sender, vars.pair, vars.actualTokenAmount);\n    if (vars.wethAmount!= 0) {\n        IERC20(WETH).safeTransferFrom(msg.sender, vars.pair, vars.wethAmount);\n    }\n    vars.liquidity = GoatV1Pair(vars.pair).mint(to);\n}\n```\n```\nfunction mint(address to) external nonReentrant returns (uint256 liquidity) {\n    if (_vestingUntil == _MAX_UINT32) {\n        // Do not allow to add liquidity in presale period\n        if (totalSupply_ > 0) {\n            revert GoatErrors.PresalePeriod();\n        }\n        // don't allow to send more eth than bootstrap eth\n        if (balanceEth > mintVars.bootstrapEth) {\n            revert GoatErrors.SupplyMoreThanBootstrapEth();\n        }\n\n        if (balanceEth < mintVars.bootstrapEth) {\n            (uint256 tokenAmtForPresale, uint256 tokenAmtForAmm) = _tokenAmountsForLiquidityBootstrap(\n                mintVars.virtualEth, mintVars.bootstrapEth, balanceEth, mintVars.initialTokenMatch\n            );\n            if (balanceToken!= (tokenAmtForPresale + tokenAmtForAmm)) {\n                revert GoatErrors.InsufficientTokenAmount();\n            }\n            liquidity = Math.sqrt(uint256(mintVars.virtualEth) * uint256(mintVars.initialTokenMatch)) - MINIMUM_LIQUIDITY;\n        } else {\n            // This means that user is willing to make this pool an amm pool in first liquidity mint\n            liquidity = Math.sqrt(balanceEth * balanceToken) - MINIMUM_LIQUIDITY;\n            uint32 timestamp = uint32(block.timestamp);\n            _vestingUntil = timestamp + VESTING_PERIOD;\n        }\n        mintVars.isFirstMint = true;\n    }\n}\n```