Developer docs

Build on AERE, EVM-compatible Layer 1, chain ID 2800, sub-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 general-purpose public RPC endpoints are available for redundancy, hosted in separate datacenters. Both are operated by the Aere Foundation, so they are not independent parties and are not a second opinion on each other; a third, https://client2.aere.network, is served by the second client for the eth, net and web3 methods (corrected 2026-10-28: this said two independent endpoints). The two general endpoints 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-10-16 (first measured 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 620 ms block interval (re-measured 2026-10-15) is about 5 minutes 17 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 behaviour that used to need coding around

Outside the window, both endpoints now refuse every state read plainly: eth_getBalance, eth_getCode, eth_getStorageAt, eth_getTransactionCount and eth_getProof return error -32000 World state unavailable, and eth_call returns -32603 Internal error (re-measured on both endpoints on 2026-10-16).

Until 2026-09-10, eth_getTransactionCount did not. Outside the window it returned 0x0, which is a well formed value and is indistinguishable from an account that has never sent a transaction, and eth_getBalance, eth_getCode and eth_getStorageAt returned null. Code that read a nonce at a historical block and trusted the answer silently concluded that an active account had never signed anything. Other providers and older node versions can still answer that way, so the rules below still apply. Here is the example, with what both endpoints answer today:

# 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"]}'
# -> today: error -32000 "World state unavailable", the honest answer.
#    Until 2026-09-10: "result":"0x0", which was WRONG: the correct answer is "unavailable", not zero.

# eth_getBalance, at the same address and the same block:
# -> today: error -32000 "World state unavailable"   (until 2026-09-10: "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 what the raw call returns today (a refusal; a false zero until 2026-09-10), shows the guard turned off handing a false zero to a caller (reproduced by a wrapper, now that these endpoints no longer produce one), then shows the guard turned on refusing. It exits non-zero if any of that stops being true. Run on 2026-10-16:

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

ANCHOR  block 8236382 body says 0xbeb33d20… signed with nonce 123063
STEP 1  WHAT THE ENDPOINT DOES TODAY   refuses honestly: error -32000 World state unavailable
STEP 2  NEGATIVE CONTROL  guard disabled (false zero reproduced), getTransactionCount answered 0
STEP 3  THE GUARD         StateWindowError requested-block-outside-window
STEP 4  MEASURE           511 answers, 512 does not
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_getBalanceno-32000 World state unavailable (until 2026-09-10: null)
eth_getCodeno-32000 World state unavailable (until 2026-09-10: null)
eth_getStorageAtno-32000 World state unavailable (until 2026-09-10: null)
eth_getProofno-32000 World state unavailable
eth_callno-32603 Internal error
eth_getTransactionCountno-32000 World state unavailable (until 2026-09-10: "0x0", the false answer described above)

Since 2026-09-10 every pruned read on these two endpoints raises an error (corrected 2026-10-27: this page dated that change, in seven places, to October 2026; both public endpoints run the build that refuses since 2026-09-10). Until then the nonce row was the only one where the endpoint returned a value it did not have. If you take one thing from this page, take that row, and check it first on any other provider you use.

Namespaces and limits, as actually served

Itemrpc.aere.networkrpc2.aere.network
ETH, NET, WEB3, QBFTenabledenabled
txpool_*enablednot enabled, -32604
debug_*, trace_*not exposeda read-only subset since 2026-09-02, by exact method name (listed below), within the state window
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, about 5m17s at the measured 0.62 s block interval

Tracing: off on rpc, a read-only subset on rpc2, and what that costs you

On rpc.aere.network the debug_ and trace_ namespaces are not exposed. On rpc2.aere.network, since 2026-09-02, sixteen read-only methods are served by exact name, and nothing else in those namespaces: debug_traceTransaction, debug_traceBlockByNumber, debug_traceBlockByHash, debug_traceBlock, debug_traceCall, debug_getRawHeader, debug_getRawBlock, debug_getRawTransaction, debug_getRawReceipts, debug_storageRangeAt, trace_transaction, trace_block, trace_call, trace_callMany, trace_replayBlockTransactions and trace_get. A trace re-executes against world state, so on rpc2 it works inside the same 512-block window and returns -32603 for anything older (measured 2026-10-16). Both choices are deliberate, and they have 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. About 0.62 seconds 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 rpc.aere.network (re-measured 2026-10-16):

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
debug_metrics on rpc2 (not in the read-only subset)-32601 Method not foundnull

-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 the public source: npm install git+https://git.aere.network/aere-network/sdk-js.git ethers
import { AereClient } from "@aere/sdk";

const aere = new AereClient({ rpcUrl: "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/statsHead block, timestamp, gas price and base fee
GET /api/blocksRecent blocks (limit/offset)
GET /api/block/:nOne block by number, with its transactions (a block hash is not accepted)
GET /api/transactionsRecent transactions
GET /api/tx/:hashSingle tx + receipt
GET /api/address/:addrBalance, nonce and code of an address (no activity, no history)
Measured 2026-10-16: these six routes answer 200. The token routes (holders, transfers, stats) and the mempool routes listed here in earlier revisions answer 404 and are not offered; for pending transactions use txpool_content on rpc.aere.network. Corrected 2026-10-28, measured that day: this table said that /api/stats gives a total transaction count, that /api/block answers by hash and that /api/address gives recent activity; the API keeps no indexed history, and its routes are described in full on the data API page.

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-v3-2026-10-16. Every endpoint behaviour on this page was measured against rpc.aere.network and rpc2.aere.network, not taken from a client manual: the state window, the namespaces, the error codes, the tracing subset and the indexer routes were re-measured on 2026-10-16; the rest was measured on 2026-08-02. The previous revision is kept, unedited, at rpc-docs-v2-2026-08-02.html, so that anything quoted from it stays quotable; it describes the endpoints as they were on that date. Earlier revision: 2026-07-20.