Ethereum
| Slug | eth |
| Address format | EIP-55 checksummed hex, 0x… |
| Account path | m/44'/60'/0' |
| Cloud stores | xpub |
| Derivation | ✅ M/0/{i} — public, no Edge required |
| Confirmations | 12 |
| Tokens | ERC-20 |
| Explorer | https://etherscan.io/tx/{txid} · https://etherscan.io/address/{address} |
One address across the EVM chains
Ethereum, BSC, Polygon, Avalanche and Base all use coin type 60', so one extended public key
serves all five and one address receives on all five.
Issue it once per customer:
curl -X POST $EDGE/addresses \
-H "X-API-Key: $CHAINOS_EDGE_KEY" \
-H "Idempotency-Key: addr-cust_88213-evm" \
-d '{ "chain": "eth", "userRef": "cust_88213" }'
That address receives ETH and ERC-20 on Ethereum, BNB and BEP-20 on BSC, POL and ERC-20 on
Polygon, and AVAX and ERC-20 on Avalanche. A deposit arriving on BSC to an address you created with
"chain": "eth" is still that customer's deposit; the webhook's chain field tells you which
network it landed on.
It works, in the sense that all five are valid — but they are five distinct addresses at five distinct indices, they count four times against your active-address quota, and your customer now has four "Ethereum-family" addresses to be confused by.
Issue for eth and use it on all five. Tell your customer which networks it accepts.
TRON and XRP do not share this path. See HD derivation.
Avalanche shares the address and nothing else. It is a separate L1 rather than an Ethereum network: its gas is paid in AVAX, and one confirmation there is final rather than probable. See Avalanche.
Base shares the address and the asset — its native token is ETH too — and is still a different chain with a different balance. It is an OP-Stack rollup, so its confirmation waits for Ethereum to finalize the batch (roughly half an hour) and its fee carries a second, L1 component. It is the easiest of the four to mistake for Ethereum itself. See Base.
Confirmations
Twelve. This is the standard margin for post-Merge PoS: a reorg deeper than a couple of blocks requires a consensus failure rather than ordinary luck, and twelve blocks is roughly two and a half minutes.
deposit_detected fires at 1, deposit_confirmed at 12. Credit on the second.
Fees — EIP-1559
fee = gasUnits × (baseFee × 2 + priorityFee)
| Field | |
|---|---|
baseFeeGwei | The current block's base fee, burned |
priorityFeeGwei | The tip to the proposer |
maxFeeGwei | What the build sets as the ceiling |
gasUnits | 21,000 for a plain transfer; roughly 45,000–65,000 for an ERC-20 |
The baseFee × 2 headroom is deliberate: the base fee can rise up to 12.5% per block, so a
transaction priced at exactly the current base fee will not be included if the next block is fuller.
Doubling gives about six blocks of margin. You are only charged the actual base fee at inclusion
time — the ceiling is a ceiling, not a price.
INSUFFICIENT_GAS is the error you will see most
The fee must be paid in ETH, by the sending address. An ERC-20 deposit address holds tokens and no ETH — because your customer sent you USDT and nobody sent you ETH. That is the default state of every ERC-20 deposit address, not an unusual one.

Plan for it in your design rather than treating it as an error path. A token sweep is a two-pass job: collect the addresses that need gas, fund them, sweep on the next pass. See Sweeps.
ERC-20 tokens
Monitored contracts on mainnet:
| Token | Contract | Decimals |
|---|---|---|
| USDT | 0xdAC17F958D2ee523a2206206994597C13D831ec7 | 6 |
| USDC | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 | 6 |
| RLUSD | 0x8292Bb45bf1Ee4d140127049757C2E0fF06317eD | 18 |
| PYUSD | 0x6c3ea9036406852006290770BEdFcAbA0e23A0e8 | 6 |
| EURC | 0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c | 6 |
| cNGN | 0x17CDB2a01e7a34CbB3DD4b83260B05d0274C8dab | 6 |
| DAI | 0x6B175474E89094C44Da98b954EedeAC495271d0F | 18 |
| FDUSD | 0xc5f0f7b66764F6ec8C8Dff7BA683102295E16409 | 18 |
| USDD | 0x4f8e5DE400DE08B164E7421B3EE387f461beCD1A | 18 |
Branch on tokenContract, never on tokenSymbol. Anyone can deploy a contract that calls
itself USDT, and several have. The contract address is the identity; the symbol is a label the
contract chose for itself.
{ "amount": "1000000", "amountFormatted": "1.00", "decimals": 6,
"tokenSymbol": "USDT",
"tokenContract": "0xdAC17F958D2ee523a2206206994597C13D831ec7" }
Note the decimals: USDT and USDC on Ethereum are 6, not 18. "1000000" is one dollar. The same
tokens on BSC are 18 — see BSC. Read decimals from the payload rather than
assuming per token, and per chain rather than per symbol: the contract addresses differ on every
one of the four networks this address receives on.
A deposit of a token ChainOS does not monitor produces no webhook. The funds are at your address and recoverable from your mnemonic; they are simply not tracked. To add a contract, ask — the adapter takes a list per logical symbol.
Balances
{ "confirmed": "1000000000000000000", "available": "1000000000000000000",
"reserved": "0", "decimals": 18 }
available == confirmed on Ethereum. Nothing is immobilised — that is an XRP, Solana and Stellar
concern.
"1000000000000000000" is 1 ETH, as a string, because 10^18 does not survive a JavaScript
Number. See API conventions.
Operational notes
- Reverted transactions still cost the fee. An EVM transaction can be mined and revert;
withdrawal_failedfires and the gas is spent. Do not treat a failure as a free retry. - Nonce management is Cloud's. Nonces are assigned at build time. If two withdrawals from one address are built concurrently, the second waits — the API serialises per address rather than issuing two transactions with the same nonce and letting one silently replace the other.
- Contract destinations are not special-cased. A withdrawal to a contract address succeeds if
the contract accepts it. ChainOS does not simulate the call, so a destination whose receive hook
reverts produces
withdrawal_failedafter the fee is spent. Validate destinations withPOST /v1/addresses/validate, which checks the format — it cannot check the behaviour. - Gas spikes are visible as
maxFeeGweiclimbing in a fee estimate. There is nothing to fix, but a withdrawal queue that ignores the estimate will price transactions your customers did not agree to.