This repo is a CEX-onboarding-oriented compatibility harness for Ethereum JSON-RPC surfaces.
It does not pretend to mathematically "guarantee" production readiness. What it does is give you a release-gate harness that exercises the failure modes that actually matter for centralized exchanges:
- raw JSON-RPC request/response semantics
- configured chain identity matching
ethersprovider compatibilityviempublic-client compatibilityweb3.pycompatibilitycastcompatibility- ERC20-style
eth_callprobes across major client paths - transaction lookup and receipt semantics
- transfer log indexing and address/topic-scoped
eth_getLogs - address/topic-scoped filter lifecycle
- active EOA-style and ERC20-style transfers in full mode
Wallets are a weak signal. MetaMask can work while exchange middleware still breaks on:
eth_getTransactionByHasheth_getTransactionReceipteth_getLogseth_newFilter/eth_getFilterChanges- block walking by number and index
- ABI-decoded
eth_call - client-library assumptions in
ethers,viem, or backend scripts
This harness tests those directly.
The harness currently exercises the same endpoint through five paths:
- raw JSON-RPC over HTTP
castviemethersweb3.pywith standard PoA middleware
The Python path is not just an example script. Its results are merged into the same readiness report.
Useful for smoke testing an endpoint without a funded test key.
This mode checks:
EXPECTED_CHAIN_IDagainst the target endpoint- chain metadata
- latest block lookup
- pseudo-contract
eth_getCode - raw JSON-RPC 2.0 envelope semantics, including id echoing, method-not-found, malformed-filter, and null-vs-error behavior
- ERC20 reads:
name,symbol,decimals,totalSupply,balanceOf - the same standard ERC20 probe set through
ethersandcast - unknown tx / receipt / block / by-index null semantics
ethersandviemlatest-block andgetLogscompatibilitycastchain / block /getLogs/eth_callcompatibility- address/topic-scoped filter lifecycle and uninstall behavior
Read-only mode is not enough to claim exchange readiness.
This is the actual readiness gate.
In addition to read-only checks, it:
- sends an EOA-style transfer
- sends an ERC20-style transfer through the pseudo-contract
- verifies the first receipt poll after submission returns either
nullor an already-mined receipt - waits for receipts
- verifies transaction lookup by hash
- verifies transaction and receipt field shape as clients see them
- verifies transfer log presence and decodability
- verifies address/topic-scoped
eth_getLogsrange queries - verifies address/topic-scoped
eth_getFilterChangesandeth_getFilterLogsdeliver the live transfer - verifies block transaction enumeration and by-index lookup
- verifies missing by-index lookups return null
- re-reads txs, receipts, logs, blocks, and ERC20 state through
ethers,viem,cast, andweb3.py
npm installFor the Python suite:
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r python/requirements.txtYou can configure the harness via environment variables or a JSON config file.
Example files:
config.read-only.example.jsonconfig.full.example.json
RPC_URL=http://127.0.0.1:50002 \
EXPECTED_CHAIN_ID=1234 \
npm run checkRPC_URL=http://127.0.0.1:50002 \
EXPECTED_CHAIN_ID=1234 \
PRIVATE_KEY=0x... \
EOA_RECIPIENT=0x... \
ERC20_RECIPIENT=0x... \
npm run check -- --mode fullEXPECTED_CHAIN_IDrequired; the harness aborts immediately ifeth_chainIddoes not matchEXPECTED_NAMEdefault:CanopyEXPECTED_SYMBOLdefault:CNPYEXPECTED_DECIMALSdefault:6CAST_BINARYdefault:castPYTHON_BINARYdefault:python3unless.venv/bin/pythonexistsREPORT_DIRdefault:./reportsPOLL_INTERVAL_MSdefault:1500TX_TIMEOUT_MSdefault:120000EOA_AMOUNT_WEIdefault:1000000000000ERC20_AMOUNT_UNITSdefault:1MAX_FEE_PER_GAS_WEIMAX_PRIORITY_FEE_PER_GAS_WEI
0: all required checks passed for the selected mode1: at least one required check failed, or full mode was incomplete
Each run prints a human-readable summary and writes a JSON report under reports/.
That report is intended to be the artifact you keep for release reviews.