StoreFactory

Git Source

Inherits: Ownable, IStoreFactory

Title: StoreFactory

Factory for the two per-user DotNS store types, sharing one factory contract and two beacons. @dev Each user may acquire AT MOST two stores, ever:

  • a LabelStore, deployed via deployLabelStoreFor by a protocol-registered caller during registration; and
  • a UserStore, claimed via claimUserStore by the user themselves. Both are BeaconProxy instances pointing at their respective UpgradeableBeacon. The factory owns both beacons so the factory owner can upgrade implementations for every proxy atomically. Neither per-user mapping is ever transferred, reassigned, or overwritten after the first write; bindings are permanent.

Note: security-contact: admin@parity.io

Constants

labelStoreBeacon

Beacon backing every LabelStore proxy.

Public getter name is interface-constrained by @custom:contract IStoreFactory.

address public immutable override labelStoreBeacon

userStoreBeacon

Beacon backing every UserStore proxy.

Public getter name is interface-constrained by @custom:contract IStoreFactory.

address public immutable override userStoreBeacon

protocolRegistry

Protocol registry used to authorise deployLabelStoreFor callers.

Public getter name is interface-constrained by @custom:contract IStoreFactory.

address public immutable override protocolRegistry

State Variables

_labelStores

user => their permanent LabelStore. Set once per user, forever.

mapping(address user => address store) private _labelStores

_userStores

user => their permanent UserStore. Set once per user, forever.

mapping(address user => address store) private _userStores

_labelStoreList

Insertion-order list of every LabelStore proxy ever deployed. Append-only.

address[] private _labelStoreList

_userStoreList

Insertion-order list of every UserStore proxy ever claimed. Append-only.

address[] private _userStoreList

Functions

onlyOwnerOrProtocol

Restricts deployLabelStoreFor to the owner or any protocol-registered caller.

modifier onlyOwnerOrProtocol() ;

constructor

Deploys the factory together with both store implementations and beacons.

A single new StoreFactory(protocolRegistry, owner) call wires everything:

  • Deploys a fresh LabelStore implementation.
  • Deploys a fresh UserStore implementation.
  • Constructs both UpgradeableBeacon instances, owned by address(this) so upgrade*Implementation can delegate to beacon.upgradeTo. Keeping the implementation deployments inside the constructor removes a class of operator error: there is no "did I deploy the implementation first?" step and no way to pass the wrong implementation address. protocolRegistry_ must be non-zero, otherwise @custom:reverts InvalidProtocolRegistry.

Implementations and beacons are deployed inline so a single factory address fully describes the store topology, removing a class of operator error around mismatched beacons.

constructor(address protocolRegistry_, address owner_) Ownable(owner_);

Parameters

NameTypeDescription
protocolRegistry_addressThe protocol registry for writer auth on label stores.
owner_addressAccount that owns this factory and can upgrade store implementations.

deployLabelStoreFor

Deploys a LabelStore beacon-proxy bound to user.

Callable by the factory owner or any address currently registered in the protocol registry; any other caller @custom:reverts NotAuthorised. user must be non-zero, otherwise @custom:reverts InvalidUser. The user must not already have a LabelStore, otherwise @custom:reverts AlreadyDeployed. After deployment the freshly initialised proxy must report user as its owner, otherwise

Notes:

  • reverts: ImplementationBindingMismatch. Emits

  • emits: LabelStoreDeployed on success.

function deployLabelStoreFor(address user)
    external
    override
    onlyOwnerOrProtocol
    returns (address store);

Parameters

NameTypeDescription
useraddressThe user the store is bound to forever.

Returns

NameTypeDescription
storeaddressThe deployed store address.

getLabelStore

Returns the LabelStore address bound to user, or the zero address if none.

function getLabelStore(address user) external view override returns (address store);

Parameters

NameTypeDescription
useraddressThe user to look up.

Returns

NameTypeDescription
storeaddressThe bound store address, or zero.

getLabelStoreCount

Returns the total number of LabelStore proxies ever deployed.

function getLabelStoreCount() external view override returns (uint256 count);

Returns

NameTypeDescription
countuint256Length of the deployment list.

getLabelStores

Paginated enumeration over every LabelStore proxy ever deployed.

Insertion order of deployLabelStoreFor calls. offset >= getLabelStoreCount() returns an empty array; result length is min(limit, count - offset).

function getLabelStores(
    uint256 offset,
    uint256 limit
)
    external
    view
    override
    returns (address[] memory stores);

Parameters

NameTypeDescription
offsetuint256Start index.
limituint256Maximum entries to return.

Returns

NameTypeDescription
storesaddress[]Slice of label-store addresses.

upgradeLabelStoreImplementation

Upgrades the LabelStore implementation for every existing and future proxy.

Callable by the factory owner only, otherwise

Notes:

  • reverts: OwnableUnauthorizedAccount. newImplementation must be non-zero, otherwise @custom:reverts InvalidImplementation. The candidate is sentinel-probed by calling ILabelStore.protocolRegistry on it before the beacon is rotated; if the address does not implement that selector the probe reverts and the upgrade does not land (deliberate fail-fast guard, no named error). Delegates to UpgradeableBeacon.upgradeTo and emits

  • emits: LabelStoreImplementationUpgraded on success.

function upgradeLabelStoreImplementation(address newImplementation)
    external
    override
    onlyOwner;

Parameters

NameTypeDescription
newImplementationaddressThe new implementation address.

claimUserStore

Caller claims their UserStore beacon-proxy.

Self-claim only; _owner on the resulting store is always msg.sender, regardless of who pays gas. One store per caller, forever: a caller who already has a UserStore @custom:reverts AlreadyDeployed. After deployment the freshly initialised proxy must report msg.sender as its owner, otherwise

Notes:

  • reverts: ImplementationBindingMismatch. Emits

  • emits: UserStoreClaimed on success.

function claimUserStore() external override returns (address store);

Returns

NameTypeDescription
storeaddressThe deployed store address.

getUserStore

Returns the UserStore address bound to user, or the zero address if none.

function getUserStore(address user) external view override returns (address store);

Parameters

NameTypeDescription
useraddressThe user to look up.

Returns

NameTypeDescription
storeaddressThe bound store address, or zero.

getUserStoreCount

Returns the total number of UserStore proxies ever claimed.

function getUserStoreCount() external view override returns (uint256 count);

Returns

NameTypeDescription
countuint256Length of the claim list.

getUserStores

Paginated enumeration over every UserStore proxy ever claimed.

Insertion order of claimUserStore calls. offset >= getUserStoreCount() returns an empty array; result length is min(limit, count - offset).

function getUserStores(
    uint256 offset,
    uint256 limit
)
    external
    view
    override
    returns (address[] memory stores);

Parameters

NameTypeDescription
offsetuint256Start index.
limituint256Maximum entries to return.

Returns

NameTypeDescription
storesaddress[]Slice of user-store addresses.

upgradeUserStoreImplementation

Upgrades the UserStore implementation for every existing and future proxy.

Callable by the factory owner only, otherwise

Notes:

  • reverts: OwnableUnauthorizedAccount. newImplementation must be non-zero, otherwise @custom:reverts InvalidImplementation. The candidate is sentinel-probed by calling IUserStore.getKeyCount on it before the beacon is rotated; if the address does not implement that selector the probe reverts and the upgrade does not land (deliberate fail-fast guard, no named error). Delegates to UpgradeableBeacon.upgradeTo and emits

  • emits: UserStoreImplementationUpgraded on success.

function upgradeUserStoreImplementation(address newImplementation) external override onlyOwner;

Parameters

NameTypeDescription
newImplementationaddressThe new implementation address.

version

Returns implementation version.

function version() external pure virtual returns (string memory versionString);

Returns

NameTypeDescription
versionStringstringCurrent version string.

_onlyOwnerOrProtocol

Internal authorisation check deferred from the onlyOwnerOrProtocol modifier.

function _onlyOwnerOrProtocol() internal view;

_paginateAddresses

Shared pagination helper used by getLabelStores and getUserStores.

Single canonical slicer so both enumerations bound-check and copy identically.

function _paginateAddresses(
    address[] storage source,
    uint256 offset,
    uint256 limit
)
    internal
    view
    returns (address[] memory slice);

Parameters

NameTypeDescription
sourceaddress[]Storage array to slice.
offsetuint256Start index.
limituint256Maximum entries to return.

Returns

NameTypeDescription
sliceaddress[]Result slice; empty when offset >= source.length.