Claiming all fees results in unexpected revert #379
Labels
bug
Something isn't working
duplicate-45
grade-b
Q-11
QA (Quality Assurance)
Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax
🤖_34_group
AI based duplicate group recommendation
satisfactory
satisfies C4 submission criteria; eligible for awards
Lines of code
https://github.com/code-423n4/2024-02-uniswap-foundation/blob/main/src/V3FactoryOwner.sol#L190
Vulnerability details
Impact
Attempting to claim all accrued fees from a Uniswap v3 pool triggers a revert due to a gas optimization in the
UniswapV3Pool
function that collects protocol fees.This unexpected behavior can result in MEV searchers missing out on potential profits.
Proof of Concept
The issue lies in
V3FactoryOwner#claimFees()
which usesUniswapV3Pool#collectProtocol()
to collect and send the claimed fees:Notice how if the fees available for collection are less than requested, this results in a
V3FactoryOwner__InsufficientFeesCollected()
revert.Now let's take a look at the implementation of
UniswapV3Pool#collectProtocol()
:Notice the gas saving which decrements the amount of fees to be collected by 1 wei if all of the accrued fees in the pool are requested. This is to ensure that the storage slot for
protocolFees.token0
andprotocolFees.token1
are not set to zero which would be a costly operation from gas perspective.What this means is that if a MEV searcher tries to claim all accumulated fees in a pool, their transaction will fail due to the above mentioned check check in
V3FactoryOwner
:The likelihood of this vulnerability is very high because:
Thus, the impact of this issue is very high and would result in missed profits for many MEV searchers.
Tools Used
Manual review
Recommended Mitigation Steps
While far from ideal, considering that 1 wei is dust, the easiest solution would be to offset the check by 1 wei in
V3FactoryOwner#claimFees()
to account for the gas optimization inUniswapV3Pool#collectProtocol()
:Alternatively, allowing
type(uint128).max
as a value for_amount0Requested
and_amount1Requested
could indicate a request to claim all fees, avoiding the issue entirely.Assessed type
Error
The text was updated successfully, but these errors were encountered: