Pools should be created when ReFi token is either currency0 or currency1. The validation logic checks currency1 twice and never checks currency0, causing all pools where ReFi has the lower address to revert.
Likelihood:
Uniswap V4 sorts currencies by address - lower address becomes currency0
Every pool deployment where ReFi address < paired token address triggers this bug
Impact:
~50% of valid pool configurations rejected at initialization
Protocol unusable for token pairs where ReFi happens to have lower address
When ReFi (0x1111) pairs with USDC (0x2222), Uniswap sorts them as currency0=ReFi, currency1=USDC. The check evaluates currency1 != ReFi which is 0x2222 != 0x1111 = true, so it reverts despite ReFi being present.
Buyers should pay 0% fee and sellers should pay 0.3% fee. The _isReFiBuy function returns true when users sell and false when users buy, causing the opposite fees to be applied.
Likelihood:
Every swap calls this function to determine fee
The return values are backwards for all four possible scenarios
Impact:
Buyers charged 0.3% when they should pay nothing
Sellers pay nothing when they should pay 0.3%
Protocol revenue model completely inverted
When ReFi is currency0 and user sells ReFi (zeroForOne=true), the function returns true indicating a "buy". When user buys ReFi (zeroForOne=false), it returns false indicating a "sell". Both cases apply the wrong fee.
The withdrawTokens function should revert when transfer fails. Non-standard ERC20 tokens like USDT return false on failure instead of reverting, but the return value is ignored and the success event emits regardless.
Likelihood:
Occurs when withdrawing non-standard ERC20s (USDT, BNB, OMG)
Triggers when hook has insufficient balance or token is paused
Impact:
Tokens remain stuck in contract while event claims successful withdrawal
Off-chain systems show incorrect balances
When hook has 500 tokens and owner withdraws 1000, the non-standard token returns false. The return value is not checked so execution continues and emits TokensWithdrawn(1000) while actual balances remain unchanged.
The TokensWithdrawn event declares parameters as (token, to, amount) but emits them as (to, token, amount). Indexed parameters are stored in swapped positions permanently on-chain.
Likelihood:
Every withdrawal emits event with swapped parameters
Indexed data stored permanently in transaction logs
Impact:
Queries filtering by token address return zero results
Off-chain indexers and subgraphs display incorrect data
When withdrawing token 0x1111 to recipient 0x2222, the event stores 0x2222 in topic[1] (token slot) and 0x1111 in topic[2] (recipient slot). Any query for "withdrawals of token 0x1111" finds nothing.
Fee changes should be bounded to prevent malicious values. The ChangeFee function accepts any uint24 value up to 16,777,215 without validation, allowing fees that exceed swap amounts.
Likelihood:
Malicious or compromised owner calls ChangeFee with max value
No timelock allows instant execution
Impact:
Fee exceeding swap amount causes all swaps to revert
User funds trapped in pool with no way to exit
Owner sets sellFee to max uint24. User tries selling 1000 tokens but fee calculates to 167 million tokens. Transaction reverts since fee exceeds balance, trapping all user funds.
Uniswap V4 fees use 1,000,000 as denominator where 3000 equals 0.3%. The calculation uses 100,000 as denominator, making all fees ten times higher than intended.
Likelihood:
Every sell swap uses this calculation
Hardcoded denominator affects all transactions
Impact:
Users pay 3% instead of 0.3% on every sell
Extra 27,000 tokens taken per million swapped
Selling 1,000,000 tokens with sellFee=3000 calculates fee as (1000000 * 3000) / 100000 = 30,000 tokens (3%). Correct calculation with 1,000,000 denominator yields 3,000 tokens (0.3%).
Hooks collect fees by returning non-zero BeforeSwapDelta to the pool manager. The function calculates fees and emits events but always returns ZERO_DELTA, instructing the pool manager to transfer nothing.
Likelihood:
Every swap returns ZERO_DELTA regardless of calculated fee
Hardcoded return value
Impact:
Hook balance remains zero despite fee events claiming collection
Protocol earns no revenue from any swaps
After executing a sell swap, the ReFiSold event claims fees were collected but hook balance stays at zero. The ZERO_DELTA return told pool manager "transfer 0 tokens to hook".
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.