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

# Smart contracts

> Architecture, addresses, and responsibilities of every peaqOS contract.

peaqOS runs on four on-chain layers. The core registry and staking contracts live on peaq chain as UUPS upgradeable proxies; bridging is LayerZero V2 ONFT; smart accounts follow ERC-4337; and low-level DID, batch, and WPEAQ operations are peaq chain precompiles.

## Architecture

```
Core (peaq chain, UUPS proxies)
  IdentityRegistry ──owns──► IdentityStaking
        │                         ▲
        │ (gates on)              │ stakeFor()
        └─────► EventRegistry
        │
        └─────► MachineNFT

Cross-chain (peaq ↔ Base, LayerZero V2)
  MachineNFTAdapter (peaq)  ◄──► MachineNFTBase (Base)

ERC-4337 (peaq chain)
  MachineAccountFactory ──deploys──► MachineSmartAccount (BeaconProxy)

Precompiles (peaq chain, fixed addresses)
  DID (0x...800) · Batch (0x...805) · WPEAQ (0x...809)
```

* Core contracts use UUPS upgradeable proxies (OpenZeppelin 5.x) with ERC-7201 namespaced storage. Future upgrades preserve state.
* Identity NFT (minted by IdentityRegistry) and Machine NFT (minted by MachineNFT) are separate ERC-721 spaces with independent `tokenId` sequences linked by `machineId`. See [Machine NFT](/peaqos/concepts/machine-nft#ownership-semantics).
* IdentityRegistry implements **ERC-8004** for DID-anchored machine metadata; the JSON Machine Card is served by the MCR API.

## peaq mainnet addresses

Set these in your environment. The SDK reads them from `fromEnv()` / `from_env()`.

### Core

| Contract         | Variable                    | Address                                      |
| :--------------- | :-------------------------- | :------------------------------------------- |
| IdentityRegistry | `IDENTITY_REGISTRY_ADDRESS` | `0xb53Af985765031936311273599389b5B68aC9956` |
| IdentityStaking  | `IDENTITY_STAKING_ADDRESS`  | `0x11c05A650704136786253e8685f56879A202b1C7` |
| EventRegistry    | `EVENT_REGISTRY_ADDRESS`    | `0x43c6AF2E14dc1327dc3cc6c7117D1CD72fffEcbA` |
| MachineNFT       | `MACHINE_NFT_ADDRESS`       | `0x2943F80e9DdB11B9Dd275499C661Df78F5F691F9` |

### Precompiles

| Contract | Variable                   | Address                                      |
| :------- | :------------------------- | :------------------------------------------- |
| DID      | `DID_REGISTRY_ADDRESS`     | `0x0000000000000000000000000000000000000800` |
| Batch    | `BATCH_PRECOMPILE_ADDRESS` | `0x0000000000000000000000000000000000000805` |
| WPEAQ    | n/a                        | `0x0000000000000000000000000000000000000809` |

### Optional

| Contract              | Variable                          | Address                                      | Needed for                                                   |
| :-------------------- | :-------------------------------- | :------------------------------------------- | :----------------------------------------------------------- |
| MachineAccountFactory | `MACHINE_ACCOUNT_FACTORY_ADDRESS` | `0x4A808d5A90A2c91739E92C70aF19924e0B3D527f` | `deploySmartAccount` / `getSmartAccountAddress`              |
| MachineNFTAdapter     | `MACHINE_NFT_ADAPTER_ADDRESS`     | `0x9AD5408702EC204441A88589B99ADfC2514AFAE6` | `bridgeNft` from peaq                                        |
| AdminFlags            | `ADMIN_FLAGS_ADDRESS`             | `0x1c5f33fBEE6BA38ed9bDE247C1Ba89A2116C25f1` | MCR API server (negative-flag reads + admin trust overrides) |

## Base mainnet addresses

Needed when bridging **into** peaq from Base. Pass as `baseNftAddress` / `base_nft_address` to `bridgeNft` / `bridge_nft`.

| Contract                        | Address                                      |
| :------------------------------ | :------------------------------------------- |
| MachineNFTBase (LayerZero ONFT) | `0xee8A521eA434b11F956E2402beC5eBfa753Babfa` |

## Agung testnet addresses

Use these for development on agung. The contract surface matches mainnet; only the deployed addresses differ.

### Core

| Contract         | Variable                    | Address                                      |
| :--------------- | :-------------------------- | :------------------------------------------- |
| IdentityRegistry | `IDENTITY_REGISTRY_ADDRESS` | `0x9E9463a65c7B74623b3b6Cdc39F71be7274e5971` |
| IdentityStaking  | `IDENTITY_STAKING_ADDRESS`  | `0x55f336714aDb0749DbFE33b057a1702405564E3d` |
| EventRegistry    | `EVENT_REGISTRY_ADDRESS`    | `0x2DAD8905380993940e340C5cE6d313d5c2780040` |
| MachineNFT       | `MACHINE_NFT_ADDRESS`       | `0xB41C2A4f1c19b6B06beaAce0F5CD8439e77C4b1c` |

### Precompiles

Identical to mainnet: same fixed addresses on every peaq runtime.

| Contract | Variable                   | Address                                      |
| :------- | :------------------------- | :------------------------------------------- |
| DID      | `DID_REGISTRY_ADDRESS`     | `0x0000000000000000000000000000000000000800` |
| Batch    | `BATCH_PRECOMPILE_ADDRESS` | `0x0000000000000000000000000000000000000805` |
| WPEAQ    | n/a                        | `0x0000000000000000000000000000000000000809` |

### Optional

| Contract              | Variable                          | Address                                      | Needed for                                                   |
| :-------------------- | :-------------------------------- | :------------------------------------------- | :----------------------------------------------------------- |
| MachineAccountFactory | `MACHINE_ACCOUNT_FACTORY_ADDRESS` | `0x65a4DfEB799dFf8CF15f13816d648a7805d6b1F9` | `deploySmartAccount` / `getSmartAccountAddress`              |
| MachineNFTAdapter     | `MACHINE_NFT_ADAPTER_ADDRESS`     | `0x63fD7e64A38e50D1486Bc569B4CaCeD38528De22` | `bridgeNft` from peaq                                        |
| AdminFlags            | `ADMIN_FLAGS_ADDRESS`             | `0x4181a2Aa34aFb247450FfcBd65be5aBD4Cbee658` | MCR API server (negative-flag reads + admin trust overrides) |

<Warning>
  **Bridging cannot be exercised on agung.** `MachineNFTAdapter` is deployed, but LayerZero V2 has no DVN routes between agung and Base. `bridgeNft` / `bridge_nft` calls will not relay end-to-end. Exercise the bridge on peaq mainnet ↔ Base mainnet only.
</Warning>

## Core contracts

### IdentityRegistry

Central machine identity registry. Mints an ERC-721 Identity NFT to each machine on registration and orchestrates bonding through `IdentityStaking.stakeFor()`. Implements **ERC-8004** so that each Identity NFT's `tokenURI` resolves to the machine's DID-anchored Machine Card. DID attributes themselves live on the peaq DID precompile (W3C DID), written by the SDK via `writeMachineDIDAttributes` and read by the MCR API. Tracks per-machine status (`None` → `Pending` → `Verified` / `Rejected` / `Deactivated`). Supports self-registration and proxy registration.

**SDK methods:** `registerMachine`, `registerFor`
**Key state:** `minBond` (currently 1 PEAQ), `nextMachineId`, `operatorOf`, `machineStatus`

### IdentityStaking

Bond token storage. Tokens are staked at registration time via `stakeFor()` and held permanently; no withdrawal path is exposed. Only authorized callers (IdentityRegistry) can initiate stakes. Supports pause / unpause by owner.

**SDK interaction:** Indirect. `registerMachine` / `registerFor` route the bond through here automatically.

### EventRegistry

On-chain store for revenue (type `0`) and activity (type `1`) events. Gates event submission on (a) the machine being registered in IdentityRegistry, and (b) the machine being bonded in IdentityStaking. Authorization rule: `msg.sender` must be the machine wallet or the operator. Stores a `keccak256` hash of the raw data; payloads stay off-chain.

**SDK methods:** `submitEvent`, `batchSubmitEvents`
**Concept:** [Events](/peaqos/concepts/events)

### MachineNFT

LayerZero V2 ONFT representing a machine's financial profile. Minted in a separate `mintNft` call after registration: the Machine NFT `tokenId` is independent from the Identity NFT `tokenId`. `tokenURI` resolves to the MCR API's `/metadata/{token_id}` endpoint, which returns the Machine Card.

**SDK methods:** `mintNft`, `tokenIdOf`
**Concept:** [Machine NFT](/peaqos/concepts/machine-nft)

## Cross-chain contracts

### MachineNFTAdapter (peaq)

Wraps `MachineNFT` for LayerZero V2 bridging. Lock/unlock pattern: locks the NFT on peaq while the mirror exists on the destination chain. Needed only when bridging **from** peaq.

**SDK methods:** `bridgeNft` / `bridge_nft` when `source` is `"peaq"`

### MachineNFTBase (Base)

Standard `ONFT721` on Base. Burn/mint pattern: NFT is burned when bridged back to peaq. Needed when bridging **from** Base.

**SDK methods:** `bridgeNft` / `bridge_nft` when `source` is `"base"` (pass the address as `baseNftAddress` / `base_nft_address`)

## ERC-4337 smart accounts

### MachineAccountFactory

CREATE2 factory for deploying `MachineSmartAccount` BeaconProxy instances. Standard ERC-4337 flow: smart accounts run through the canonical EntryPoint at `0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789` (same address across all EVM networks).

**SDK methods:** `deploySmartAccount` / `deploy_smart_account`, `getSmartAccountAddress` / `get_smart_account_address`

### MachineSmartAccount

The shared BeaconProxy implementation behind deployed smart accounts. Handles owner/machine RBAC and broad machine execution authority. Users never interact with the implementation address directly; calls go to the deployed proxy.

## AdminFlags

Optional peaq-chain contract read by the MCR API server (not the SDK). Holds admin-set flags that modify MCR responses: per-machine `negative_flag`s and [trust-level](/peaqos/concepts/trust-levels) overrides. MCR consumers see the adjusted score in their API response.

When the contract isn't configured, `contracts.admin_flags` on [`GET /ready`](/peaqos/api-reference/health) returns `false` and the service serves unmodified MCR. See [API overview](/peaqos/api-reference/overview#server-configuration).

## Precompiles (peaq chain)

| Precompile | Address                                      | Purpose                                                                                       |
| :--------- | :------------------------------------------- | :-------------------------------------------------------------------------------------------- |
| DID        | `0x0000000000000000000000000000000000000800` | Read/write DID attributes. Used for Machine Card metadata and proxy-operator fleet attributes |
| Batch      | `0x0000000000000000000000000000000000000805` | Atomic multi-call for bonding (registration + stake) and proxy DID writes                     |
| WPEAQ      | `0x0000000000000000000000000000000000000809` | Wrapped PEAQ used internally by IdentityStaking as the staking token                          |

## LayerZero endpoints

Used by the bridge adapters. You don't set these directly; the SDK handles them.

| Network      | LayerZero V2 endpoint                        | EID     |
| :----------- | :------------------------------------------- | :------ |
| peaq mainnet | `0x6F475642a6e85809B1c36Fa62763669b1b48DD5B` | `30302` |
| Base mainnet | `0x1a44076050125825900e736c501f859c50fE728c` | `30184` |

The SDK exports the EIDs as `LAYER_ZERO_EIDS` (JS) / `LAYERZERO_EIDS` (Python) for reference.

## Upgrade pattern

All core contracts (IdentityRegistry, IdentityStaking, EventRegistry, MachineNFT) use OpenZeppelin **UUPS upgradeable proxies** with ERC-7201 namespaced storage. Implementation slots are kept distinct by namespace, so future upgrades won't collide with existing state.

MachineSmartAccount uses a **BeaconProxy** pattern: a single implementation upgrade simultaneously applies to every deployed smart account.

## See also

<CardGroup cols={3}>
  <Card title="Install" icon="download" href="/peaqos/install">
    Wire the contract addresses into `.env` for the SDK.
  </Card>

  <Card title="SDK reference" icon="code" href="/peaqos/sdk-reference/sdk-js">
    Every method that reads or writes these contracts.
  </Card>

  <Card title="API reference" icon="server" href="/peaqos/api-reference/overview">
    Off-chain reads derived from the on-chain state.
  </Card>
</CardGroup>
