Skip to content
0xSlots

Utility modules

A slot on its own is a position and nothing more. Holding it grants you no rights, because there is nothing attached to grant.

A module is what makes holding worth something: the ad that renders, the name that resolves, the feed you can post to, the door that opens.

The slot is the plot. The module is the crop.

Set one at creation, or leave it empty.

Available modules

ModuleHolding the slot meansFee
Metadatayour content appears here — ads, listings, profilesnone
Feed postyou may publish into a feednone

Metadata is the workhorse. The occupant sets a URI and structured data; it clears when they leave.

Hooks

The slot tells its module what happened. The module does what it likes with that.

HookFires when
onTransferoccupancy moves
onPriceUpdateoccupant self-assesses
onReleaseoccupant leaves or is liquidated
onSettletax is charged
Loading diagram...

Three report occupancy — who holds the slot. onSettle reports money.

Fees

A module can take a cut of the tax via feeBps and feeRecipient, skimmed at collection. The rest goes to the recipient.

That is how a module author gets paid for building something on a slot they do not own. It is declared by the module and visible before anyone commits.

Writing one

Any contract implementing IUtility — the interface formerly called ISlotsModule, kept as an alias so existing utilities keep compiling. No registry, no permission: pass its address at slot creation.

You also need IModuleMetadataname, version, metadataURI — which IUtility inherits. Verification checks both ERC-165 ids separately, so a utility that implements the hooks but cannot describe itself will not verify.

The factory can mark a module verified, which is a curation signal in the explorer, not a security boundary. Unverified modules work identically.

Practical notes:

  • Keep hooks cheap. They run inside user transactions under a gas cap.
  • Key state by msg.sender — one module usually serves many slots.
  • Never assume a hook arrived. See below.

Design notes

Modules are fail-open

If a module reverts, runs out of gas, or is simply broken, the slot carries on regardless. The call is gas-capped and the failure is swallowed.

This is the exact opposite of an occupancy policy, and the asymmetry is the point:

Occupancy policyUtility module
Answersmay this happen?this happened
On failureblocks the actionignored
Can move fundsnevertakes a fee from tax

A rule about who may take your property must be reliable, so a broken policy stops everything. A feature attached to a slot must never freeze the money underneath it, so a broken module is skipped.

onSettle carries both what was owed and what was actually paid, and they differ. A charge is capped by the remaining deposit, so an occupant running dry pays less than they owe.

Anything doing revenue share or contribution accounting must use paid. Reconstructing it from price × time computes owed and over-credits — and someone can trigger that deliberately by declaring a huge price against a tiny deposit.

onSettle fires mid-transaction

Unlike the other hooks, it runs from inside the settlement that begins every mutating call. The slot is in its pre-operation state — during a buy, occupant() still returns the outgoing occupant. Reentry into the same slot is blocked, but treat anything you read as in flux.

Next