Liquidity provider fees can be stolen from any pair
An attacker can steal the liquidiy providers fees by transfering liquidity tokens to the pair and then withdrawing fees on behalf of the pair itself.\\nThis is possible because of two reasons:\\nTransfering liquidity tokens to the pair itself doesn't update the fee tracking variables:\\n```\\nif (to != address(this)) {\\n    _updateFeeRewards(to);\\n}\\n```\\n\\nwhich results in the variable `feesPerTokenPaid[address(pair)]` of the pair being equal to 0.\\nThe function withdrawFees() is a permissionless function that allows to withdraw fees on behalf of any address, including the pair itself.\\nBy combining this two quirks of the codebase an attacker can steal all of the currently pending liquidity provider fees by doing the following:\\nAdd liquidity to a pair, which will mint the attacker some liquidity tokens\\nTransfer the liquidity tokens to the pair directly\\nCall withdrawFees() by passing the address of the pair. Because `feesPerTokenPaid[address(pair)]` is 0 this will collect fees on behalf of the pair even if it shouldn't. The function will transfer an amount `x` of WETH from the pair to the pair itself and will lower the `_pendingLiquidityFee` variable by that same amount\\nBecause the variable `_pendingLiquidityFee` has been lowered by `x` the pool will assume someone transferred `x` WETH to it\\nAt this point the attacker can take advantage of this however he likes, but for the sake of the example let's suppose he calls swap() to swap `x` ETH into tokens that will be transferred to his wallet\\nThe attacker burns the liquidity transferred at point `2` to recover his funds\\nPOC\\n
In withdrawFees(pair) add a require statement to prevent fees being withdrawn on behalf of the pool.\\n```\\nrequire(to != address(this));\\n```\\n
Liquidity provider fees can be stolen from any pair.
```\\nif (to != address(this)) {\\n    _updateFeeRewards(to);\\n}\\n```\\n