In UpliftOnlyExample users are restricted to a maximum of 100 positions within a certain pool. This is to prevent users from potentially running out of gas when completing an action such as removing liquidity. The fee data from all deposits is looped to decide the appropriate fee upon removal and could potentially run out of gas if the feeDataArray grows too large. The problem is that no check is in place for the afterUpdate hook that is called when a LP token is transferred to a user leaving no limit on the amount of LP positions an attacker could send to a user.
When a user adds liquidity to a pool through addLiquidityProportional they mint a LP NFT to represent their position. Their fee data is also recorded in poolsFeeData for later fee calculations based on LP movement. That array has a maximum length of 100 to prevent accidental DOS to the user. An issue may arise however from the transfer of these LP NFTs to a new user. Within the _update function in the LPNFT contract there is a call to afterUpdate upon transfer of the NFT.
If we take a look inside this function, one of the things it does is update poolsFeeData with the fee data of the NFT being transferred to the new user.
The issue here is there is no check to make sure the user receiving this NFT has 100 or less positions in this pool. An attacker could easily create hundreds of dust LP positions across different wallets and send them to one user, completely blocking them from ever adding liquidity to this pool. If the user already had a position in this LP, they could also send them hundreds of NFTs so that the user would run out of gas when trying to remove their position. This can happen because all of the pool fee data is looped through to calculate fees as seen in onAfterRemoveLiquidity
Add the following test to UpliftOnlyExample.t.sol and run forge test --match-test testTransferBypassesMaxPositions -vv
DOS to users trying to add or remove liquidity from pools
Manual Review
Add same check in place in afterUpdate to ensure a user cannot have more than 100 positions
Likelihood: Medium/High, anyone can receive an unlimited NFT number but will cost creation of LP tokens and sending them. Impact: Low/Medium, DoS the afterUpdate and addLiquidityProportional but will be mitigable on-chain because a lot of those NFT can be burn easily in onAfterRemoveLiquidity.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.