Plate 05 · Technical reference
Technical reference.
The contracts as they are written: what gets deployed, what the pool key is, how a cut is collected without ever being able to block a trade, and who can do what.
§ 05.1The deployed set
| Contract | Role |
|---|---|
| MorphToken | the ERC-20. Fixed supply, permit signatures, checkpointed voting on a timestamp clock. One burn entry point, callable only by the hook, and only against tokens the hook itself holds. |
| MorphHook | the Uniswap v4 hook. Holds the module registry, the active index, the epoch state and the tally. Performs every pool action. |
| BurnOnSellModule | registry index 0. Pure read. |
| DynamicFeeModule | registry index 1. Pure read. |
| BuybackSkimModule | registry index 2. Pure read. |
The hook's address is mined so that its low bits match the permissions it declares — a requirement of Uniswap v4, and the reason it is deployed through the project's own CREATE2 factory rather than a shared one.
§ 05.2Pool key
- currency0
- native ETH
- currency1
- MORPH
- fee
- dynamic — set by the hook, per swap
- tickSpacing
- 200
- hooks
- MorphHook
The hook accepts exactly one pool: initialisation reverts unless the key is that key, and unless the caller is the single address bound at construction. It is a one-time gate — once the canonical pool exists, no second initialisation is possible.
§ 05.3Hook permissions
| Callback | Enabled | Why |
|---|---|---|
| beforeInitialize | yes | bind the pool to one key and one initialiser |
| beforeSwap | yes | read the active module; apply a fee override; take the cut on an exact-input trade |
| afterSwap | yes | take the cut on an exact-output trade, whose input is only known here |
| beforeSwapReturnDelta | yes | the mechanism the cut is charged through |
| afterSwapReturnDelta | yes | the same, for the exact-output path |
| liquidity callbacks | no | the hook has no say over who adds or removes liquidity |
| donate callbacks | no | unused |
§ 05.4How a cut is collected
When a module's decision includes a share of the input leg, the hook does not pull real tokens out of the pool during the swap. It credits itself a claim against the pool manager instead, which is a ledger entry rather than a transfer.
This matters for a specific failure mode. A real transfer during a swap draws on the pool's physical balance before the trader's input has settled, so a large enough trade would ask for more than the pool is holding at that instant and the whole swap would revert. A claim cannot fail that way, so no trade size can be blocked by the collection mechanism.
The claim is turned into real tokens later, off the trading path, by redeemBurnAndBurn() or redeemSkimmedEth(). Both are callable by anyone, and neither can do anything other than what its name says.
§ 05.5Callable surface
| Call | Who | Effect |
|---|---|---|
| delegate(address) | any holder | starts checkpointing your balance as voting weight |
| vote(uint256) | any holder with past weight | one ballot for one registry index, this epoch |
| finalizeEpoch() | anyone | after the window closes: elects the leader, opens the next window, takes the next snapshot |
| redeemBurnAndBurn() | anyone | converts the accrued MORPH claim to tokens and burns them |
| redeemSkimmedEth() | anyone | converts the accrued ETH claim to ETH held by the hook |
| sweepTreasury(address,uint256) | the keeper only | withdraws ETH from the hook |
| moduleCount() · moduleAt(i) · moduleNameAt(i) | anyone | reads the registry |
| activeIndex · epoch · snapshotTs · epochEnd | anyone | reads the current state |
| votes(epoch,i) · hasVoted(epoch,addr) | anyone | reads the tally |
| timeUntilEpochEnd() | anyone | seconds left in the window, or zero |
There is no addModule, no setModule, no upgrade entry point and no owner on the token. The one-shot call that binds the hook to the token clears its own authority when it succeeds.
§ 05.6Trust assumptions
| Party | Can | Cannot |
|---|---|---|
| The deploying wallet | receives the entire initial supply; provides and controls the launch liquidity position; binds the hook once at deployment | mint, add a module, change the active module outside a vote, or take a holder's tokens |
| The keeper | withdraw ETH the hook has collected under MOD-02 | mint, add a module, move liquidity, or influence the vote |
| Holders, collectively | elect the active module each epoch | anything outside the three catalogued indices |
| Anyone at all | roll a closed epoch; redeem an accrued claim | change the outcome of either — both are determined before the call |
Read the first row carefully: at launch, one wallet holds the supply that has not been placed in the pool, and holds the liquidity position. That is the ordinary shape of a fresh launch and it is a real dependency, not a rounding error.
§ 05.7Review status
These contracts have not been audited by a third party. They carry an internal test suite, including tests that exercise the hook against a fork of Ethereum mainnet with the real Uniswap v4 pool manager, and an internal adversarial review whose findings were fixed and re-tested. That is the author's own work and should be weighed as such.
Nothing on these six plates should be read as a security guarantee, and nothing here is investment advice.