Skip to content

fix(hooks): anchor HeavierHand to the pool's own price; make CapGate cap decimals-safe - #13

Merged
aaronjmars merged 1 commit into
mainfrom
fix/heavierhand-capgate-price-anchor
Sep 5, 2026
Merged

fix(hooks): anchor HeavierHand to the pool's own price; make CapGate cap decimals-safe#13
aaronjmars merged 1 commit into
mainfrom
fix/heavierhand-capgate-price-anchor

Conversation

@aaronjmars

Copy link
Copy Markdown
Contributor

Summary

Fixes two hooks whose gates silently misbehaved on realistic pools, and redeploys both across all 7 chains. The HeavierHand issue is the serious one.

HeavierHand - was permanently one-directional off 1:1

The skew gate compared the two virtual reserves. Their ratio is exactly 1/price (liquidity cancels), so the gate was really comparing the pool's RAW price to an implicit 1.0. Any pool that isn't a same-decimals pair near parity - a USDC(6d)/WETH(18d) pool sits ~8 orders of magnitude off; two 18-dec tokens at price 2.0 are already outside a 10% band - was permanently one-directional: one whole leg of trade reverted forever.

Fix: capture the pool's OWN sqrt price at afterInitialize and gate the current price against THAT, never 1.0. Adds the afterInitialize callback, so flags go 0xC4 -> 0x10C4. The band test compares sqrt prices against precomputed sqrt-band edges (sqrt(1.1), sqrt(0.9) * 2^96) so it never squares a sqrt price and cannot overflow at any drift.

CapGate - cap was decimals-blind

MAX_TRADE = 100e18 was a raw token-unit cap: a no-op on any pool whose specified token had < 18 decimals (100e18 USDC-raw = 100 trillion), and wildly inconsistent across pairs. Replaced with MAX_TRADE_BPS = 500 (5%) of the specified currency's virtual reserve - dimensionless and decimals-safe. Flags unchanged (0xC4). Adds a maxTradeSize() quoter.

Tests

test/fork/GateFix.t.sol (new, Base fork, no cheatcodes): a HeavierHand pool opened at price 4.0 trades BOTH legs (the previously-dead leg swaps), and the gate engages symmetrically inside/beyond the band; CapGate's cap equals exactly 5% of the reserve and rejects an oversize swap while allowing one just under. test/fork/ForkDeploy.t.sol HeavierHand flags bumped to 0x10C4 to match.

Redeployment (new addresses, all verified live)

Redeployed HeavierHand + CapGate across Base, Ethereum, Robinhood, Monad, Arbitrum, BNB, Unichain. New CREATE2 addresses supersede the prior deployments (immutable; the old ones remain on-chain). Registry/marketplace records (hooklist.json, hooks/*.json, HOOKS.md, DEPLOYMENTS.md, aeon.fun) and the "Audited" badge are handled in a separate follow-up.

forge fmt --check clean, forge build clean.

…cap decimals-safe

HeavierHand's skew gate compared the two virtual reserves, whose ratio is
exactly 1/price (liquidity cancels), so it really tested the raw price against
an implicit 1.0. Any pool not near a same-decimals 1:1 (USDC/WETH, or two
18-dec tokens at price 2.0) was permanently one-directional: one whole leg of
trade reverted forever. Re-anchor to the pool's OWN sqrt price captured at
afterInitialize (new flag 0x10C4) and gate the current price against that via
sqrt-band thresholds (never squares a sqrt price, so no overflow at any drift).

CapGate's MAX_TRADE = 100e18 was a raw token-unit cap: a no-op on any pool whose
specified token had < 18 decimals, and wildly inconsistent across pairs. Replace
with MAX_TRADE_BPS = 500 (5%) of the specified currency's virtual reserve -
dimensionless and decimals-safe.

- script/DeployFleet.s.sol: HeavierHand flag set adds AFTER_INITIALIZE.
- test/fork/ForkDeploy.t.sol: same flag bump for HeavierHand.
- test/fork/GateFix.t.sol: new Base-fork behavioral proof (a price-4 pool trades
  both legs; the gate engages symmetrically; CapGate's cap equals 5% of reserves
  and rejects oversize swaps).

Redeployed across 7 chains (Base, Ethereum, Robinhood, Monad, Arbitrum, BNB,
Unichain). New addresses supersede the prior deployments; registry and
address-record updates follow separately.
@aaronjmars
aaronjmars merged commit c0c2ac8 into main Sep 5, 2026
1 check passed
@aaronjmars
aaronjmars deleted the fix/heavierhand-capgate-price-anchor branch September 5, 2026 22:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant