aere-research/research/specs/spec-account-abstraction.md
Aere Network 4a0b48588c Initial public release
Aere Network public source. Everything here can be checked against the live
chain (chain id 2800, https://rpc.aere.network).

Scope note, stated up front rather than buried: consensus on chain 2800 is
classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at
the signature, precompile, account and transport layers. Nothing here makes the
consensus post-quantum, and no document in it should be read as claiming so.
2026-07-20 01:02:30 +03:00

242 lines
28 KiB
Markdown

# AERE Account Abstraction and Onboarding Stack
**Chain:** AERE Network, chain ID 2800 (`0xAF0`)
**Consensus:** Hyperledger Besu QBFT, 0.5-second target blocks, sub-second finality, seven validators
**EVM ruleset:** Pectra (Prague/Cancun) plus Fusaka (Osaka), functional parity with Ethereum mainnet
**Source of truth for addresses:** `aerenew/sdk-js/src/addresses.ts`
**Contract source:** `aerenew/contracts/contracts/`
This document specifies the wallet and onboarding layer of AERE: passkey smart accounts, the ERC-4337 EntryPoint, the four gasless paymasters, EIP-7702 EOA delegation, the ERC-7579 modular account line, ERC-6551 token-bound accounts, and the post-quantum smart account. It states plainly what is live on mainnet 2800 today, what is source-complete but not yet deployed, and where the current design has seams. Honesty about the seams is deliberate: this is an engineering reference, not marketing copy.
---
## 1. Substrate: what the chain gives the wallet layer
Two hardfork features do the heavy lifting for account abstraction on AERE.
**RIP-7951 secp256r1 (P-256) precompile at `0x100`.** Fusaka activated at unix `1780220351`, block `2,106,606`. From that block onward the P-256 verification precompile is unconditionally present at address `0x100`. It takes a 160 byte input (`msgHash || r || s || x || y`, five 32 byte words) and returns a 32 byte word whose low bit is set on a valid signature. Per the registry notes the fixed cost is roughly 3,450 gas, versus roughly 250,000 gas for a pure-Solidity P-256 verification. This is what makes native passkey (WebAuthn) signatures affordable to check on chain, so a user's Face ID, Touch ID, Windows Hello, Android biometric, YubiKey, or EU Digital Identity Wallet key can directly authorize account operations with no seed phrase.
**EIP-7702 EOA delegation (Pectra).** An existing externally owned account can sign a 7702 authorization tuple that makes its account temporarily execute a designated contract's deployed bytecode, while remaining controlled by the original secp256k1 key. AERE uses this to upgrade a plain MetaMask style EOA into a batching, session-key, passkey-capable account without moving funds to a new address.
One substrate constraint shapes the account designs below. AERE's own EntryPoint keeps a strictly sequential, single-dimension per-sender nonce in its own storage (no 2D nonce keys of the kind canonical ERC-4337 v0.7 uses for validator routing). Accounts that want to route between multiple validators therefore cannot encode the route in a nonce key, and instead route on a signature prefix byte. This is called out explicitly in the modular account (Section 6).
---
## 2. Passkey smart accounts (live)
The passkey account is a smart contract wallet whose owner set can be WebAuthn P-256 keys, plain EOA keys, or a mix. It is the production onboarding path for "no seed phrase" users.
### 2.1 Components and addresses
| Component | Address (chain 2800) | Status |
|---|---|---|
| `AereEntryPointV2` | `0x8D6f40598d552fF0Cb358b6012cF4227B86aF770` | Live |
| `AerePasskeyAccountFactoryV2` | `0x5FFa9a6487DA4641a1A1e7900ff2bD4525D34fdA` | Live (canonical) |
| `AerePasskeyAccountFactory` (V1) | `0xfB0eF980667A79Fe1AB69c5f2d512118F1B30739` | Legacy, retained for the original demo account |
Source: `contracts/passkey/AerePasskeyAccountV2.sol`, `MultiOwnable.sol`, `WebAuthn.sol`, `AerePasskeyAccountFactoryV2.sol`.
### 2.2 WebAuthn verification (`WebAuthn.sol`)
`WebAuthn.verify` is a precompile-only port adapted from Coinbase's `base-org/webauthn-sol` library. Given the 32 byte challenge, a `requireUV` flag, the parsed `WebAuthnAuth` assertion, and the public key `(x, y)`, it:
1. Rejects malleable signatures (`s > n/2`, guarding against the secp256r1 curve order half).
2. Confirms `clientDataJSON` contains `"type":"webauthn.get"` at the declared `typeIndex`.
3. Reconstructs `"challenge":"<base64url(challenge)>"` and confirms it appears at `challengeIndex`, binding the signed browser payload to the on-chain challenge.
4. Checks the authenticator data flags: User Present always, User Verified when `requireUV` is set (the passkey account passes `requireUV = true`, so a biometric or PIN gesture is required, not a bare presence tap).
5. Computes `sha256(authenticatorData || sha256(clientDataJSON))` and calls the `0x100` precompile.
The FreshCryptoLib fallback path present in the upstream library is stripped, because the precompile is guaranteed on AERE from the Fusaka block.
### 2.3 Ownership model (`MultiOwnable.sol`)
Owners are stored as raw bytes: 32 bytes for an EOA (a `uint160` address left-padded, top 12 bytes must be zero) or 64 bytes for a P-256 public key (`x || y`). Each owner has a monotonic index that is never reused. The authorization gate is a self-call check: `onlyOwner` requires `msg.sender == address(this)`. That means every owner-management action (add EOA owner, add passkey owner, remove owner) must arrive as an authenticated self-call through one of the account's execute paths. Any single registered owner can add or remove other owners, and the set can never be emptied (`removeOwnerAtIndex` reverts `LastOwner` at count 1).
This is the account's recovery model in its live form: keep at least one owner, and optionally pre-register a backup key (for example a hardware EOA) so loss of the primary passkey does not lose the account. A guardian-and-timelock recovery flow is a separate module and lives in the in-development ERC-7579 line (Section 6), not in the passkey account itself.
### 2.4 Authorization paths (`AerePasskeyAccountV2.sol`)
The account exposes three ways to authorize a call, all resolving through the same `_verifyWrappedSignature` routine that selects the owner by index and dispatches to ECDSA recovery (EOA owners, EIP-191 personal_sign envelope, MetaMask compatible) or WebAuthn (passkey owners):
- **ERC-4337 path.** `validateUserOp` is callable only by the account's `entryPoint`. It verifies the wrapped signature over `userOpHash`, returns `0` on success or `1` (`SIG_VALIDATION_FAILED`) on failure per spec (it does not revert on a bad signature), and forwards any `missingAccountFunds` prefund to the EntryPoint. Execution is dispatched by `executeFromEntryPoint` / `executeBatchFromEntryPoint`, both EntryPoint-gated.
- **Direct passkey path.** `executeWithPasskey` / `executeBatchWithPasskey` let the Foundation relayer (or the user self-relaying) drive the account without a bundler. The signer signs a domain-separated `getExecuteChallenge` that binds `address(this)`, `block.chainid`, a monotonic `passkeyNonce`, and the call payload, giving replay protection independent of the EntryPoint nonce.
- **EIP-1271.** `isValidSignature` wraps the queried hash in an `AereAccount1271(address account,uint256 chainid,bytes32 hash)` digest before verifying, preventing cross-account signature replay. This makes the account usable with Permit2, OpenSea, Snapshot, and dapp login flows.
### 2.5 Deployment (`AerePasskeyAccountFactoryV2.sol`)
A CREATE2 factory. `predictAddress(initialOwners[], salt)` returns the counterfactual address; the initial owner set is mixed into the salt, so the same passkey with a different initial owner set produces a different address and multi-owner accounts cannot be front-run at their counterfactual address. `createAccount` is idempotent (returns the existing account if already deployed) and pins every new account to the factory's immutable `defaultEntryPoint`.
---
## 3. ERC-4337 EntryPoint (live) and an honest note on two EntryPoints
AERE ships two EntryPoint contracts, and the distinction matters for anyone integrating.
**`AereEntryPointV2`** at `0x8D6f40598d552fF0Cb358b6012cF4227B86aF770` (source `contracts/passkey/AereEntryPointV2.sol`) is the account-facing EntryPoint. It implements the canonical `handleOps(PackedUserOperation[], beneficiary)` flow: a validation phase that calls `account.validateUserOp` for every op and reverts the whole batch on any non-zero return, then an execution phase that calls `sender.call(op.callData)`, meters gas, and charges the paymaster's deposit if `paymasterAndData` names one, else the account's own deposit. It computes the canonical v0.7 `userOpHash` (binding the op fields, `address(this)`, and `block.chainid`), keeps per-account deposits, and emits standard `UserOperationEvent` records so bundlers and indexers can subscribe. AERE hosts its own relayer while bootstrapping; the contract is shaped so external bundlers (Pimlico, Stackup, ZeroDev) can target it via per-chain config.
**`AereEntryPoint`** at `0x19773ba45287A64B05d0BCBD59D1371BF51Bd5D2` (source `contracts/paymaster/AereEntryPoint.sol`) is a lightweight, paymaster-oriented EntryPoint from the Tier-1.3 stack. It implements the deposit and stake surface (`depositTo`, `balanceOf`, `withdrawTo`, `addStake`, `unlockStake`, `withdrawStake`) plus a `relayUserOp` that calls a paymaster's `validatePaymasterUserOp`, executes the sender call, and deducts the paymaster's deposit.
Two honest consequences of this split:
1. **The four paymasters bind to the staking-capable EntryPoint interface.** `PaymasterBase` (Section 4) declares an `IEntryPoint` with `addStake` / `unlockStake` / `withdrawStake`. `AereEntryPointV2` exposes deposit accounting but not staking, whereas the lightweight `AereEntryPoint` implements the full stake surface. The paymaster validation hook (`validatePaymasterUserOp`) is therefore exercised through the lightweight EntryPoint's `relayUserOp` path or through an off-chain relayer that calls the hook directly.
2. **`AereEntryPointV2.handleOps` charges a paymaster's deposit but does not itself call `validatePaymasterUserOp`.** It reads the paymaster address from `paymasterAndData[0:20]` and debits that deposit for `actualGasUsed * maxFee`, but the paymaster's own policy checks (per-sender caps, token pull, quota) are not invoked inside `handleOps`. Unifying paymaster validation into `handleOps` (so a single EntryPoint runs both account and paymaster validation in one batch) is a roadmap item. Until then, gasless sponsorship runs through the relayer-plus-lightweight-EntryPoint path where the hook is actually called.
Also note `handleOps` charges `actualGasUsed * maxFee` (the max fee, not an effective basefee-plus-tip price) and does not implement the full canonical prefund-and-refund economics. It is a compatible subset sufficient for the hosted relayer, not a byte-for-byte reimplementation of eth-infinitism v0.7.
---
## 4. The four gasless paymasters (live)
All four inherit `PaymasterBase` (`contracts/paymaster/PaymasterBase.sol`), an in-house `Ownable` (OpenZeppelin v4.9) base that exposes `validatePaymasterUserOp` / `postOp` guarded by `onlyEntryPoint`, plus deposit and stake helpers. Each paymaster overrides `_validatePaymasterUserOp` with its own sponsorship policy. "Gasless" here means the user needs no native AERE: either the Foundation, a dApp, the user's stake, or an ERC-20 covers the gas.
### 4.1 Address map
| Paymaster | Address (chain 2800) | Status |
|---|---|---|
| `AereOnboardingPaymaster` | `0x4058E406475Dbed7056Aee0c808f293F05fEa879` | Live |
| `AereAppPaymasterFactory` | `0xEC22603E8712cBc5c31E53370D10f1a80CcB4DF0` | Live (permissionless factory) |
| `AereTokenPaymasterV2` | `0x217f56a5b0C7f35abe4D2fff924A6c13B85d7243` | Live (canonical) |
| `AereStakeQuotaPaymasterV2` | `0xE50464ca7E8E7F542D1816B3172a2330cFE384E8` | Live (canonical) |
| `AereTokenPaymaster` (V1) | `0xEb6e2Eb24e597C85392DdCD68a1F9b654FffdcB2` | Deprecated, do not use |
| `AereStakeQuotaPaymaster` (V1) | `0xD16C86D792444c2667A26dB62f01b90FC0DaB87b` | Deprecated, do not use |
### 4.2 `AereOnboardingPaymaster` (Foundation-funded)
The first-touch paymaster. It sponsors a hard-capped number of UserOps per address (`sponsoredOpsPerSender`, default 3, lifetime, never resets) under a sitewide per-UTC-day cap (`dailySitewideCap`, default 100) for Sybil resistance, with an optional target-contract whitelist. When its Foundation-funded balance drains it refuses all ops until a governance top-up. The design intent recorded in source is that 3 sponsored ops per address plus a sitewide daily cap lets a fixed, small AERE budget onboard a large number of first-time users without an automated refill.
### 4.3 `AereAppPaymaster` via `AereAppPaymasterFactory` (dApp-funded)
Any dApp calls `createPaymaster()` on the factory (no fee, permissionless) and becomes owner of its own `AereAppPaymaster`. The dApp funds it from its own treasury and sets a required target whitelist, an optional sender allowlist, and an optional per-sender lifetime cap. The Foundation contributes nothing. This is the standard pattern for a game, marketplace, or app to sponsor its own users' gas.
### 4.4 `AereTokenPaymasterV2` (pay gas in an ERC-20)
Lets a user pay for gas in any whitelisted ERC-20 rather than native AERE. It reads the token's USD price and the AERE/USD price from an oracle, converts the op's AERE cost to a token amount, applies a markup in basis points (`markupBps`, default 500 = 5%, capped at 3000), and pulls the tokens via `transferFrom` (the user pre-approves). V2 fixes a V1 medium-severity bug: V1's `withdrawToken` used `transferFrom(address(this), ...)`, which needs a self-allowance that never exists, permanently stranding collected token revenue; V2 uses `transfer`, the correct primitive for moving the contract's own balance, so the Foundation can sweep collected fees. Honest dependency: the paymaster's oracle reference is immutable and, per the registry, currently resolves to the legacy price source; repointing it to `AereOracleV2` requires a fresh paymaster deploy.
### 4.5 `AereStakeQuotaPaymasterV2` (stake AERE, get free transactions)
A Tron-style UX: a user's effective AERE stake buys a daily quota of sponsored UserOps (`quotaPerDay = stakedAERE * txPerKiloAerePerDay / 1000`, default 20 free ops per 1000 AERE staked, resetting each UTC day, no rollover). Effective stake is the sum of delegated stake across the validator set, the user's own validator self-stake, and active locked-staking positions. V2 fixes two confirmed high-severity liveness bugs in V1: V1 called a non-existent `balanceOf` on the real staking contract (so the delegated read always returned 0), and V1 decoded `AereLockedStaking.getLock` with the wrong field order (so any real lock hard-reverted validation and the user could never be sponsored). V2 reads the real public getters and aggregates them, matches the real `getLock` field order (amount first), bounds both scan loops at 100 entries so validation cannot be griefed out of gas, and wraps every external read in try/catch so a paused source degrades the quota to 0 rather than bricking validation. It reads the canonical `AereStakingV2` (`0x1D95eF6D17aeAB732dF914Ba2d018c270BC155FC`) and `AereLockedStaking` (`0x21108c28A849b05aE6b7a3a5bc435C9Bc897E7Ad`) getters.
---
## 5. EIP-7702 EOA delegation (live)
For users who already hold a MetaMask style EOA and do not want a new address, EIP-7702 lets that EOA point its delegation tuple at a shared implementation and gain smart-account behavior in place.
| Component | Address (chain 2800) |
|---|---|
| `AereDelegate7702` | `0x5673D92080efbd0987402E9335c14200d0a5EaeF` |
| `AereDelegationRegistry` | `0x6c25c07D134713b6C2F8E19D807423f022903D63` |
**`AereDelegate7702`** (`contracts/delegation/AereDelegate7702.sol`) is the code an EOA delegates to. Because EIP-7702 transmits only code, not storage, every EOA delegating to this one implementation gets independent storage at its own account, and can re-point its delegation at any time with no migration. Its surface:
- `executeBatch(Call[])`: atomic multicall, authorized by the EOA's own transaction signature. The owner check is `msg.sender == address(this)`, which under 7702 is the EOA acting on itself. A transient reentrancy guard protects the batch path.
- `executeWithPasskey(Call, P256Signature)`: a single call authorized by a registered WebAuthn passkey, verified through the `0x100` precompile, with a relayer paying gas. A round-3 fix binds the signed `clientDataJSON` to the specific call by recomputing the expected challenge `keccak256(address(this), passkeyNonce, call)`, base64url-encoding it, and requiring the canonical `"challenge":"<expected>"` substring, which closes a replay hole where an unrelated WebAuthn login signature could have authorized arbitrary calls. A `passkeyNonce` gives replay protection.
- `addSessionKey` / `revokeSessionKey` / `executeWithSessionKey`: register a scoped secondary key with an expiry and a selector allowlist for low-risk, popup-free dApp flows, plus a kill switch.
- `setPasskey(x, y)`: register one WebAuthn key. Phase 1 supports a single passkey; the source notes a Phase 2 extension to a MultiOwnable-style set is planned.
**`AereDelegationRegistry`** is a purely informational, permissionless index: an EOA self-registers (`register()`), the registry records the account's delegated code hash and timestamps, and dApps query it to render a "smart-wallet enabled" badge, discover batch-eligible EOAs, and coordinate paymaster eligibility. It holds no funds and has no authority over any account; wrong data only affects the registrant's own UX.
---
## 6. ERC-7579 modular accounts, session keys, social recovery (in development, not yet on mainnet)
A modular account line exists in source but is **not present in the canonical registry (`addresses.ts`) and is therefore not deployed to mainnet 2800**. It is documented here as the intended next-generation account, marked in-development. No mainnet address is cited because none exists yet.
Source files: `contracts/modular/AereModularAccount.sol`, `AereModularAccountFactory.sol`, `AereSessionKeyValidator.sol`, `AereSessionKeyValidatorV2.sol`, `AereSocialRecoveryModule.sol`.
**`AereModularAccount`** is an ERC-4337 account with ERC-7579-style pluggable modules of two types: validators (type 1, signature validation) and executors (type 2, may call `executeFromExecutor` and `setRootOwner`). It targets `AereEntryPointV2` exactly, and because that EntryPoint uses a single-dimension nonce, the account routes validation on the first signature byte: `0x00` selects the root-owner ECDSA fallback (`0x00 || 65-byte sig` over the EIP-191 envelope), `0x01` selects an installed validator module (`0x01 || 20-byte validator address || payload`). Validators return the canonical 4337 validation-data packing (`authorizer | validUntil<<160 | validAfter<<208`); since `AereEntryPointV2` reverts on any non-zero return and cannot unpack time bounds, the account unpacks the packing itself, enforces the time window against `block.timestamp`, and returns strictly `0` or `1`. It supports `execute` / `executeBatch`, EIP-1271 with the same domain-wrapping convention as the passkey account, and root-owner rotation gated to a self-call or an installed executor.
**`AereSessionKeyValidator` / `AereSessionKeyValidatorV2`** (ERC-7579 type 1) grant a session key a window (`validAfter`, `validUntil`), a per-op native value cap, and an allowlist of `(target, selector)` pairs, with `0x00000000` as the native-transfer sentinel. V2 is a hardened redeploy of the module logic that fixes a confirmed per-batch value-cap bypass (V1 checked each `executeBatch` sub-call's value independently against the per-op cap with no running sum, so a session key could move `maxValuePerOp * N` in one batch); V2 caps the sum of sub-call values, adds a defense-in-depth rule that a session key can never call account-admin selectors (`installModule`, `uninstallModule`, `setRootOwner`, `execute`, `executeBatch`) back into its own account regardless of the allowlist, and adds an optional rolling cumulative spend cap.
**`AereSocialRecoveryModule`** (ERC-7579 type 2 executor) is the guardian-based recovery the live passkey account lacks. An M-of-N guardian set, per account, drives an `initiateRecovery` then `supportRecovery` flow; after a 48 hour timelock and at least the threshold approvals, any guardian may `executeRecovery`, which calls `account.setRootOwner`. The current owner or the account can `cancelRecovery` at any time before execution. Guardian and threshold changes are owner-only (they require `msg.sender == account`).
When this line is audited and deployed, its addresses will be added to `addresses.ts` and this section updated to "live".
---
## 7. ERC-6551 token-bound accounts (live)
ERC-6551 gives every NFT its own wallet. These are account and registry primitives, not tokens: they mint nothing and have no supply.
| Component | Address (chain 2800) |
|---|---|
| `ERC6551Registry` | `0x7fFdA0AcDeB919938dB91dbEa779D841c833EF68` |
| `AereTokenBoundAccount` | `0xBc5e24180f3F75DC6b1965E4aaD3D4F184b6F9E2` |
**`ERC6551Registry`** (`contracts/tokenbound/ERC6551Registry.sol`) is the verbatim `erc6551/reference` registry: a stateless, owner-less CREATE2 factory that deploys deterministic ERC-1167 minimal-proxy accounts bound to a `(chainId, tokenContract, tokenId)` tuple. The source notes the canonical public deployment lives at `0x000000006551c19487814612e58FE06813775758` on chains that received the deterministic Nick-factory deploy; on AERE the identical source was deployed at the address above (the address differs only because the deterministic factory salt was not replayed here, the bytecode and behavior are identical).
**`AereTokenBoundAccount`** (`contracts/tokenbound/AereTokenBoundAccount.sol`) is the implementation the proxies point at. Its sole authority source is `ownerOf(tokenId)` on the bound ERC-721, read live. Whoever holds the NFT controls the account: they can `execute` arbitrary calls (operation 0, CALL only; DELEGATECALL and CREATE are rejected so the account can never be hijacked into changing its own logic), and the account produces EIP-1271 signatures on their behalf via OpenZeppelin `SignatureChecker` (so both EOA and smart-contract holders work). It also implements the ERC-4337 path against `AereEntryPointV2` (hardcoded as `ENTRY_POINT`), so a bundler or paymaster can sponsor the NFT wallet's gas. A live demo binds `AereNFT` (`0x3f9A9D9CAB005327869396C69bE226ef98039f1c`) token #1 to account `0x82D24cC4E09CaBfD9B00233438B8B6321CBC13Dd`.
---
## 8. Post-quantum smart account (live, roadmap #270)
The most experimental account in the stack, and the one whose scope needs the most careful statement. It is a working ERC-4337 v0.7 account whose sole owner is a NIST Falcon-512 lattice public key, with no classical ECDSA fallback.
| Component | Address (chain 2800) |
|---|---|
| `AerePQCAccountFactory` | `0xd5315Ea7caa60d320c4f34b1bEd70dd9cc02CE58` |
| `AerePQCAccount_sample` | `0xa42a5e7F72E46BadC11367650Ec34D676194326f` |
| `AereFalcon512Verifier` | `0x4E8e9682329e646784fB3bd01430aA4bA54D8fFC` |
**`AerePQCAccount`** (`contracts/pqc/AerePQCAccount.sol`) owns exactly one Falcon-512 public key (897 bytes, NIST encoding, header byte `0x09`). Every authorization, a bundled UserOperation, an EIP-1271 check, or the direct `executeWithFalcon` path, is decided by the live on-chain `AereFalcon512Verifier`, which runs real lattice cryptography: SHAKE256 HashToPoint, 14-bit public-key decode, compressed-signature decode, negacyclic NTT multiply mod q=12289 in the ring, centering, and an l2-norm bound check. The signature envelope is `abi.encode(bytes nonce, bytes compSig)` (the 40-byte Falcon salt and the compressed s2 body); the message handed to the verifier is the raw 32 bytes of the relevant hash, which for a UserOperation is the userOpHash that already binds sender and chain. `validateUserOp` returns `0` or `1` per spec; `isValidSignature` is a `view`, so integrators can verify a post-quantum signature for free via `eth_call`. `AerePQCAccountFactory` is a CREATE2 factory keyed on `(falconPubKey, salt)`, mirroring the passkey factory, binding each account to an immutable EntryPoint and Falcon verifier.
**Honest scope, stated exactly as the registry frames it.** This is Falcon-512 (NIST security level 1), not Falcon-1024. A Falcon-512 verify is heavy: roughly 10.5M gas per PQC authorization. That is real and it fits under the Fusaka EIP-7825 per-transaction cap of 2^24 = 16,777,216 gas, and a full UserOperation through `AereEntryPointV2.handleOps` was demonstrated end-to-end with estimated 10,641,716 and measured 10,278,313 gas used, under the cap, `opSuccess=true`. A native SHAKE or keccak precompile would cut this sharply and is tracked as a separate roadmap item. PQC authorization here is app-layer and account-layer: it secures how this account authorizes operations. It does not change consensus. AERE's validators sign classical QBFT, and the native PQC precompiles that would make lattice verification cheap are proposed and in development on a scratch fork, not live on mainnet 2800. On the broader PQC verifier suite that this account draws on, we are not aware of any other public chain that verifies all of these on-chain; that is the claim, stated with that exact hedge, and nothing stronger.
---
## 9. Honest limitations
This layer is real and on chain, but a credible reader should weigh it against the following, all true today.
- **Decentralization.** AERE runs seven QBFT validators under one operator, one client (Besu), with no external security audit of these contracts and thin real-world usage. The wallet layer inherits that trust profile. Sponsorship and relaying currently depend on a Foundation-hosted relayer.
- **Two EntryPoints, one seam.** As described in Section 3, the account-facing `AereEntryPointV2` and the paymaster-facing lightweight `AereEntryPoint` are distinct, and `handleOps` charges but does not itself invoke the paymaster validation hook. Gasless flows run through the relayer-plus-lightweight-EntryPoint path. Unifying the two is a roadmap item.
- **EntryPoint economics are a subset.** `AereEntryPointV2` uses `maxFee` for gas charging and does not implement full canonical prefund-and-refund. It is sufficient for the hosted relayer, not a drop-in reimplementation of eth-infinitism v0.7.
- **Recovery.** The live passkey account's recovery is "keep at least one owner / add a backup owner". Guardian-and-timelock social recovery is source-complete in the ERC-7579 line but not yet deployed (Section 6).
- **ERC-7579 modular line is not live.** The modular account, its factory, both session-key validators, and the social recovery module are in-development. They carry no mainnet address and must not be presented as deployed.
- **Post-quantum cost.** The Falcon-512 account is genuinely quantum-resistant at the account layer but costs roughly 10.5M gas per authorization and is level 1, not 1024. It is a real primitive with a heavy price, pending a SHAKE precompile.
- **Deprecated contracts remain on chain.** The V1 token and stake-quota paymasters, and the V1 passkey factory, are retained at their addresses; integrators must point at the canonical V2 addresses listed above.
---
## 10. Address appendix (verbatim from `addresses.ts`)
**EntryPoints**
- `AereEntryPointV2` (accounts): `0x8D6f40598d552fF0Cb358b6012cF4227B86aF770`
- `AereEntryPoint` (lightweight, paymaster relay): `0x19773ba45287A64B05d0BCBD59D1371BF51Bd5D2`
**Passkey wallets**
- `AerePasskeyAccountFactoryV2`: `0x5FFa9a6487DA4641a1A1e7900ff2bD4525D34fdA`
- `AerePasskeyAccountFactory` (V1, legacy): `0xfB0eF980667A79Fe1AB69c5f2d512118F1B30739`
**Paymasters**
- `AereOnboardingPaymaster`: `0x4058E406475Dbed7056Aee0c808f293F05fEa879`
- `AereAppPaymasterFactory`: `0xEC22603E8712cBc5c31E53370D10f1a80CcB4DF0`
- `AereTokenPaymasterV2`: `0x217f56a5b0C7f35abe4D2fff924A6c13B85d7243`
- `AereStakeQuotaPaymasterV2`: `0xE50464ca7E8E7F542D1816B3172a2330cFE384E8`
- `AereTokenPaymaster` (V1, deprecated): `0xEb6e2Eb24e597C85392DdCD68a1F9b654FffdcB2`
- `AereStakeQuotaPaymaster` (V1, deprecated): `0xD16C86D792444c2667A26dB62f01b90FC0DaB87b`
**EIP-7702**
- `AereDelegate7702`: `0x5673D92080efbd0987402E9335c14200d0a5EaeF`
- `AereDelegationRegistry`: `0x6c25c07D134713b6C2F8E19D807423f022903D63`
**ERC-6551**
- `ERC6551Registry`: `0x7fFdA0AcDeB919938dB91dbEa779D841c833EF68`
- `AereTokenBoundAccount`: `0xBc5e24180f3F75DC6b1965E4aaD3D4F184b6F9E2`
- Demo NFT (`AereNFT`): `0x3f9A9D9CAB005327869396C69bE226ef98039f1c`
- Demo bound account: `0x82D24cC4E09CaBfD9B00233438B8B6321CBC13Dd`
**Post-quantum account**
- `AerePQCAccountFactory`: `0xd5315Ea7caa60d320c4f34b1bEd70dd9cc02CE58`
- `AerePQCAccount_sample`: `0xa42a5e7F72E46BadC11367650Ec34D676194326f`
- `AereFalcon512Verifier`: `0x4E8e9682329e646784fB3bd01430aA4bA54D8fFC`
**Supporting**
- `AereStakingV2`: `0x1D95eF6D17aeAB732dF914Ba2d018c270BC155FC`
- `AereLockedStaking`: `0x21108c28A849b05aE6b7a3a5bc435C9Bc897E7Ad`
- Foundation (owner of all `Ownable` contracts): `0x0243A4f47D44b40b65D33f20329dE20D00c6f3C3`
**In development, no mainnet address (ERC-7579 modular line):** `AereModularAccount`, `AereModularAccountFactory`, `AereSessionKeyValidator`, `AereSessionKeyValidatorV2`, `AereSocialRecoveryModule`.