The deposit of a new pair can be stolen
To create a new pair, a user is expected to call the same `addLiquidity()` (or the addLiquidityETH()) function of the router contract seen above:\\n```\\nfunction addLiquidity(\\n    LiquidityParams calldata lp,\\n    uint deadline\\n) external override ensure(deadline) returns (uint256 amountBase) {\\n    if (IDAOfiV1Factory(factory).getPair(\\n        lp.tokenBase,\\n        lp.tokenQuote,\\n        lp.slopeNumerator,\\n        lp.n,\\n        lp.fee\\n    ) == address(0)) {\\n        IDAOfiV1Factory(factory).createPair(\\n            address(this),\\n            lp.tokenBase,\\n            lp.tokenQuote,\\n            msg.sender,\\n            lp.slopeNumerator,\\n            lp.n,\\n            lp.fee\\n        );\\n    }\\n    address pair = DAOfiV1Library.pairFor(\\n        factory, lp.tokenBase, lp.tokenQuote, lp.slopeNumerator, lp.n, lp.fee\\n    );\\n\\n    TransferHelper.safeTransferFrom(lp.tokenBase, lp.sender, pair, lp.amountBase);\\n    TransferHelper.safeTransferFrom(lp.tokenQuote, lp.sender, pair, lp.amountQuote);\\n    amountBase = IDAOfiV1Pair(pair).deposit(lp.to);\\n}\\n```\\n\\nThis function checks if the pair already exists and creates a new one if it does not. After that, the first and only deposit is made to that pair.\\nThe attacker can front-run that call and create a pair with the same parameters (thus, with the same address) by calling the `createPair` function of the `DAOfiV1Factory` contract. By calling that function directly, the attacker does not have to make the deposit when creating a new pair. The initial user will make this deposit, whose funds can now be withdrawn by the attacker.
There are a few factors/bugs that allowed this attack. All or some of them should be fixed:\\nThe `createPair` function of the `DAOfiV1Factory` contract can be called directly by anyone without depositing with any `router` address as the parameter. The solution could be to allow only the `router` to create a pair.\\nThe `addLiquidity` function checks that the pair does not exist yet. If the pair exists already, a deposit should only be made by the owner of the pair. But in general, a new pair shouldn't be deployed without depositing in the same transaction.\\nThe pair's address does not depend on the owner/creator. It might make sense to add that information to the salt.
```\\nfunction addLiquidity(\\n    LiquidityParams calldata lp,\\n    uint deadline\\n) external override ensure(deadline) returns (uint256 amountBase) {\\n    if (IDAOfiV1Factory(factory).getPair(\\n        lp.tokenBase,\\n        lp.tokenQuote,\\n        lp.slopeNumerator,\\n        lp.n,\\n        lp.fee\\n    ) == address(0)) {\\n        IDAOfiV1Factory(factory).createPair(\\n            address(this),\\n            lp.tokenBase,\\n            lp.tokenQuote,\\n            msg.sender,\\n            lp.slopeNumerator,\\n            lp.n,\\n            lp.fee\\n        );\\n    }\\n    address pair = DAOfiV1Library.pairFor(\\n        factory, lp.tokenBase, lp.tokenQuote, lp.slopeNumerator, lp.n, lp.fee\\n    );\\n\\n    TransferHelper.safeTransferFrom(lp.tokenBase, lp.sender, pair, lp.amountBase);\\n    TransferHelper.safeTransferFrom(lp.tokenQuote, lp.sender, pair, lp.amountQuote);\\n    amountBase = IDAOfiV1Pair(pair).deposit(lp.to);\\n}\\n```\\n