Skip to main content
Penalty-curve model enables the dynamic fee used in the Penalty for Excessive Fee-Bidding step of the E2E flow. It is the part where MEV bots really receive what they deserve. The hook charges every swap a small baseline fee (0.1%), plus an extra penalty if the swap’s priority fee is unusually high compared to the recent reference median. The penalty only kicks in past a threshold, then grows smoothly up to a hard cap. To decide the penalty, the hook first computes the ratio of the swap’s priority fee to the reference median priority fee. If that ratio is above 2.7x, the penalty kicks in (see The formula below for the exact math). Check the table below to see what ratio will result in what total fee. So the penalty curve looks like this:
Frame 49Frame 49
You can see it is 1.5 curve that has delayed start and has a strict 10% penalty cap.

Design questions

Why is the basic fee 0.1%?

This hook is built for low-liquidity pools — launchpads, meme coins, creator tokens. 0.1% is roughly the market standard there; go lower and LPs stop earning enough to bother providing liquidity.

Why does the penalty start only from 2.7x?

I didn’t want to punish real users. Even people who pick “fast” in their wallet rarely go above ~3x the typical priority fee. So the curve starts at 2.7x — the penalty only really kicks in once you’re past what a normal user would ever pay.

Why is the cap 10%?

Sandwich attacks need two transactions, so a 10% cap becomes ~20% across the attack — more than enough to kill the profit. I capped it rather than let it grow uncapped so a swap can never eat a user’s (or bot’s) entire amount. It’s the sweet spot between real deterrence and not being punitive.

The formula

The curve is computed on-chain with the formula below, using OpenZeppelin’s Math library.

Why frac^1.5 and not a “real” power function

Solidity has no cheap general pow for fractional exponents. But frac^1.5 can be rewritten as:
and sqrt is cheap on-chain via Math.sqrt. So the whole curve costs one multiplication and one integer square root, with no fixed-point ln / exp / pow library needed.

Constants

Formula → code mapping

How this looks in the code

All fixed-point math here uses two scales: PRECISION = 1000 for the ratio (so 2700 means “2.7x”), and WAD = 1e18 for the fractional-exponent part.

Notes

  • M (reference median) is a smoothed value, not the live running median directly — see Priority Fee Median for how it’s derived.
  • Edge case: if referenceMedian <= 0 (no data yet), _getDynamicFee returns BASIC_FEE directly, skipping the ratio/penalty calculation to avoid division by zero.

Key takeaway

  • Every swap pays a flat 0.1% baseline.
  • Nothing extra is charged until the priority fee is 2.7x the reference median.
  • Above that, a smooth frac^1.5 curve adds up to 10% more, saturating at 10x.
  • The whole thing is computed with one multiplication and one Math.sqrt, cheap enough to run on every swap.
Last modified on September 3, 2026