MachineBridgeAdapter and CrossChainMirror over LayerZero V2; that mechanism is switched off on chain today and the SDKs expose status reads only. And the 1.0 Machine NFT bridge (peaq ↔ Base; the Solana lane is closed) is on the Machine NFT page.
This means a or app on a satellite chain can resolve a Tokenomics 1.0 machine’s , identity and status (satellites carry no mirror, see Qualify) without an hop to peaq. The satellites today are agung (mirroring peaq mainnet) and Sepolia (mirroring agung); there is no Lite deployment on Base mainnet, Ethereum or Polygon. A read trusts the Signer Daemon’s push key to have pushed peaq state faithfully.
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 ’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 hop. Records are written exclusively by signed batches from the Signer Daemon; consumers only read.
Public consumer views
readAttribute LiteIsPaused() 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)LiteIsPaused()
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 the publiclastBatchAcceptedAt()andrequire(lastAt > 0, LiteUninitialized(address(this))).LiteIsPaused()
Cold-start pattern
A Lite that has never accepted a batch holds no records, sogetIdentity reverts MachineNotFound on a fresh Lite just as it does for an unknown machine. Read the public lastBatchAcceptedAt() first when you need to tell the two apart:
StakingLite
StakingLite mirrors the peaqIdentityStaking per-machine stake record. Consumers gate authorisation or service eligibility on stake state without crossing chains.
Public consumer views
getStake and getStakeRaw revert MachineNotFound for an absent stake record, including on a fresh Lite, and isStaked and totalStaked return no timestamp. Read lastBatchAcceptedAt() and require(lastAt > 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 make the on-chain cursor 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(home, satellite, Lite) triple. The fleet is six daemons across two pipelines: three for peaq (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.
Health endpoint
Each daemon exposes a loopback-only/health (default port unique per instance, conventionally 8080–8085):
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 one boolean plus a snapshot , not an enum, next to the two pause booleans: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 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, and the SDKs do not wrap it. ComparelastBatchAcceptedAt to block.timestamp and reject reads older than your 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
The Lites carry Tokenomics 1.0 records only:machineId is the IdentityRegistry ID and didAccount is the address behind a did:peaq:<0x-address> DID. An Economics 2.0 machine ID has no record on them.
- Resolve a peaqID on a satellite chain. Call
readAttribute(didAccount, "peaqID")and decode the returnedbytesas abytes32. A fresh Lite revertsAttributeNotFound; readlastBatchAcceptedAt()first if you need to tell a cold Lite from a missing attribute. - 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.
Solana
Solana is the first non-EVM chain peaqOS reaches, and the first chain besides peaq where an Economics 2.0 machine can live. The eleven Economics 2.0 programs are deployed on Solana mainnet-beta (addresses on Smart contracts). The Tokenomics 1.0 mirror programs (identityAWGibJPvQnj8mhfK8QWdUhvJBySCcwYadqAdtj2N137m, stake 4PyqZKtej7CWcV1jZ5h5FMd8EoR5edTTaZxAxEQmVDvs, DID attributes AMQgyqNcWSJy6cK2wSmXRykgjoPhSroKkjKtN8Y11WMc) and the address-binding program GrsCoPkeLUAoXjuwPfCcuch77Chco1Gx95zCCQNYGqG6 are closed on mainnet-beta: their program data no longer exists, so they cannot be called and receive no pushes. What is reachable today:
The Economics 2.0 messages between peaq and Solana (reservation mirror, link push) travel over LayerZero.
There is no
peaqos solana command group: Solana is selected per command (peaqos activate --chain solana, peaqos stream pay --chain solana).

