Developer docs

Build on AERE, EVM-compatible Layer 1, chain ID 2800, 0.5-second blocks, QBFT consensus.

Quick reference

Public RPC
https://rpc.aere.network copy
https://rpc2.aere.network copy
WebSocket
wss://wss.aere.network copy
Chain ID
2800 (0xAF0)
Native token
AERE (18 decimals)
Indexer API

Add to MetaMask

Click the button below or visit aere.network/addnetwork:

Public RPC endpoints

Two independent public RPC endpoints are available for redundancy, hosted in separate datacenters. Both are open and rate-limited per IP, and both serve the same chain. Point your client at either, or list both in your wallet for automatic failover if one is unreachable.

EndpointAuthRate limit
rpc.aere.networknoneper-IP
rpc2.aere.networknoneper-IP

What these endpoints serve, and what they do not

Both public endpoints are pruning full nodes, not archive nodes. That distinction changes what you can ask them, so it is written down here rather than left for you to discover.

Every number in this section was re-measured against both endpoints on 2026-08-02: 511 blocks deep answers, 512 does not, on rpc.aere.network and on rpc2.aere.network. The command that measured it is in the SDK and you can run it yourself, below. An archive node that does not have this limit exists and is being prepared for exposure.

History that is always available

Blocks, transactions, receipts, logs and the validator set go back to block 0. Anything derived from a block body or a receipt is available at any depth: eth_getBlockByNumber, eth_getBlockByHash, eth_getTransactionByHash, eth_getTransactionReceipt, eth_getBlockReceipts, eth_getLogs, qbft_getValidatorsByBlockNumber.

World state: a rolling window of about 512 blocks

Account and contract state is retained for roughly the most recent 512 blocks, which at the measured 517 ms block interval is about 4 minutes 25 seconds of chain. Beyond that the state has been pruned and the node cannot answer. This applies to eth_getBalance, eth_getCode, eth_getStorageAt, eth_call, eth_getProof and eth_getTransactionCount.

The window is an operational fact of a pruning node, and it is a real edge rather than a fixed fence: the chain head advances while your request is in flight, so a block that was 511 deep when you looked it up can be 512 deep by the time the node reads it. Leave yourself a margin of a few blocks, or simply read at latest.

The one behaviour you must code around

Outside the window, most methods say so plainly. eth_getBalance, eth_getCode and eth_getStorageAt return null; eth_getProof returns error -32000 World state unavailable; eth_call returns an error.

eth_getTransactionCount does not. Outside the window it returns 0x0, which is a well formed value and is indistinguishable from an account that has never sent a transaction. If your code reads a nonce at a historical block and trusts the answer, it will silently conclude that an active account has never signed anything. This is the single most important thing to know about these endpoints, so here it is with a reproducible example you can run right now:

# Block 8,236,382 contains a transaction from this address with nonce 123,063.
# Read it straight out of the block body, which is available at any depth:
curl -s https://rpc.aere.network -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionByHash","params":
       ["0xbfd3620dc705cc1dbf5bf747c02f71f0d4f68227ab8b5ccafe3de15955587ce3"]}'
# -> "from":"0xbeb33d20dfbbd49ec7ac1f617667f1f02dfd6465", "nonce":"0x1e0b7"   (123,063)

# Now ask for that same account's nonce AT that block. The state is long gone:
curl -s https://rpc.aere.network -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionCount","params":
       ["0xbeb33d20dfbbd49ec7ac1f617667f1f02dfd6465","0x7dad5e"]}'
# -> "result":"0x0"        WRONG. The correct answer is "unavailable", not zero.

# eth_getBalance, at the same address and the same block, is honest about it:
# -> "result":null

Three rules follow, and they are cheap to apply:

The @aere/sdk ships StateWindowReader, which applies all three for you. It returns a value or throws; it never returns a placeholder.

import { StateWindowReader, StateWindowError } from "@aere/sdk";

const reader = new StateWindowReader((m, p) => provider.send(m, p));

await reader.getTransactionCount(addr);            // latest: fine
await reader.getTransactionCount(addr, 8236382);   // throws StateWindowError, never returns 0

// Do not trust the number above, measure it yourself against the endpoint:
await reader.measureWindow();   // { head, deepestOkDepth: 511, firstFailDepth: 512 }

The SDK also ships the proof itself, so you do not have to take the paragraph above on faith. It reads the true nonce out of a block body, shows the raw call returning the false zero, shows the guard turned off handing that zero to a caller, then shows the guard turned on refusing. It exits non-zero if any of that stops being true:

node dist/test/state-window-live.js https://rpc.aere.network

ANCHOR  block 8236382 body says 0xbeb33d20… signed with nonce 123063
STEP 1  PLANTED FAILURE  eth_getTransactionCount returns a false zero   -> "0x0"
STEP 2  NEGATIVE CONTROL guard disabled, getTransactionCount answered 0
STEP 3  THE GUARD        StateWindowError requested-block-outside-window
STEP 4  MEASURE          511 answers, 512 refused
RESULT: PASS

Which calls work at any depth, and which do not

This table is measured against both endpoints, not copied from a Besu manual. Everything in the green half reads from a block body, a receipt or the header chain, all of which are kept from block 0. Everything in the red half reads the world-state trie, which is pruned.

MethodAt any depthOutside the 512-block window it returns
eth_getBlockByNumberyesthe block
eth_getBlockByHashyesthe block
eth_getTransactionByHashyesthe transaction, including its real nonce
eth_getTransactionReceiptyesthe receipt
eth_getBlockReceiptsyesevery receipt in the block
eth_getLogsyesthe logs, within a 5,000-block span
qbft_getValidatorsByBlockNumberyesthe validator set at that height
eth_getBalancenoresult: null
eth_getCodenoresult: null
eth_getStorageAtnoresult: null
eth_getProofno-32000 World state unavailable
eth_callno-32603 Internal error
eth_getTransactionCountno"0x0", and that is the false answer described above

The nonce row is the only one where the endpoint returns a value it does not have. Every other pruned read either says null or raises an error. If you take one thing from this page, take that row.

Namespaces and limits, as actually served

Itemrpc.aere.networkrpc2.aere.network
ETH, NET, WEB3, QBFTenabledenabled
txpool_*enablednot enabled, -32604
debug_*, trace_*, admin_*, miner_*not exposednot exposed
eth_getLogsat most 5,000 blocks between fromBlock and toBlock, otherwise -32005. A span of exactly 5,000 is accepted; 5,001 is refused.
World state depth512 blocks, roughly 4m25s

Tracing is switched off, and here is what that costs you

The debug_ and trace_ namespaces are not exposed on either public endpoint. That is a deliberate choice, and it has a real price for you. Stating the choice without stating the price would be dishonest, so both are here.

Why

A single debug_traceBlockByNumber re-executes every transaction in a block with an instrumented EVM and can allocate hundreds of megabytes for one response. On an open, unauthenticated endpoint that is a denial of service anyone can trigger from a laptop, and these two endpoints also carry wallets, the explorer and every integration on the network. Half a second of block time leaves no slack to absorb it. admin_ and miner_ are off for the more obvious reason: they mutate a node the public does not own.

The cost, stated plainly

There is one more cost, and it is the subtle one. The error you get back does not tell you the namespace was switched off. Measured on both endpoints:

You callYou getJSON-RPC id
debug_traceTransaction-32601 Method not foundnull
trace_block-32601 Method not foundnull
admin_peers-32601 Method not foundnull
eth_totallyMadeUpMethod-32601 Method not foundechoed
txpool_besuStatistics on rpc2-32604 Method not enabledechoed

-32604 Method not enabled is what a node says when it has a method and has chosen not to serve it. That is the honest code, and rpc2 uses it for txpool_. The debug_ and trace_ methods do not get that code; they get -32601 Method not found, the same code an invented method gets, which reads as if the method never existed. So: a -32601 on a debug_ or trace_ call is a policy decision, not a statement about the chain. The data those methods would read is present on the network. It is simply not offered here.

What you get instead

These are on the public endpoints today, measured, and they cover most of what people actually reach for tracing to do.

Instead ofUseWhat it gives you
debug_traceCalleth_simulateV1Many calls in one simulated block, each with its own status, gasUsed, logs and decoded revert reason. traceTransfers: true emits a synthetic Transfer log for plain value movement, at pseudo-address 0xeee…eee, so internal transfers stop being invisible.
debug_traceCall with overrideseth_simulateV1 + stateOverridesRewrite balances, nonces, code or individual storage slots for the simulation only, then run the call against that world. This is the closest public substitute for a full tracing session.
debug_traceCalleth_callThe full revert reason, not just a failure flag. See below.
debug_storageRangeAteth_createAccessListExactly which accounts and storage slots a call touches, plus its gas.
debug_traceBlocketh_getBlockReceiptsStatus, gas and every log for every transaction in the block, at any depth.
a trusted state readeth_getProofA Merkle proof against the state root at latest, which you can verify yourself instead of trusting us.

A revert on this chain comes back decoded, which is the single most common reason to want a trace:

curl -s https://rpc.aere.network -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":
       [{"from":"0x0000000000000000000000000000000000000001",
         "to":"0x7e84d7d66d5da4cfE46Da67CDEeB05B323e1f5e8",
         "data":"0x23b872dd…"},"latest"]}'

{"error":{"code":3,
          "message":"Execution reverted (WAERE: insufficient balance)",
          "data":"0x08c379a0…"}}
# The message carries the Solidity revert string, and data is the ABI-encoded
# Error(string) so you can decode custom errors yourself.

And if you genuinely need opcode-level tracing, take it. The chain is not the obstacle, the shared endpoint is:

# genesis.json and the chain spec are public. Run a node, enable everything,
# and trace against your own hardware instead of ours.
besu --network-id=2800 --genesis-file=genesis.json \
     --data-storage-format=BONSAI \
     --rpc-http-enabled --rpc-http-api=ETH,NET,WEB3,QBFT,DEBUG,TRACE,TXPOOL
# For historical state as well, add:  --sync-mode=FULL --data-storage-format=FOREST

The archive node

An archive node for chain 2800 exists and is fully synced. It holds world state at every height from block 0, and it answers debug_ and trace_. It is not yet reachable from the public internet, and this section says exactly where it stands rather than promising a date we have not earned.

Measured 2026-08-02

Full sync from block 0, eth_syncing false, head tracking the public endpoints in the same second. A verifier walks 20 sampled heights spanning block 1 to block 11,000,000, asks each for eth_getBalance, eth_getCode and eth_getStorageAt, and carries every answer back to a state root that both public endpoints independently confirm. 20 of 20 heights judged, 0 failures, 0 unproven answers. Pointed at a public pruning endpoint, the same verifier reports 81 failures and exits non-zero, which is how we know the check is capable of failing. At block 8,236,382 the archive answers nonce 123,064, matching what the block body proves; the public endpoints answer 0x0.

What is left is exposure, not construction: a public listener, a TLS certificate and a rate limit in front of a node that already has the data. We are not publishing a launch date, because the work that remains is a decision rather than an engineering task, and a date we invent is worth nothing to you. What we will commit to is that this section gets updated the day it changes, and that the endpoint will not be announced until the same verifier passes against it from outside our network.

If historical state or tracing is blocking you now, say so at git.aere.network and we will prioritise accordingly. In the meantime the two public endpoints are deliberately tuned to stay fast for the common case, and running your own node with --sync-mode=FULL gives you the same history on your own hardware.

SDK quickstart

JavaScript / TypeScript (@aere/sdk)

// not yet on public npm, install from GitHub: npm install github:aerenetwork/aere-sdk ethers
import { AereClient } from "@aere/sdk";

const aere = new AereClient({ rpc: "https://rpc.aere.network" });

// Read state
const portfolio = await aere.getPortfolio("0x0243A4f47D44b40b65D33f20329dE20D00c6f3C3");
console.log(portfolio);

// Watch incoming transfers
aere.watchTransfersTo(myAddr, (event) => {
  console.log("got", event.value, "AERE from", event.from);
});

Plain ethers v6

import { JsonRpcProvider, Contract, parseEther } from "ethers";

const provider = new JsonRpcProvider("https://rpc.aere.network");
const blockNum = await provider.getBlockNumber();

// Read an ERC-20 (WAERE)
const waere = new Contract(
  "0x7e84d7d66d5da4cfE46Da67CDEeB05B323e1f5e8",
  ["function totalSupply() view returns (uint256)"],
  provider
);
const sup = await waere.totalSupply();

Python (web3.py)

from web3 import Web3
w3 = Web3(Web3.HTTPProvider("https://rpc.aere.network"))
print("chain id:", w3.eth.chain_id)  # 2800
print("latest:", w3.eth.block_number)

Indexer REST API

Hosted at https://api.aere.network. CORS open. Read-only.

PathDescription
GET /api/statsLatest indexed block + total tx count
GET /api/blocksRecent blocks (limit/offset)
GET /api/block/:idBlock by number or hash + tx list
GET /api/transactionsRecent transactions
GET /api/tx/:hashSingle tx + receipt
GET /api/address/:addrRecent activity for address
GET /api/token/:addr/holdersERC-20 holders + balances
GET /api/token/:addr/transfersRecent Transfer events
GET /api/token/:addr/statsTotal transfer count
GET /api/mempoolPending-tx snapshot (last 5 min)
GET /api/mempool/streamServer-Sent Events feed of new pending tx

Contracts

Production contract addresses are bundled in @aere/sdk. The full list, with read methods, is on the dApp dashboard.

Source code

All AERE Network code is hosted at git.aere.network (self-hosted Gitea, GitHub mirror is rate-limited):


Revision rpc-docs-v2-2026-08-02. Every endpoint behaviour on this page was measured against rpc.aere.network and rpc2.aere.network on 2026-08-02, not taken from a client manual. A dated copy of this revision is kept at rpc-docs-v2-2026-08-02.html and is not edited again, so that anything you quote from it stays quotable. Previous revision: 2026-07-20.