Skip to main content

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​

MainnetDevnet
Chain id1D
Contract shard11
Paid inUSDC (USDC-c76f1f)USDC (USDC-350c4e)
NetworkContract address
Devneterd1qqqqqqqqqqqqqpgqreqa9d42a754kwr8lzr42qgtpy2evg2uxhpsdwvtkx

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 chainOff chain
What an account bought — tier, cap, period, named-wallet limit, pay-as-you-go priceWhat an account used — counted by the backend
The price, and every price that was ever in forceRate limits and admission policy
The relayer registry and its statesWhich relayer serves which sender right now
The revenue split and the relayer poolLatency, 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.

Cratecorelayer 1.0.0
Frameworkmultiversx-sc 0.66.2
Endpoints55 state-changing, 31 read-only views
Events54
Types73 structs and enums
ABI/abi/corelayer.abi.json

Endpoints · Views · Events · Types

The four roles​

RoleHeld byTemperatureCan
ownerThe deploying wallet. No multisig.Cold — an offline keystore, never on a serverEverything: tariff, tiers, Relay Unit schedule, rate classes, deposit bounds, swap venue, treasury, operator, every unpause, grants, registering relayers, upgrades
operatorA shard-1 walletWarm, human-held, no serverEvery pause; activate, drain, retire and reweight relayers; lower settlement caps; schedule a reporter change
reporterA shard-1 walletHot, inside the backend's signersettleUsage, and nothing else
treasuryThe deployer by defaultColdReceives 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.

ScopeBlocksNever blocks
AllDeposits, subscribing, flags, adding and removing sendersViews, settlement, renewals, releasing escrow, the registry, distribution
DepositsThe three deposit endpointsPurchases from existing credits, flags, settlement, renewals
SettlementsettleUsageRenewals
DistributionDistributing the relayer poolDeposits, which keep accruing
RenewalsThe charging part of an automatic renewal — it charges nothing, writes nothing and does not revertManual purchases, where the buyer states a ceiling

Two entries in that table are constraints on us, not on you:

  • releaseEscrow is 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​

DeployedPaused, with the venue not yet validated, so no deposit can be taken before a deliberate step.
ConfigurationChain 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.
UpgradeRequires every money scope paused. Reverts otherwise.
VerificationPlanned: 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:

ViewAnswers
getConfigChain id, tokens, venue addresses, roles.
getPauseStateWhich scopes are paused.
getEffectiveTariffThe price lever in force right now.
getTariffHistoryEvery tariff that has ever been in force.
getTiersThe full tier ladder as stored.
getAccountAn account's plan, credits and flags.
getActiveRelayers, getRelayerStateWho is allowed to co-sign.
getRegistryVersionA cache key for the two above.
getTotalOutstandingCreditsWhat 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​