The contract
One MultiversX smart contract on shard 1 holds everything that has to be true whether or not CoRelayer's servers are running: the price, the tier ladder, who bought what, the relayer registry and the revenue split.
The reference pages in this section are generated from the contract's build output. A contract starts paused, and each money path opens only when the owner unpauses it.
At a glance
| Mainnet | Devnet | |
|---|---|---|
| Chain id | 1 | D |
| Contract shard | 1 | 1 |
| Paid in | USDC (USDC-c76f1f) | USDC (USDC-350c4e) |
| Network | Contract address |
|---|---|
| Devnet | erd1qqqqqqqqqqqqqpgqreqa9d42a754kwr8lzr42qgtpy2evg2uxhpsdwvtkx |
Each network's API names its contract address in GET /v1/network, and co-relayer.com publishes it
in /.well-known/corelayer.json. Pin the
address in your own configuration: those are copies for convenience, and your pin wins. A
MultiversX round lasts about 600 ms, and the contract counts time in milliseconds throughout.
(Timestamps)
What it is for
The division of labour is deliberate:
| On chain | Off chain |
|---|---|
| What an account bought — tier, cap, period, named-wallet limit, pay-as-you-go price | What an account used — counted by the backend |
| The price, and every price that was ever in force | Rate limits and admission policy |
| The relayer registry and its states | Which relayer serves which sender right now |
| The revenue split and the relayer pool | Latency, incidents, notices |
The contract knows entitlement; the backend counts consumption and reports it back through a settlement call. "Halted" is therefore a backend state, derived from the two.
The contract never sees a relayed transaction. It only ever sees Relay Unit counts.
The build it is generated from
The reference pages in this section come from corelayer.abi.json, the contract crate's own build
artefact, so they say exactly what the code says. Nothing is paraphrased; an endpoint without a doc
comment gets its signature and no prose.
| Crate | corelayer 1.0.0 |
| Framework | multiversx-sc 0.66.2 |
| Endpoints | 55 state-changing, 31 read-only views |
| Events | 54 |
| Types | 73 structs and enums |
| ABI | /abi/corelayer.abi.json |
Endpoints · Views · Events · Types
The four roles
| Role | Held by | Temperature | Can |
|---|---|---|---|
| owner | The deploying wallet. No multisig. | Cold — an offline keystore, never on a server | Everything: tariff, tiers, Relay Unit schedule, rate classes, deposit bounds, swap venue, treasury, operator, every unpause, grants, registering relayers, upgrades |
| operator | A shard-1 wallet | Warm, human-held, no server | Every pause; activate, drain, retire and reweight relayers; lower settlement caps; schedule a reporter change |
| reporter | A shard-1 wallet | Hot, inside the backend's signer | settleUsage, and nothing else |
| treasury | The deployer by default | Cold | Receives its share |
The asymmetry is the point. A stolen operator key can take relayers out of service — a denial of service, and a visible one — but it cannot move the tariff, edit a tier, change the treasury or the swap venue, cannot unpause anything, and cannot register a relayer of its own: every address it can activate was added by the owner first. A stolen reporter key can only report usage, bounded by an escrow and a per-window cap.
Changing the reporter has a delay when the operator does it, and is immediate only for the owner.
The operator's instant incident tool is pauseSettlement(), not a reporter swap.
A role address may not also be a relayer, and the contract enforces that: the sets are disjoint, and the backend's signer refuses to start with a key bundle that violates it.
Pausing
Five independent scopes. Any of them can be paused by the operator or the owner; only the owner can unpause.
| Scope | Blocks | Never blocks |
|---|---|---|
| All | Deposits, subscribing, flags, adding and removing senders | Views, settlement, renewals, releasing escrow, the registry, distribution |
| Deposits | The three deposit endpoints | Purchases from existing credits, flags, settlement, renewals |
| Settlement | settleUsage | Renewals |
| Distribution | Distributing the relayer pool | Deposits, which keep accruing |
| Renewals | The charging part of an automatic renewal — it charges nothing, writes nothing and does not revert | Manual purchases, where the buyer states a ceiling |
Two entries in that table are constraints on us, not on you:
releaseEscrowis never blocked. Seven days after an account turns pay-as-you-go off, anyone may call it to return the unused escrow to that account's credits — so a dead or hostile settlement key can never lock it. We do not have a switch that would stop it.- An upgrade requires all four money scopes paused. Otherwise unverified code would start running on live money paths from the first block after the upgrade.
Deployment and upgrade
| Deployed | Paused, with the venue not yet validated, so no deposit can be taken before a deliberate step. |
| Configuration | Chain id, payment token, wrapped-EGLD token, the exchange pair and wrapper addresses, the initial tariff and the Relay Unit schedule hash — all arguments, never compiled constants. One binary serves both networks. |
| Upgrade | Requires every money scope paused. Reverts otherwise. |
| Verification | Planned: a reproducible build, source verified on the explorer, and a deploy gate that ships to mainnet only the hash that passed the devnet exit criteria. Not done yet — see The ABI and verification. |
Because the configuration is arguments rather than constants, the same wasm runs on devnet and mainnet. And because the deploying wallet is the same on both, the contract address may even coincide — which is exactly why an address is never a network identifier and every client must compare chain ids. (Discovery)
Reading it without asking us
Every view is a free, permissionless call. The ones worth knowing:
| View | Answers |
|---|---|
getConfig | Chain id, tokens, venue addresses, roles. |
getPauseState | Which scopes are paused. |
getEffectiveTariff | The price lever in force right now. |
getTariffHistory | Every tariff that has ever been in force. |
getTiers | The full tier ladder as stored. |
getAccount | An account's plan, credits and flags. |
getActiveRelayers, getRelayerState | Who is allowed to co-sign. |
getRegistryVersion | A cache key for the two above. |
getTotalOutstandingCredits | What is still owed to accounts. |
If a view and our API ever disagree, the chain is right and we have a bug. Please tell us.
Next
- Verifying the deployed bytes: The ABI and verification
- Why everything is in milliseconds: Timestamps
- The generated reference: Endpoints