Skip to content
0xSlots

SlotFactory

Deploys slots as BeaconProxies sharing one implementation. A slot's address is assigned at deploy time, not derived from its config, so a slot is identified by its address.

function createSlot(SlotInit calldata init) external returns (address slot);

One call, one struct. There is no batch variant and no separate recipient / currency / config argument list — everything a slot needs is in SlotInit.

SlotInit

struct SlotInit {
    address recipient;         // where tax goes; never zero
    IERC20  currency;          // token for tax and price; address(0) = native ETH
    address manager;           // may change what is mutable; zero on an immutable slot
    address hook;              // the single extension point; zero for none
    bytes32 hookData;          // that hook's configuration; must be 0 when hook is
    uint256 taxBps;            // basis points per 30 days (100 = 1%), 1..10000
    uint256 minDepositSeconds; // deposit a buy must fund; zero = no minimum
    bool    mutableTax;
    bool    mutableHook;
}

hookData is 32 bytes the slot stores and hands its hook on every callback — a minimum-tenure window, say. It is what lets one hook deployment serve every configuration, and it is refused unless there is a hook to interpret it. The hook validates it at creation, so a configuration it will reject fails there rather than vetoing every buy afterwards.

Two mutability flags, not three. A slot has one hook, so it has one promise about that hook — separate from the promise about its tax rate. A slot can offer a swappable hook on a tax rate that never changes, or the reverse.

minDepositSeconds guards against a buyer declaring a huge price with no means to pay: the deposit must cover that many seconds of tax at the declared price. It rounds up — a truncating client-side copy lands one unit short and reverts.

Admin

function transferAdmin(address next) external;               // hand over the role
function upgradeBeacon(address implementation) external;     // move every slot at once
function implementation() external view returns (address);

upgradeBeacon moves every slot to a new implementation in one call — they all share one beacon. Storage is strictly append-only for that reason.