Back to portfolioPortfolio

Nookleus

A Uniswap v4 hook that studies the other hooks. It reads their pools straight from the PoolManager’s storage, without running any of their code, and once an hour it can move one of its own six fee modules a step toward the abilities that are alive in the ecosystem and the ones its traders back with their fees.

Role
Design, economic analysis, Solidity, testing, launch package and site integration
Launched
20 October 2026, 21:00 UTCBlock 26,236,348, through Programmable’s Custom Launch
Contracts
Nine of mine, all verifiedEtherscan, exact match; plus three of the platform’s contracts
Testing
49 Foundry tests on a mainnet forkAll 49 re-run and passing on 21 October 2026
Stack
Solidity 0.8.26 (via IR), Foundry, Uniswap v4, Chainlink, JavaScript
Hook permissions
0x2ACC

Load a hook

Permission bits, bit 13 first 0x0000

No bits set.

Code size

Families it joins, and the strand each one feeds

  • Dynamic feesthe pool’s fee is dynamic

    TEMPERraises the module fee with volatility

  • Acts before swapsbeforeSwap

    KINSHIPa discount for long holders

  • Acts after swapsafterSwap

    NECTARa share for holders

  • Custom pricingbeforeSwapReturnDelta

    DIGESTbuyback and burn

  • Liquidity rulesany of the six liquidity bits

    ROOTSETH liquidity

  • DonationsbeforeDonate or afterDonate

    SPORESspore hours

Complexity

0of 100

Family

0x0000

Load one of the four hooks or switch on bits.

Fig. 1. A hook, the way Nookleus reads it. Switch on a hook’s permission bits, its dynamic fee and its code size, or load one of the four hooks in these case studies. The families and the complexity score follow FieldGuide._mask and _complexity at commit 933e33b. When this page was built, the four hooks were listed on a fork of mainnet with the deployed FieldGuide, and it stored exactly the values shown here.

The project

Nookleus is a token, NOOK, with one Uniswap v4 pool against ETH. Its hook, the Nucleus, charges each trade on its ETH side and runs six fee modules, called strands, whose levels decide how much a trade pays and where the module fee goes. Around it, three more contracts watch the rest of Uniswap v4: anyone can list a pool in a field guide, a lens reads the listed pools straight from the PoolManager’s storage, and a brain, the Helix, can move one strand one level each hour toward the abilities that are alive in the ecosystem.

The traders steer it too. A trade can name a listed hook in its hook data: a tenth of its module fee goes to the scout who listed that hook, and all of it backs that hook’s families when the Helix next weighs the strands. Nobody can set a level by hand, the owner included.

The problem

Uniswap v4 has thousands of hooks and nothing neutral to tell which abilities are new, which are copies and which pools are alive. A census I ran on 16 October 2026 counted 53,235 pools paired with ETH, 24,228 of them with a hook: 6,038 different hooks in 191 distinct sets of permission bits. In the previous 24 hours, only 95 of the hooked pools had earned any LP fee at all.

A hook that learns from other pools meets two traps. Calling another hook runs its code, and any hook can block or misprice the call. Trusting another pool’s numbers is no better: a pool’s own LP can inflate its measured fees for free. Nookleus reads storage only, caps the say of any one pool at 5% of the total, keeps its index on paper, and lets money follow only the fees traders actually pay.

What I built

  1. A census before any Solidity

    A script read every Uniswap v4 pool paired with ETH and the fees each earned in a day. It showed how thin the signal is, and a probe on a fork showed that a pool’s only LP can manufacture 0.191 ETH of measured fees for a loss of 7 wei and the gas. So nothing that pays money depends on another pool’s measured numbers.

  2. Nine contracts

    The token, with holding age, NECTAR rewards and the launch caps; the hook, with the fees, the six strands, pledges and calls; the Helix, brain and clock; the Lens, which reads other pools; the FieldGuide, with listings, abilities, copies and the Tree of Hooks; the Gut, which buys back and burns and plants ETH liquidity; Specimens, collectible NFTs; Amber, which holds the liquidity; and the Sprout, which launched it all.

  3. A launch in two steps, under the gas cap

    The whole graph needed 24.9 million gas, over the 16,777,216 one Ethereum transaction may use. Four contracts were deployed first and bind only to a caller whose code hash equals the launch contract’s, which only the platform’s factory can create. The launch transaction then used 13,867,046 gas.

  4. Programmable’s launch protection, inside the hook

    For the first 300 seconds, buys had to come through the Universal Router, no wallet could take more than 2% of the supply, and buys in the first 30 seconds paid a surcharge that fell to the normal fee. The module and both vaults are the platform’s unmodified code, created from its published bytes.

  5. 49 tests on a mainnet fork and an adversarial review

    Including the whole launch through the platform’s real factory, the launch protection against the real Universal Router, and the wash-trading probe.

  6. Site integration

    The project’s website wired to the contracts: the census clock, a journal of every move the Helix makes, and a field kit that signs each call from the page: listing a hook, buying with a pledge, calling the next step, sampling pools, challenging a copy, harvesting rewards and the upkeep calls.

Brand and website

Nookleus is drawn as a living cell: a glossy green nucleus with eyes, with hooks hanging around it that visitors can drag in, on a near-black field. Wide Archivo headlines, Inter for text and JetBrains Mono for every number make the site read like a lab instrument, and the Journal’s census dial counts down to the next hourly step.

Palette
Background #050608Text #F4F4F0Green #3DFFA8Violet #8A6BFFAmber #FFB547
Type
Archivo for headlines, wideInter for textJetBrains Mono for data
Nookleus logo: a green nucleus with eyes inside the orbits of an atom
Logo: the nucleus.
Nookleus website: the headline The nucleus of the hook economy next to a glossy green nucleus with hooks around it
Website: the opening screen; the hooks can be dragged into the nucleus.
Nookleus website Journal: a dial counting down to the next hourly census, and the grid of trait modules
Website: the Journal, with the census dial.
Nookleus Journal on a phone
On a phone.

How it works

  1. 1List

    Anyone lists a Uniswap v4 pool with a 0.002 ETH deposit. The FieldGuide records the hook’s 14 permission bits, whether the pool’s fee is dynamic, a complexity score, and whether the code copies an older listing, byte for byte or with only its metadata changed.

  2. 2Read

    The Lens reads up to 192 listed ETH pools straight from the PoolManager’s storage, each at most once an hour, and turns their fees and depth into the share of each family over a day and a week. No pool counts for more than 5% of the total.

  3. 3Back

    A trade can name a listed hook in its hook data. A tenth of its module fee goes to the scout who listed it, and the whole module fee backs that hook’s families.

  4. 4Preview

    At :45 each hour the Helix blends the ecosystem’s shares with the traders’ backing and plans at most one step, of one level, for one of the six strands. Anyone can call which step it will be.

  5. 5Step

    At the first pulse of the next hour the plan applies. Trades pulse the Helix for free when one is due; if the pulse fails, the trade still goes through.

  6. 6Pay

    Every trade pays 2.8% of its ETH side: 0.30% to the platform, 1.50% to the owner and 1.00% to the modules, which split it between holders, buyback and burn, liquidity, spore hours and the observers who keep the readings fresh.

TEMPERfollows dynamic fees

each level adds 0.125% x volatility to the module feeat 8: up to +1.00%

KINSHIPfollows hooks that act before swaps

each level takes 6.25% off the module fee for wallets holding 1M NOOK for 7 daysat 8: half off

NECTARfollows hooks that act after swaps

each level sends 7.5% of the module fee to holdersat 8: 60%

DIGESTfollows custom pricing

each level sends 7.5% to buyback and burn, plus whatever no strand claimsat 8: 60% and the rest

ROOTSfollows liquidity rules

each level sends 2.5% to ETH liquidity the Gut plants above the priceat 8: 20%

SPORESfollows donations

each level sends 2.5% to a pot paid to holders in spore hours, and adds one spore hour a dayat 8: 20%, 8 hours

Fig. 2. The six strands and what each level does, with every strand at its starting level, 4, as read from mainnet on 21 October 2026. TEMPER and KINSHIP change what a trade pays; the other four change where the module fee goes, after the observers’ 5%.

Trade. Every swap pays its fee. When a pulse is due, the swap runs it with at most 1,200,000 gas; if the pulse fails, the swap still goes through and the pulse is tried again 15 minutes later.

Call. Anyone may call which step the coming preview will plan, for free or inside a trade. Each address has one open call.

Preview. At :45 the Helix weighs the Lens’s family shares and the traders’ backing, and plans at most one step of one level for the next hour. Two evaluations in a row must agree.

Apply. The first pulse of the next hour applies the plan; the fees are split at the old levels first.

Score. Once the hour is over, a correct call earns a point, and the first to call a level the pool never held earns a Trait NFT.

Fig. 3. One hour of the Helix. Spore hours are drawn at the first pulse of each UTC day, a weekly experiment can lift the rarest family on Wednesdays at 12:45 UTC, and a season closes every 30 days. A missed hour is skipped, not stacked.

0.30%The launch platform
1.50%The owner
1.00%The modules, split as below
5%Observers, who keep the readings fresh
28.5%NECTAR, to holders
47.5%DIGEST, buyback and burn
9.5%ROOTS, ETH liquidity
9.5%SPORES, the spore pot

Fig. 4. Where a trade’s 2.8% goes, and how the module’s 1.00% is split at the starting levels. TEMPER and KINSHIP move the module fee between 0.50% and 2.00%, so a trade pays between 2.3% and 3.8%; for the first 300 seconds the owner’s share was 5%.

The contracts, reviewed

Supply and minting

One billion NOOK were created once, in the launch, and all of them went into the pool. No function can create more.

For developers

SUPPLY = 1_000_000_000e18 is minted to the Sprout in the constructor; there is no mint. Sprout.launch placed the whole supply in one band, made the first buy for the owner and burned the rounding leftover: 4,321 wei.

Burning

Any holder can burn their own tokens. Everything the Gut buys back is burned, and so are the NOOK fees of the liquidity it plants.

For developers

burn(amount); there is no burnFrom. Gut.digest burns all it buys and Gut.gather burns a ROOTS position’s NOOK fees. A transfer to the zero address is not a burn.

Transfers and launch rules

No tax on transfers. Nothing moved before the launch. For the first five minutes no wallet could receive more than 2% of the supply, and buys had to come through the Universal Router. Every balance carries a holding age.

For developers

_move reverts TradingNotStarted before start(), except for the Sprout’s seed. For PROTECTION_SECONDS = 300, receipts per wallet were capped at walletTokenLimit (20,000,000 NOOK), with nobody exempt. The age blends on every receipt: since = (balance x since + amount x now) / (balance + amount).

Fees

Every trade pays 2.8% of its ETH side: 0.30% to the platform, 1.50% to the owner and 1.00% to the modules, which can move it between 2.3% and 3.8%. The pool’s LP fee is zero. A swap that names an ETH amount must fill whole.

For developers

The rate is 3_000 + ownerPips() + module pips, with ownerPips() at 50,000 for 300 seconds after the opening and 15,000 after it; owner plus module never pass HOOK_CAP_PIPS = 35_000 after the window. ETH-named trades pay in beforeSwap, the rest in afterSwap, as ERC-6909 claims; a partial fill reverts PartialFill.

m = MODULE_PIPS;
uint256 tl = uint8(lv >> (8 * TEMPER));
if (tl != 0) {
    (, int24 tick,,) = MANAGER.getSlot0(key.toId());
    m += (tl * TEMPER_STEP_PIPS * _volatility(s, tick)) / 10_000;
}
uint256 kl = uint8(lv >> (8 * KINSHIP));
if (kl != 0) {
    (uint256 age, uint256 bal) = INookToken(NOOK).ageOf(tx.origin);
    if (age >= KIN_AGE && bal >= KIN_MIN) m -= (m * kl * KIN_STEP_BPS) / 10_000;
}

Holder rewards (NECTAR)

Part of the module fee goes to holders as ETH, by the number of tokens they hold. Until 1% of the supply is held, rewards are shared as if it were, so an early buyer cannot take a whole early pot. Holders collect their share themselves.

For developers

flow() redeems the books and calls Nook.feed: shared = amount x eligible / max(eligible, FLOOR) with FLOOR = SUPPLY / 100, and acc += shared x 1e30 / eligible; the rest waits for spread(). harvest() pays the caller. The PoolManager, the hook, the Gut and Amber are excluded.

The brain (Helix)

Once an hour, the Helix can move one strand by one level, between 0 and 8. It weighs how alive each family is across the listed pools and how much traders back it with their fees. A step needs two evaluations in a row to agree, and a strand that falls to zero waits six hours before it can rise.

For developers

sig = 0.6 x (dayShare - plain) + 0.4 x (weekShare - plain), blended half and half with the pledge shares when any exist; nothing moves inside a 0.03 dead band. The target 4 + 16 x sig, clamped to 0..8, must clear the level by 0.75. The candidate is drawn by weight from keccak256(prevrandao, blockhash(n - 1), hour, species) at PREVIEW_AT = 2700 seconds past the hour and applied at the next.

The Lens

The Lens never calls another hook. It reads the pools’ prices, liquidity and fee growth straight from the PoolManager’s storage, at most once an hour per pool, and pays a small bounty to whoever takes the readings.

For developers

sample reads extsload words at keccak256(poolId, 6) and reverts Unlocked when it runs inside a PoolManager callback, so flash liquidity cannot be sampled. Depth may at most double every 6 hours, a pool’s fee rate is capped at 5% of its depth a day, and its say at 5% of the total. BOUNTY = 0.00002 ether per pool; up to 192 pools.

The FieldGuide

Anyone can list a pool for a 0.002 ETH deposit, refundable after seven days. An exact copy of an older hook scores zero for originality, and anyone who proves a near-copy takes its deposit. The first hook of a new family earns a Species NFT and joins the Tree of Hooks under its closest older relative.

For developers

abilities = hook & 0x3fff and family = abilities | dynamic << 14. A copy has an older listing’s code hash, with or without the CBOR metadata; originality = 400 / (3 + count). contest proves a near-copy: equal code outside masked ranges of at most max(len / 100, 64) bytes. A parent is the earliest family one bit away, else two.

Owner and admin powers

There is no administrator: no pause, no upgrade, no setter. The owner wallet only receives, 1.5% of every trade and whatever Amber collects. It cannot change the fees, the strands or anyone’s balance.

For developers

No contract has an owner-only function, a proxy or a delegatecall. OWNER is an immutable recipient in Nucleus, Amber and Sprout. remitOwner() can be called by anyone and pays only the owner. The wiring calls (designate, start, bind, markOpening) were Sprout-only and ran in the launch transaction.

Liquidity

The launch liquidity is one position held by Amber, which has a single function: send the position’s fees to the owner. The hook refuses any removal, so the position can never be withdrawn. With a 0% LP fee, it earns nothing from trades.

For developers

The first add had to be the band [-887,220, openTick]; later adds come only from the Gut. beforeRemoveLiquidity reverts NoRemoval for any nonzero liquidity. Amber.collect(tokenId) runs DECREASE_LIQUIDITY 0 and TAKE_PAIR to OWNER; position NFT #475267 is held by Amber.

Randomness and outside data

The step the Helix takes and the daily spore hours are drawn from the block’s own randomness; the brain uses no oracle. The only outside input was Chainlink’s ETH price, read once at launch to check the platform’s minimum opening value.

For developers

Picks use keccak256(prevrandao, blockhash(n - 1), hour, species) and spore hours keccak256(prevrandao, day, species). Sprout.launch read the Chainlink ETH/USD feed, at most one hour old, before opening the pool.

Testing and security

49Foundry tests on a mainnet fork, all passing when re-run on 21 October 2026
13,867,046Gas used by the launch transaction, under the 16,777,216 a transaction may use; the whole graph would have needed 24.9 million
12 of 12Launch-protection scenarios passed in the launch platform’s manual review

An adversarial review before launch found a critical flaw: an overflow in the paper index could make the season roll revert inside beforeSwap and halt every swap, with no administrator to fix it. Every optional step on the swap path now runs in try/catch with a gas cap, and a failed pulse is retried fifteen minutes later while the trade goes through. The review also found that a sample taken inside an attacker’s own PoolManager callback would have read 9,850 ETH of flash liquidity as depth, so sampling now refuses inside any callback; and that 192 junk listings could keep real ones out for three days, so the Lens now evicts lifeless pools. Staging the site on a fork then caught a call-order bug that would have kept the observers’ Almanac from ever minting; it was fixed with a regression test.

Measured on a mainnet fork on 21 October 2026 (test/Gas.t.sol), with cold storage and execution gas only, except the launch, which is the mainnet transaction.
OperationGas
Buy, exact ETH in224,612
Sell, exact NOOK in189,764
Buy with a pledge and a call286,945
Buy that runs the hourly preview342,818
Buy on a new UTC day, spore hours drawn260,746
Buy closing a season a day overdue759,491
Sample 8 pools, steady state696,929
Flow, books to holders, Gut and Lens361,247
Digest, buyback and burn299,946
Plant, ETH liquidity261,271
List a pool, new family and Tree search743,532
Launch transaction on mainnet13,867,046

Limits, stated plainly

  1. The signal is thin. On 16 October 2026, only 95 hooked pools paired with ETH earned any LP fee in a day, and the Lens sees only LP fees and donations: fees a hook takes through return deltas, as Nookleus itself does, are invisible to it.
  2. A pool’s own LP can inflate its measured fees for free. Ratings are shown, but nothing that pays money depends on one, and no pool’s say passes 5% of the total.
  3. Copy detection catches identical code and the near-copies a challenger proves. A rewritten copy reads as new.
  4. KINSHIP reads the wallet that signs the trade, so a bot trading through an aged wallet gets the discount too.
  5. The Helix moves only when something pulses it, usually a trade, and a block proposer can nudge which strand is picked. Until pools are listed and sampled, it has nothing to read and holds.

Status on chain

Read from Ethereum mainnet on 21 October 2026, block 26,242,797

  • One pool, ETH against NOOK, with an LP fee of zero; the launch position is held by Amber.
  • No hook had been listed in the FieldGuide yet, so the Lens tracked no pool and the Helix had held at every evaluation: all six strands were still at their starting level, 4.
  • No NECTAR round had run yet, and the first season closes on 19 November 2026.

Contracts

Contracts on Ethereum mainnet
ContractAddressVerified source

NookERC-20 token, holder rewards

0x8B046926A7F875309117F749411e83c7E37Ff73d

NucleusUniswap v4 hook

0x443AdD53B98360742Fa8ba184757B7C87AA82AcC

HelixThe brain and the clock

0xC473e283C3a67F5555160F659FC45f3c7365440F

LensReads other pools

0x26c73e8e7AdA0960146F9e197580c2669c93E41c

FieldGuideListings, abilities, copies

0x2140321022C095caecf7f81C5dA1e723f7Ac4444

GutBuyback and burn, liquidity

0x107c837195102212D12b85978d90241c63F055EA

SpecimensCollectible NFTs

0xC9C2b82139BDc1240395b2326Dc8EFBe25a78710

AmberLiquidity custody

0x852C050E9730c775F2809952C9F38ce625c06c72

SproutLaunch initializer

0x444E9923E0754765C172a6925644496EE89f1262

Fee vaultPlatform fee, Programmable code

0xA8EacC8f7A982502d68018BC9764850d0BceAFd5

Launch protectionLaunch rules, Programmable code

0xad5A3bB32da2A7f6b39F3f7fFD004D9Ec2c2D3C0

Opening-tax vaultOpening surcharge, Programmable code

0xca512156A4e1d36ba4a1E81BA3B532dc6762d9cB

All nine of mine are verified on Etherscan with an exact match, eight of them on Sourcify as well. Compiler: solc 0.8.26, via IR, 1,000 optimizer runs, EVM target Cancun.

Source repository: github.com/Nookleus/nookleus-contracts (opens in a new tab)