RebateFi Hook

First Flight #53
Beginner FriendlyDeFi
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

ReFiSwapRebateHook – Vulnerability Assessment & Risk Report


Root + Impact

Description

The ReFiSwapRebateHook contract applies dynamic fees for ReFi token swaps and allows the owner to withdraw tokens and adjust fees. The ReFi token itself is mintable by the owner.

Issues Identified:

  1. Owner Fee Control: The owner can arbitrarily set buy and sell fees to extreme values, potentially capturing user funds or blocking trades.

  2. Unlimited Minting: The ReFi token contract allows the owner to mint unlimited tokens, which can dilute all holders and manipulate liquidity pools.

  3. Pool Validation Bug: _beforeInitialize checks currency1 twice instead of both currency0 and currency1, potentially misconfiguring the pool.

// Fee manipulation
hook.ChangeFee(false, 0, true, 100000); // 100% sell fee
// Unlimited minting
ReFi(tokenAddress).mint(ownerAddress, 1_000_000_000 * 10**18);
// Incorrect pool check
if (Currency.unwrap(key.currency1) != ReFi && Currency.unwrap(key.currency1) != ReFi) {
revert ReFiNotInPool();
}

Risk

Likelihood: High

  • Owner functions (ChangeFee and mint) can be executed at any time.

Impact: High

  • Users can lose funds via excessive fees.

  • Token holders can be diluted via unlimited minting.

  • Economic abuse could occur without mitigation.

Scope

Affected Files/Contracts:

  • ReFiSwapRebateHook.sol — fee logic and pool hooks

  • ReFi.sol — mintable token contract

Actors Impacted:

  • Owner: Has administrative control over fees and token supply.

  • Swappers/Users: Subject to dynamic fees and potential economic manipulation.

Severity:

  • High — centralized control over fees and minting can result in direct financial loss or market manipulation.


#Proof of Concept

This PoC demonstrates how the hook’s unrestricted fee‑setting authority, token minting mechanics, and incorrect pool‑validation logic can all be triggered during a normal swap flow. Because the owner has unlimited control and the hook enforces fee logic on every swap, a misconfigured or malicious owner can (1) set extreme fee values, (2) mint arbitrary amounts of the ReFi token, and (3) cause pools to behave unpredictably due to faulty token‑pair validation. The following test scenario shows a combined execution path that reproduces the observed issues in a single sequence.

// Deploy token and hook
ReFi token = new ReFi();
ReFiSwapRebateHook hook = new ReFiSwapRebateHook(address(token));
// Owner mints unlimited tokens
token.mint(owner, 1_000_000_000 * 10**18);
// Owner sets confiscatory sell fee
hook.ChangeFee(false, 0, true, 100000);
// PoolKey with correct pair
PoolKey memory key = PoolKey({
currency0: Currency.wrap(address(token)),
currency1: Currency.wrap(address(0xWETH)),
fee: 3000,
tickSpacing: 1
});
// Pool initialization fails due to incorrect validation
hook._beforeInitialize(address(0), key, 0);
// User tries to sell ReFi tokens, all tokens captured by fees
hook.beforeSwap(
user,
key,
SwapParams({zeroForOne: true, amountSpecified: int256(100 ether), sqrtPriceLimitX96: 0}),
""
);

#Recommended Mitigation

The recommended mitigations aim to limit owner powers, prevent economic abuse, and fix functional bugs. Setting maximum fees and introducing governance or timelocks prevents confiscatory swaps. Capping token minting protects holders from dilution. Correcting pool validation ensures pools initialize correctly, and logging critical actions increases transparency and auditability. Together, these changes reduce risk and protect user funds.

// 1. Owner fee controls
- Allow the owner to set arbitrary buy/sell fees at any time.
+ Introduce maximum limits and timelocks for fee changes.
+ Example: require(_sellFee <= 5000, "Sell fee too high"); // max 50%
+ Consider adding a multi-signature or governance mechanism for critical fee changes.
// 2. Unlimited token minting
- Owner can mint unlimited ReFi tokens.
+ Limit minting to a fixed cap per period or per governance approval.
+ Example: require(totalSupply() + amount <= MAX_SUPPLY, "Exceeds max supply");
// 3. Pool validation logic
- _beforeInitialize incorrectly checks currency1 twice.
+ Fix the validation to check both currencies properly:
+ if (Currency.unwrap(key.currency0) != ReFi && Currency.unwrap(key.currency1) != ReFi) revert ReFiNotInPool();
// 4. General security improvements
+ Consider adding time-based or permissioned withdrawal limits for hook fees.
+ Add event logging for all critical state changes (fees, mints, withdrawals).
+ Conduct formal testing and audits for all new hook logic.
Updates

Lead Judging Commences

chaossr Lead Judge 11 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!