Docs · RPC compatibility
Ethereum / EVM-Compatible RPC
Point ethers.js, web3.js and MetaMask at an
Animica node and they connect through familiar eth_* / net_* /
web3_* methods. This is an Ethereum RPC-compatible facade, with a path
toward full EVM execution — Animica stays its own post-quantum PoIES useful-work L1.
RPC facade, not EVM execution. Animica does not run Solidity bytecode. Read this as “Ethereum tooling can connect,” not “Animica is EVM-compatible” — the latter is only true once Solidity deployment/execution ships (a future phase).
Connect
Ethereum clients POST JSON-RPC. Methods answer at both / and /rpc.
The public mainnet endpoint is https://mainnet.animica.org .
# curl
curl -s https://mainnet.animica.org/ \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'
# -> {"jsonrpc":"2.0","id":1,"result":"0x95"} (chain id 149)
# ethers v6
import { JsonRpcProvider } from "ethers";
const provider = new JsonRpcProvider("https://mainnet.animica.org");
await provider.getBlockNumber();
# web3.py
from web3 import Web3
w3 = Web3(Web3.HTTPProvider("https://mainnet.animica.org"))
w3.is_connected(); w3.eth.chain_id # 149
w3.eth.block_number; w3.eth.get_block("latest") Add Animica to a wallet
MetaMask → Add network → Add a network manually, then use:
| Network name | Animica |
| RPC URL | https://mainnet.animica.org |
| Chain ID | 149 |
| Currency symbol | ANM |
| Decimals | 9 (1 ANM = 1e9 nANM) |
| Block explorer | https://explorer.animica.org |
Chain id 149 is the lowest unregistered EIP-155 id (Ethereum mainnet is 1, which would collide). It is registered with ethereum-lists/chains , which feeds chainid.network and chainlist.org. The native currency uses 9 decimals (nANM is the wei-style smallest unit).
Implemented methods
40 methods across eight groups.
eth_chainIdnet_versionnet_listeningnet_peerCountweb3_clientVersionweb3_sha3eth_blockNumbereth_syncingeth_protocolVersioneth_miningeth_hashrateeth_coinbase eth_getBlockByNumbereth_getBlockByHasheth_getBlockTransactionCountByNumbereth_getBlockTransactionCountByHash eth_getBalanceeth_getTransactionCounteth_getCodeeth_getStorageAteth_accounts eth_getTransactionByHasheth_getTransactionReceipteth_getTransactionByBlockNumberAndIndex eth_gasPriceeth_maxPriorityFeePerGaseth_feeHistoryeth_estimateGaseth_call eth_getLogseth_newFiltereth_newBlockFiltereth_newPendingTransactionFiltereth_uninstallFiltereth_getFilterChangeseth_getFilterLogs eth_sendRawTransactioneth_sendTransactioneth_sign animica_evmBindanimica_evmAlias How the mapping works
| Ethereum method | Animica source |
| eth_chainId / net_version | dedicated EVM id 149 (override ANIMICA_EVM_CHAIN_ID) |
| eth_blockNumber | chain.getHead().height → hex |
| eth_getBlockBy{Number,Hash} | chain.getBlockByHeight / …ByHash → Ethereum block shape |
| eth_getBalance | state.getBalance (nANM as the wei-style smallest unit) |
| eth_getTransactionCount | state.getNonce / getPendingNonce |
| eth_getTransactionByHash / …Receipt | tx.getTransactionByHash (+ tx.getTransactionStatus) |
| eth_gasPrice / eth_estimateGas | synthetic — Animica fee is account-model, not a gas market |
| web3_sha3 | real keccak-256 (eth_utils) |
Hex encoding is strict Ethereum: QUANTITY is 0x-compact (0x0 for zero),
DATA is 0x with even length. Animica 0x+64-hex hashes pass through as
32-byte hashes.
The address & signature boundary
Ethereum assumes 20-byte 0x addresses and secp256k1 ECDSA. Animica is post-quantum
(anim1…, ML-DSA / SPHINCS+). The facade bridges the two:
Every Animica account has a 20-byte EVM alias = 0x ‖ keccak256(anim1)[-20:], with
a binding registry so eth_getBalance(0xalias) resolves back.
animica_evmAlias(anim1) returns the alias; animica_evmBind records it.
An alias is a display/lookup handle — not key-compatibility.
Set ANIMICA_EVM_RELAYER=1 and eth_sendRawTransaction becomes a working
bridge: each EVM address gets a relayer-held native account A(E); an EVM signature
authorizes a native transfer from it. Fund A(E) (via animica_evmAccount),
then send normally. Custodial (operator holds the keys); off by default.
What works vs. what doesn't
- MetaMask "Add network" and EIP-1193 provider connect
- ethers.js / web3.js provider connect (JsonRpcProvider, Web3)
- eth_blockNumber, block / tx / receipt lookups
- eth_getBalance & eth_getTransactionCount for bridged addresses
- ANM as an ERC-20 (Import token 0xbb22…00af): name/symbol/decimals/balanceOf
- Real Solidity deploy + execute with ANIMICA_EVM_EXECUTION=1 (node-local EVM)
- explorer & indexer read traffic; web3_sha3 (real keccak-256)
- PoIES-consensus-validated EVM — execution is node-local sequencer state, not yet re-validated by all validators
- ANM-metered gas + payable value forwarding (v1: gas sponsored, msg.value must be 0)
- Native Animica (Python-VM) contracts via eth_call — those use the native ABI, not EVM
Roadmap
- EVM RPC facade (shipped) —
eth_*connect + read. - Custodial relayer (shipped) —
ANIMICA_EVM_RELAYER=1moves value between EVM and native Animica via managed accounts. - ERC facade (shipped) — ANM presented as a read-only ERC-20
(
eth_call); real Solidity ERC-20/721 deploy + run on the execution lane. - EVM execution lane (shipped, node-local) —
ANIMICA_EVM_EXECUTION=1runs real Solidity. Next: PoIES re-validation (consensus-level EVM), ANM-metered gas, payable value forwarding.
FAQ
Is Animica EVM-compatible?
Animica exposes an Ethereum RPC-compatible facade, with a path toward full EVM execution. Ethereum tooling (ethers, web3, MetaMask, explorers) can connect through familiar eth_* methods. But Animica does NOT run Solidity bytecode — it stays its own post-quantum PoIES useful-work L1. "EVM-compatible" in the full sense (deploy & execute Solidity) is a future phase, not today.
What chain id does Animica use for EVM?
Chain id 149 (0x95) for eth_chainId / net_version — the lowest unregistered EIP-155 id. Animica's native chain id stays 1 internally; the facade advertises a dedicated id so it doesn't collide with Ethereum mainnet (also 1) in wallet chain-lists. Override with ANIMICA_EVM_CHAIN_ID.
How do Ethereum 0x addresses map to Animica anim1 accounts?
Every Animica account gets a deterministic 20-byte EVM alias = 0x ‖ keccak256(anim1)[-20:], with a binding registry so eth_getBalance(0xalias) resolves back. An alias is a display/lookup handle, not key-compatibility — a secp256k1 key cannot control an anim1 (ML-DSA/SPHINCS+) account.
Can I send a transaction from MetaMask?
Yes, when the node operator enables the custodial relayer (ANIMICA_EVM_RELAYER=1). Each EVM address maps to a relayer-held native account A(E); you fund A(E) (animica_evmAccount returns its anim1), then sign a normal EVM tx and eth_sendRawTransaction moves ANM natively from A(E). It is custodial (the operator holds the keys) and enforces chainId 149, monotonic nonces, replay protection, and AES-256-GCM key-at-rest. With the relayer off, sends return a clear -32004 instead of failing silently.
See also: Bitcoin-Core-Compatible RPC · All docs · EVM_RPC_COMPAT.md