StoreFactory

Git Source

Inherits: Initializable, UUPSUpgradeable, OwnableUpgradeable, 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 the owner or a store writer 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.

Lives behind its own UUPS proxy. The per-user bindings and both beacon addresses are proxy storage, so the factory is upgraded in place: the bindings cannot be exported, so a replacement reached by re-pointing STORE_FACTORY would start with an empty directory.

Note: security-contact: admin@parity.io

State Variables

labelStoreBeacon

Beacon backing every LabelStore proxy.

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

address public override labelStoreBeacon

userStoreBeacon

Beacon backing every UserStore proxy.

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

address public override userStoreBeacon

protocolRegistry

Protocol registry used to authorise deployLabelStoreFor callers.

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

address public override protocolRegistry

_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

__gap

Reserved storage space to allow for layout changes in future upgrades.

uint256[50] private __gap

Functions

onlyOwnerOrProtocol

Restricts deployLabelStoreFor to the owner or a component named in

Note: function: StoreAuth.isStoreWriter.

modifier onlyOwnerOrProtocol() ;

constructor

Note: oz-upgrades-unsafe-allow: constructor

constructor() ;

initialize

Initialises the factory together with both store implementations and beacons.

Callable exactly once via Initializable, otherwise

Note: reverts: InvalidInitialization. A single initialiser call wires everything:

  • Deploys a fresh LabelStore implementation.
  • Deploys a fresh UserStore implementation.
  • Constructs both UpgradeableBeacon instances, owned by address(this), which under the proxy is the proxy itself, so upgrade*Implementation can delegate to beacon.upgradeTo and the beacons outlive any implementation swap. The implementations are deployed here rather than accepted as parameters, so the call carries no ordering dependency on a prior deploy and exposes no argument through which a mismatched implementation could reach a beacon. protocolRegistry_ must be non-zero, otherwise @custom:reverts InvalidProtocolRegistry.
function initialize(address initialOwner, address protocolRegistry_) external initializer;

Parameters

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

deployLabelStoreFor

Deploys a LabelStore beacon-proxy bound to user.

Callable by the factory owner or a component named in

Notes:

  • function: StoreAuth.isStoreWriter; any other caller

  • 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

  • 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.

_authorizeUpgrade

Function that should revert when msg.sender is not authorized to upgrade the contract. Called by {upgradeToAndCall}. Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.

function _authorizeUpgrade(address) internal onlyOwner {}
function _authorizeUpgrade(address newImplementation) internal override onlyOwner;

_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.