For the complete documentation index, see llms.txt. This page is also available as Markdown.

Permissionless base permissioned app layer

Who this is for: protocol-minded engineers and issuers deciding where to put a permission check in their own contract. For the four named checks that get built on top of this pattern, see Compliance model overview.

The core split

Lumia's chain layer (sequencing, the zkEVM, state transitions, the data-availability layer) does not gate who can transact. Any address can send a transaction, deploy a contract, or hold a token, the same as on Ethereum or any general-purpose EVM chain. There is no protocol-level allowlist of wallets.

Compliance instead lives at the application layer, enforced by the contracts an issuer deploys. This is a deliberate architectural choice: it means Lumia can host fully permissionless, DeFi-style contracts and tightly gated RWA contracts side by side on the same base layer, each choosing its own rules, rather than the whole chain adopting one compliance regime for every application.

Why the base layer doesn't enforce this itself

A chain that enforced identity checks at the protocol level would need to verify identity before including a transaction in a block: effectively an allowlisted sequencer. That trades away permissionless access and composability for every application on the chain, including ones that don't need compliance at all. Lumia's application-layer approach avoids that trade-off by leaving the choice to each contract instead.

How an app opts in

The general pattern is a permission check inside the contract itself (typically a transfer() override or a modifier gating a sensitive function) that calls out to an identity or eligibility registry before allowing the action:

// Illustrative pattern, not a copy-paste production contract.
// See ../../build/identity/on-chain-kyc-integration.md for the actual verifier integration steps.
modifier onlyVerified(address account) {
    require(kycRegistry.isVerified(account), "not verified");
    _;
}

function transfer(address to, uint256 amount)
    public
    onlyVerified(msg.sender)
    onlyVerified(to)
    returns (bool)
{
    // standard ERC-20 transfer logic
}

This is the same general pattern most permissioned-security-token standards use (compare to ERC-1400's transfer restrictions or ERC-3643's identity registry): the token contract checks an identity/eligibility registry at the moment of transfer, rather than the chain checking identity before the transaction is even included.

What's enforced where

Layer
Enforces
Example

Protocol (base chain)

Nothing identity-related; open access

Anyone can submit a valid transaction

Application (contract)

Whatever the issuer builds

transfer() requires a verified-credential check

Off-chain (issuer's own process)

The actual KYC/KYB/KYT decision-making

A compliance team or vendor approves an applicant, reflected on-chain

This page describes an architecture, not a legal status. It does not state that any application built this way is thereby compliant with a specific regulator or jurisdiction. That determination belongs to the issuer and their counsel.

Last updated

Was this helpful?