An ERC-721 NFT contract that enables builders to register unique codes (e.g., "myapp") with an associated payout addresses for revenue attribution and distribution. Implements the ERC-8021 ICodesRegistry interface.
- Unique Code Registration: Mint ERC-721 tokens representing alphanumeric codes (1-32 characters)
- Flexible Registration Methods: Direct registration via authorized registrars or gasless signature-based registration
- Revenue Attribution: Each code has a configurable payout address for tracking and distributing revenue
- Role-Based Access Control: Granular permissions for registration, transfers, and metadata updates
- Upgradeable Design: UUPS proxy pattern enables future enhancements while preserving state
- Gas-Optimized: Efficient storage layout using ERC-7201 and Solady libraries
BuilderCodes implements the ERC-721 standard where each token represents a unique builder code. The token ID is deterministically derived from the code string itself, ensuring a 1:1 mapping between codes and token IDs. The contract uses OpenZeppelin's upgradeable ERC-721 implementation as the base.
The contract employs a central registry with periphery registrars architecture:
- Central Registry: The BuilderCodes contract serves as the authoritative registry, storing all code ownership and payout mappings
- Periphery Registrars: External contracts or EOAs granted
REGISTER_ROLEcan register codes on behalf of users - Restricted Transfers: Only addresses with
TRANSFER_ROLEcan initiate transfers, preventing unauthorized code transfers
Roles:
REGISTER_ROLE: Authorize code registration (direct calls or signatures)TRANSFER_ROLE: Authorize token transfersMETADATA_ROLE: Update token metadata URIs- Owner: Automatically has all roles via
hasRole()override and can manage role grants
The contract uses the UUPS (Universal Upgradeable Proxy Standard) pattern:
- Proxy Pattern: ERC-1967 transparent proxy separates logic (implementation) from state (proxy)
- Storage Safety: ERC-7201 namespaced storage prevents collisions during upgrades
- Owner-Only Upgrades: Only the contract owner can authorize implementation upgrades via
_authorizeUpgrade()
Builder codes must adhere to strict formatting rules:
- Length: 1-32 characters
- Allowed Characters: Lowercase letters (
a-z), digits (0-9), and underscore (_)
The contract provides toCode() and toTokenId() as pure functions that bidirectionally map between builder codes and token IDs. This deterministic 1:1 mapping is enabled by 7-bit ASCII encoding of the allowed character set.
The register() function allows authorized registrars to mint codes:
function register(
string memory code,
address initialOwner,
address initialPayoutAddress
) external onlyRole(REGISTER_ROLE)Flow:
- Caller must have
REGISTER_ROLE(or be owner) - Code is validated for format compliance
- Token is minted to
initialOwner - Payout address is set to
initialPayoutAddress - Events emitted:
Transfer,CodeRegistered,PayoutAddressUpdated
The registerWithSignature() function enables gasless registration via EIP-712 signatures:
function registerWithSignature(
string memory code,
address initialOwner,
address initialPayoutAddress,
uint48 deadline,
address signer,
bytes memory signature
) externalFlow:
- Verify deadline has not passed
- Verify
signerhasREGISTER_ROLE - Compute EIP-712 typed data hash for registration parameters
- Validate signature against signer's address
- Execute registration (same as direct registration)
EIP-712 Typed Data:
BuilderCodeRegistration(
string code,
address initialOwner,
address payoutAddress,
uint48 deadline
)
This pattern allows users to obtain off-chain signatures from authorized registrars and submit registrations without the registrar paying gas.
BuilderCodes implements a permission-gated transfer system to control how codes can be transferred between addresses.
How it works:
- Transfers are only allowed if initiated by an address with
TRANSFER_ROLE - Holders of
TRANSFER_ROLEcannot move tokens unilaterally—they still need approval from each owner to transfer tokens
This design enables intentional rollout of specific transfer patterns, such as controlled marketplaces or recovery mechanisms.