> ## Documentation Index
> Fetch the complete documentation index at: https://docs.layerzero.network/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> System design, inheritance hierarchy, and cross-chain message flow.

## Design Philosophy

Security modules (fee, rate limiting, pause-by-destination) are independent, upgradeable layers that compose through inheritance without modifying core OFT logic. Allowlist controls live on the token (`ERC20Plus`), not in the extension stack.

Token logic (`ERC20Plus`) is fully decoupled from cross-chain OFT logic (OFT variants). The token can exist without an OFT, and the OFT works with any ERC20 that implements `IERC20Metadata` and the necessary mint/burn functions with appropriate role-based access control.

All storage uses EIP-7201 namespaced storage slots, preventing storage collisions across inheritance chains and making proxy upgrades safe by construction.

## Four-Layer Architecture

```
+----------------------------------------------------------+  IOFTExtended
|  Cross-Chain Extensions                                  |
|  Fee | RateLimiter | PauseByID                           |
|  (composable, per-destination configuration)             |
+----------------------------------------------------------+  IOFT
|  Cross-Chain Transport                                   |
|  BurnMint | LockUnlock | Native | BurnSelfMint           |
|  (send/receive via LayerZero V2)                         |
+==========================================================+  IERC20Plus
|  Token Controls                                          |
|  Allowlist | Pause | Fund Recovery                       |
|  (apply to all token operations, not just cross-chain)   |
+----------------------------------------------------------+  IERC20
|  Token Core                                              |
|  ERC20 + ERC20Permit (transfer, approve, permit)         |
|  (OpenZeppelin ERC20Upgradeable)                         |
+----------------------------------------------------------+
```

The system is two independent deployment units — a **Token Stack** and an **OFT Stack** — connected by the `IERC20Plus` interface.

**Token Core (Layer 1):** Standard ERC20 functionality built on OpenZeppelin's `ERC20Upgradeable` and `ERC20PermitUpgradeable`. Transfers, approvals, balances, and gasless permit signatures.

**Token Controls (Layer 2):** Allowlist (three-mode address restrictions), global pause, fund recovery, and role-based mint/burn access control. These apply to **all** token operations — a paused token blocks local transfers as well as cross-chain sends. Deployed as the `ERC20Plus` contract independently of any OFT.

**Cross-Chain Transport (Layer 3):** Manages cross-chain send/receive. Each OFT variant implements a different transfer model (burn/mint, burn-self/mint, lock/unlock, native).

**Cross-Chain Extensions (Layer 4):** Per-destination fee collection, rate limiting, and pause-by-destination controls. These modules intercept `_debit` and `_credit` to enforce policies before the underlying transfer executes.

## Inheritance Hierarchy

```mermaid theme={null}
graph TB
    OAppUpgradeable["OAppUpgradeable<br/>(LayerZero)"]
    OFTCoreBase["OFTCoreBaseUpgradeable<br/><i>Core OFT send/receive logic</i>"]
    OFTCoreRBAC["OFTCoreRBACUpgradeable<br/><i>+ RBAC for OApp config</i>"]
    OFTCoreExtended["OFTCoreExtendedRBACUpgradeable<br/><i>+ Fee + RateLimiter + PauseByID</i>"]

    BurnMintExtended["OFTBurnMintExtendedRBACUpgradeable<br/><i>+ burn/mint with custom selectors</i>"]
    LockUnlockExtended["OFTLockUnlockExtendedRBACUpgradeable<br/><i>+ lock/unlock token transfers</i>"]
    NativeExtended["OFTNativeExtendedRBACUpgradeable<br/><i>+ native token wrapping</i>"]

    OFTBurnMint["OFTBurnMint"]
    OFTBurnSelfMint["OFTBurnSelfMint"]
    OFTLockUnlock["OFTLockUnlock"]
    OFTNative["OFTNative"]

    OAppUpgradeable --> OFTCoreBase
    OFTCoreBase --> OFTCoreRBAC
    OFTCoreRBAC --> OFTCoreExtended
    OFTCoreExtended --> BurnMintExtended
    OFTCoreExtended --> LockUnlockExtended
    OFTCoreExtended --> NativeExtended
    BurnMintExtended --> OFTBurnMint
    BurnMintExtended --> OFTBurnSelfMint
    LockUnlockExtended --> OFTLockUnlock
    NativeExtended --> OFTNative

    ACEnumerable["AccessControlEnumerableUpgradeable<br/>(OpenZeppelin)"]
    AC2Step["AccessControl2StepUpgradeable"]
    FeeRBAC["FeeRBACUpgradeable"]
    RateLimiterRBAC["RateLimiterRBACUpgradeable"]
    PauseByIDRBAC["PauseByIDRBACUpgradeable"]

    ACEnumerable --> AC2Step
    AC2Step -.->|inherited via| FeeRBAC
    AC2Step -.->|inherited via| RateLimiterRBAC
    AC2Step -.->|inherited via| PauseByIDRBAC
    FeeRBAC -.->|mixin| OFTCoreExtended
    RateLimiterRBAC -.->|mixin| OFTCoreExtended
    PauseByIDRBAC -.->|mixin| OFTCoreExtended

    style OFTBurnMint fill:#34a853,color:#fff
    style OFTBurnSelfMint fill:#34a853,color:#fff
    style OFTLockUnlock fill:#34a853,color:#fff
    style OFTNative fill:#34a853,color:#fff
```

Each green box is a **deployable contract**. Everything above is abstract. The `Alt` variants (`OFTBurnMintAlt`, `OFTLockUnlockAlt`, `OFTBurnSelfMintAlt`) follow the same hierarchy but target `EndpointV2Alt` for chains where ERC20 tokens are used for gas fees.

## ERC20Plus Inheritance

```mermaid theme={null}
graph TB
    ERC20Upgradeable["ERC20Upgradeable<br/>(OpenZeppelin)"]
    ERC20PermitUpgradeable["ERC20PermitUpgradeable<br/>(OpenZeppelin)"]
    AllowlistRBAC["AllowlistRBACUpgradeable<br/><i>3-mode allowlist + RBAC</i>"]
    PauseRBAC["PauseRBACUpgradeable<br/><i>Global pause + RBAC</i>"]
    ACEnumerable["AccessControlEnumerableUpgradeable<br/>(OpenZeppelin)"]
    AC2Step["AccessControl2StepUpgradeable"]

    ERC20Plus["ERC20Plus<br/><i>+ mint/burn + fund recovery</i>"]

    ERC20Upgradeable --> ERC20PermitUpgradeable
    ERC20PermitUpgradeable --> ERC20Plus
    AllowlistRBAC --> ERC20Plus
    PauseRBAC --> ERC20Plus
    ACEnumerable --> AC2Step
    AC2Step -.->|inherited via| AllowlistRBAC
    AC2Step -.->|inherited via| PauseRBAC

    style ERC20Plus fill:#34a853,color:#fff
```

## Cross-Chain Message Flow

### Send Path (Source Chain)

```
send()
  |
  v
OFTCoreBaseUpgradeable.send()
  |
  v
_debit() [overridden per variant]
  |-- whenNotPaused(_dstEid)              <-- PauseByID
  |-- _debitView()                        <-- Fee calculation
  |     |-- getFee(_dstEid, _amountLD)
  |     |-- _removeDust()
  |     +-- SlippageExceeded check
  |-- _outflow(_dstEid, _from, amount)    <-- Rate limit
  |     |-- Address exemption check
  |     +-- Token bucket decay
  +-- Transfer/burn + collect fee         <-- Allowlist & global pause
  |
  v
_buildMsgAndOptions()
  |
  v
_lzSend() --> LayerZero Endpoint
  |
  v
emit OFTSent(guid, dstEid, from, amountSentLD, amountReceivedLD)
```

### Receive Path (Destination Chain)

```
LayerZero Endpoint delivers message
  |
  v
_lzReceive()
  |
  v
_credit() [overridden per variant]
  |-- _inflow(_srcEid, _to, _amountLD)   <-- Rate limit (inbound)
  +-- Mint/unlock/transfer to recipient  <-- No allowlist & pause checks (credit must not fail)
  |
  v
If compose message exists:
  +-- endpoint.sendCompose() --> downstream contract
  |
  v
emit OFTReceived(guid, srcEid, to, amountReceivedLD)
```

## Transfer Model Mechanics

### Burn/Mint

```
Source Chain                          Destination Chain
+--------------------+                +--------------------+
|  ERC20Plus         |                |  ERC20Plus         |
|                    |                |                    |
|  burn()            |  LayerZero V2  |  mint()            |
|                    |  ----------->  |                    |
|                    |                |                    |
|  OFTBurnMint       |                |  OFTBurnMint       |
+--------------------+                +--------------------+
```

The OFT must hold `MINTER_ROLE` and `BURNER_ROLE` on the `ERC20Plus` token. Total supply across all chains remains constant.

### Burn-Self/Mint

```
Source Chain                          Destination Chain
+--------------------+                +--------------------+
|  ERC20Plus         |                |  ERC20Plus         |
|                    |                |                    |
|  transferFrom()    |  LayerZero V2  |  mint()            |
|  burn()            |  ----------->  |                    |
|                    |                |                    |
|  OFTBurnSelfMint   |                |  OFTBurnSelfMint   |
+--------------------+                +--------------------+
```

First transfers tokens from user to OFT via ERC20 allowance, then burns using `burn(uint256)` selector. The OFT must hold `MINTER_ROLE` on the destination token.

### Lock/Unlock

```
Source Chain                          Destination Chain
+--------------------+                +--------------------+
|  ERC20Plus         |                |  ERC20Plus         |
|                    |                |                    |
|  transferFrom()    |  LayerZero V2  |  transfer()        |
|  (lock in OFT)     |  ----------->  |                    |
|                    |                |                    |
|  OFTLockUnlock     |                |  OFTLockUnlock     |
+--------------------+                +--------------------+
```

Tokens are locked in the OFT contract on the source chain and unlocked from the OFT contract on the destination. Only one lock/unlock OFT should exist per mesh to prevent supply fragmentation.

### Native

```
Source Chain                          Destination Chain
+--------------------+                +--------------------+
|                    |                |                    |
|  msg.value         |  LayerZero V2  |  .call{value}      |
|  (ETH sent         |  ----------->  |  (ETH sent to      |
|   with tx)         |                |   recipient)       |
|                    |                |                    |
|  OFTNative         |                |  OFTNative         |
+--------------------+                +--------------------+
```

The OFT wraps/unwraps native tokens. `msg.value` must include both the transfer amount and the LayerZero messaging fee.

## Upgradeability Model

All contracts support Transparent Upgradeable Proxy (TUP) and Beacon proxy patterns:

* **Proxy contract** holds state (storage) and delegates calls to the implementation
* **Implementation contract** holds logic and is stateless
* **EIP-7201 namespaced storage** ensures each module's storage is isolated at a deterministic slot, preventing collisions

## Next Steps

* [ERC20Plus](/v2/developers/evm/stablecoin-oft/erc20plus) for the token core (layer 1)
* [OFTs](/v2/developers/evm/stablecoin-oft/ofts) for the cross-chain transport (layer 3)
* [Extensions](/v2/developers/evm/stablecoin-oft/extensions) for token controls and cross-chain extensions (layers 2 and 4)
