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.
Omni-chain V1 ships with Scale. Lite contracts and the Signer Daemon are landing across supported chains this week. Addresses get published in the launch manifest. Treat anything here as the canonical shape that goes live.
What the mesh looks like
name = "PeaqosLite", version = "1.0.0". Each Lite is identified by (chainId, verifyingContract) per EIP-712.
DIDLite
DIDLite mirrors the peaq DID precompile’s per-attribute records onto every satellite chain. Consumers on the satellite resolve any peaq DID account’s attributes (including the locked"peaqID" attribute) without an extra cross-chain hop. Records are written exclusively by signed batches from the Signer Daemon; consumers only read.
Public consumer views
readAttribute reverts LitePaused while the Lite is paused. readAttributeRaw is an admin/debug carve-out that ignores the gate. lastHomeBlockApplied() is intentionally not pause-gated so consumers can still read the global watermark when reads are paused.
To resolve a peaqID, compose: readAttribute(didAccount, "peaqID"). The orchestrator does not ship a dedicated peaqIDOf view; clients decode the 32-byte value themselves.
Consumer view errors
AttributeNotFound(address didAccount, bytes attrName)AttributeRemoved(address didAccount, bytes attrName, uint64 removedAtHomeBlock)LitePaused()
IdentityLite
IdentityLite mirrors the peaqIdentityRegistry per-machineId record. Consumers gate writes that depend on having seen a specific peaq approval by reading lastCursorPacked().
Public consumer views
Consumer view errors
MachineNotFound(uint256 machineId)LiteUninitialized(address lite)— not raised by the Lite itself. Read(record, lastAt)andrequire(lastAt > 0, LiteUninitialized(address(this))).LitePaused()
Cold-start pattern
The Lite returns(record, 0) when it has never accepted a batch, rather than reverting, so callers choose the policy:
StakingLite
StakingLite mirrors the peaqIdentityStaking per-machine stake record. Consumers gate authorisation or service eligibility on stake state without crossing chains.
Public consumer views
require(lastBatchAcceptedAt_ > 0, LiteUninitialized(address(this))) before trusting reads. StakingLite has its own pause flag and its own EIP-712 schema (StakingEvent), but shares the PeaqosLite domain and the cross-language daemon parity gate.
EIP-712 schemas
7-field IdentityEvent
txIndex and logIndex were added vs the earlier 5-field shape so the on-chain cursor can be sub-block-precise. The daemon-side encoder is bit-identical to Solidity (parity-gated by the EIP-712 fixture suite).
DIDEvent
bytes fields are pre-hashed with keccak256(bytes(...)) per EIP-712 dynamic-bytes rule. kind ordinal: 0 = Add, 1 = Update, 2 = Remove. Removes must carry value.length == 0 and validity == 0.
Batch envelope (shared)
Signer Daemon
Off-chain. Python package, one instance per(cross-chain pair, Lite) tuple. V1 launches with a 6-daemon fleet: three for peaq mainnet (home) → Agung (satellite) and three for Agung (home) → Base Sepolia (satellite). Each daemon binds to one LITE_NAME (IdentityLite | DIDLite | StakingLite), one push key (currentSigner on the Lite), one HEALTH_PORT, and one CURSOR_FILE_PATH. Six unique push keys total — reuse triggers nonce races.
| Property | Behaviour |
|---|---|
| Finality | GRANDPA-finalized only. No latest-N fallback. Daemon freezes if GRANDPA stalls rather than serve unfinalized state. |
| Batching | Critical events flush immediately; non-critical aggregate up to flush_after_sec=30 or max_batch_size=50. MAX_BATCH_SIZE env override bounded [1, 50]; required =10 for DIDLite (byte-payload events exceed Agung block gas at 50). |
| Nonce ordering | Per-chain EVM nonce lock + per-Lite monotonic batch nonce. AlreadyApplied → skip-advance. NonceOutOfOrder → backfill missing nonce(s). |
| Restart catchup | On boot, resume_cursor = max(localCursor, liteCursor). Prevents replay after a crash between Lite acceptance and local commit. |
| Pause retries | WritesPaused from applyBatch triggers exponential backoff (1, 5, 15, 60, 300)s rather than fatal exit, so admin pauses do not crash the fleet. |
| Poison events (DIDLite) | Orphan Update/Remove events whose Add predates the deploy block trigger AttributeDoesNotExist or AttributeAlreadySoftDeleted. The daemon decodes the revert, isolates the offending event, pushes the rest of the batch, and increments poison_event_skipped_per_lite[lite] on /health. Under partial-history replay the satellite is best-effort cache, not authoritative. |
| Cross-language parity | EIP-712 typehashes are constants in Solidity (EVENT_TYPEHASH_V1, BATCH_TYPEHASH_V1) and in Python. A Hardhat task dumps canonical fixtures; Python recomputes identical hashes (17 fixtures, all 65-byte signatures bit-identical). |
| Hot-wallet floor | HOT_WALLET_MIN_BALANCE_WEI (default 0.02 native). Below the floor the daemon stops signing and /health.hot_wallet_low[chain_id] = true. |
Health endpoint
Each daemon exposes a loopback-only/health (default port unique per instance, conventionally 8080–8085):
signer-daemon-deploy, signer-daemon-monitoring, and signer-daemon-troubleshooting (coming soon).
Pause and emergency model
Every Lite has two independent pause flags and one emergency flag, allexternal onlyOwner:
setSigner rotation opens a GRACE_BLOCKS = 600 (~1h) window where the previous PUSH_KEY remains valid so in-flight signed batches do not fail mid-flight. Emergency rotation does not keep the previous key valid.
EmergencyMode
EmergencyMode is two booleans plus a snapshot address, not an enum:pauseLite or pauseApplyBatch sets inEmergencyMode = true and snapshots emergencyEnteredBySigner = currentSigner. To exit, the owner calls emergencyRotatePushKey(newKey) (rotation must actually change the signer) then exitEmergencyMode(). Pause flags are not auto-cleared.
Hot/cold key collapse defense
The cold key isowner() (admin and upgrade authority). The hot key is currentSigner (the PUSH_KEY on the daemon server). A single transaction must never collapse them onto the same address. Enforcement points:
initialize(owner_, pushKey_)reverts ifpushKey_ == owner_.setSigner(newSigner)reverts ifnewSigner ∈ {owner(), pendingOwner()}.emergencyRotatePushKey(newPushKey)reverts on the same membership check.transferOwnership/_transferOwnershiprejectnewOwner ∈ {currentSigner, previousSigner}.renounceOwnershipis permanently disabled.
Staleness policy
The Lite does not staleness-revert. SDK and ops layers apply staleness gates. Consumers should comparelastBatchAcceptedAt to block.timestamp and reject reads older than their own SLO. The Lite only blocks cold-start via the consumer-side sentinel pattern.
Soft delete (DIDLite)
Removed DID attributes stay in storage withremoved = true and value = "". readAttribute reverts AttributeRemoved(...) for these. readAttributeRaw returns them as-is for admin/debug.
What an integrator does
- Resolve a peaqID on a satellite chain. Call
readAttribute(didAccount, "peaqID")and decode the returnedbytesas abytes32. Always pair withrequire(lastBatchAcceptedAtTs > 0)to handle cold start. - Read identity status.
getIdentity(machineId)returns the full record. Same cold-start check. Or use the granular home-style getters:getOwnerIfExists,operatorOf,getMachineStatus,getMachineURI. - Read stake state.
StakingLite.getStake(machineId),isStaked(machineId),isAuthorized(wallet), ortotalStaked(). - Gate on a specific peaq approval. Read
IdentityLite.lastCursorPacked() >= myExpectedCursorbefore letting a satellite action depend on it. Use the unpausedlastCursor()view if you need the unpacked form. - Apply your own staleness SLO. Compare
lastBatchAcceptedAttoblock.timestamp. The Lite intentionally does not enforce one.
Addresses
Per-chain proxy addresses are pasted into operator.env files generated from templates in signer-daemon/deploy/ and surfaced through the SDK satellite registry. There is no single deploy-manifest JSON in the repo. Track the launch announcement for the canonical Agung and Base Sepolia address list, or pull them from peaqos/concepts/contracts once published.
Related
- Satellite mirrors — propagation and cursor-independence model (coming soon)
- Signer daemon — runtime surface (coming soon)
- Satellite SDK overview — JS/Python bindings (coming soon)
- Lite views (Solidity) — Solidity consumer surface (coming soon)
- Operate → Signer daemon deploy — production runbooks (coming soon)
- Scale function
- Activate function
- Qualify function
- Machine NFT concept
- peaqID concept
- Roadmap

