SlotFactory
Deploys slots as BeaconProxies sharing one implementation. Addresses are
assigned at deploy time, not derived from config — createSlots can deploy many
slots with identical parameters, so a slot is identified by its address.
function createSlot(
address recipient,
IERC20 currency,
SlotConfig memory config,
SlotInitParams memory initParams
) external returns (address slot);
function createSlots(
address recipient,
IERC20 currency,
SlotConfig memory config,
SlotInitParams memory initParams,
uint256 count
) external returns (address[] memory slots);SlotConfig
What, if anything, a manager may change later.
struct SlotConfig {
bool mutableTax; // the tax rate
bool mutableUtility; // the UTILITY — what the slot does
bool mutablePolicy; // the OCCUPANCY policy — who may take it, and when
address manager; // address(0) if every flag is false
}Three independent flags because they are three different promises. A slot can offer a swappable module on occupancy terms that never change — and a slot advertising "the module may change" cannot quietly also reserve the right to change who is allowed to take it.
SlotInitParams
struct SlotInitParams {
uint256 taxPercentage; // basis points per 30 days (100 = 1%)
address utility; // utility contract, address(0) for none
uint256 liquidationBountyBps; // share of collected tax paid to liquidators
uint256 minDepositSeconds; // deposit must cover this much tax
address occupancyPolicy; // IOccupancyPolicy, address(0) for instant buy
}minDepositSeconds is the guard against a buyer declaring a huge price with no
means to pay for it: the deposit must cover that many seconds of tax at the
declared price. It rounds up — "no deposit required" means
minDepositSeconds == 0 and nothing else, in every currency. Integrators
computing a deposit client-side must round up the same way; a truncating copy
lands one unit under and reverts.
Curation
function setUtilityVerified(address utility, bool verified) external; // admin
function isUtilityVerified(address utility) external view returns (bool);
function setPolicyVerified(address policy, bool verified) external; // admin
mapping(address => bool) public verifiedPolicies;A display signal only. Unverified utilities and policies work identically — they simply carry no endorsement, and the explorer says so.
Both setters assert two ERC-165 ids: the behavioural interface (IUtility /
IOccupancyPolicy) and IModuleMetadata. Checking one alone would verify a
contract that cannot describe itself, and the events emitted read its name,
version and metadataURI immediately. See
ERC-165 ids.
event ModuleVerified(
address indexed utility, bool verified,
string name, string version, uint256 feeBps, string metadataURI
);
event PolicyVerified(
address indexed policy, bool verified,
string name, string version, string metadataURI
);setModuleVerified, isModuleVerified and verifiedModules remain as
deprecated aliases — the selectors deployed callers and old ABIs still hold.
Operations
function collectAll(address[] calldata slots) external; // batch tax collection
function upgradeBeacon(address newImplementation) external; // adminupgradeBeacon moves every slot at once — they all share one implementation.
Storage is strictly append-only for that reason.