Build on AERE, EVM-compatible Layer 1, chain ID 2800, 0.5-second blocks, QBFT consensus.
Click the button below or visit aere.network/addnetwork:
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.
| Endpoint | Auth | Rate limit |
|---|---|---|
| rpc.aere.network | none | per-IP |
| rpc2.aere.network | none | per-IP |
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.
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.
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.
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:
latest or pending. Wallets, nonce management and
balance display need nothing else, and at latest every method here is correct.0.latest, or scan block bodies, which are retained forever.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
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.
| Method | At any depth | Outside the 512-block window it returns |
|---|---|---|
| eth_getBlockByNumber | yes | the block |
| eth_getBlockByHash | yes | the block |
| eth_getTransactionByHash | yes | the transaction, including its real nonce |
| eth_getTransactionReceipt | yes | the receipt |
| eth_getBlockReceipts | yes | every receipt in the block |
| eth_getLogs | yes | the logs, within a 5,000-block span |
| qbft_getValidatorsByBlockNumber | yes | the validator set at that height |
| eth_getBalance | no | result: null |
| eth_getCode | no | result: null |
| eth_getStorageAt | no | result: null |
| eth_getProof | no | -32000 World state unavailable |
| eth_call | no | -32603 Internal error |
| eth_getTransactionCount | no | "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.
| Item | rpc.aere.network | rpc2.aere.network |
|---|---|---|
| ETH, NET, WEB3, QBFT | enabled | enabled |
| txpool_* | enabled | not enabled, -32604 |
| debug_*, trace_*, admin_*, miner_* | not exposed | not exposed |
| eth_getLogs | at most 5,000 blocks between fromBlock and toBlock, otherwise -32005. A span of exactly 5,000 is accepted; 5,001 is refused. | |
| World state depth | 512 blocks, roughly 4m25s | |
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.
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.
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 call | You get | JSON-RPC id |
|---|---|---|
| debug_traceTransaction | -32601 Method not found | null |
| trace_block | -32601 Method not found | null |
| admin_peers | -32601 Method not found | null |
| eth_totallyMadeUpMethod | -32601 Method not found | echoed |
| txpool_besuStatistics on rpc2 | -32604 Method not enabled | echoed |
-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.
These are on the public endpoints today, measured, and they cover most of what people actually reach for tracing to do.
| Instead of | Use | What it gives you |
|---|---|---|
| debug_traceCall | eth_simulateV1 | Many 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 overrides | eth_simulateV1 + stateOverrides | Rewrite 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_traceCall | eth_call | The full revert reason, not just a failure flag. See below. |
| debug_storageRangeAt | eth_createAccessList | Exactly which accounts and storage slots a call touches, plus its gas. |
| debug_traceBlock | eth_getBlockReceipts | Status, gas and every log for every transaction in the block, at any depth. |
| a trusted state read | eth_getProof | A 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
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.
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.
// 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); });
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();
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)
Hosted at https://api.aere.network. CORS open. Read-only.
| Path | Description |
|---|---|
| GET /api/stats | Latest indexed block + total tx count |
| GET /api/blocks | Recent blocks (limit/offset) |
| GET /api/block/:id | Block by number or hash + tx list |
| GET /api/transactions | Recent transactions |
| GET /api/tx/:hash | Single tx + receipt |
| GET /api/address/:addr | Recent activity for address |
| GET /api/token/:addr/holders | ERC-20 holders + balances |
| GET /api/token/:addr/transfers | Recent Transfer events |
| GET /api/token/:addr/stats | Total transfer count |
| GET /api/mempool | Pending-tx snapshot (last 5 min) |
| GET /api/mempool/stream | Server-Sent Events feed of new pending tx |
Production contract addresses are bundled in @aere/sdk. The full list, with read methods, is on the dApp dashboard.
All AERE Network code is hosted at git.aere.network (self-hosted Gitea, GitHub mirror is rate-limited):
@aere/sdk JS/TS client
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.