Skip to main content

pallet-relayer Reference

The on-chain surface behind Relay Setup & Fees. For the operator walkthrough, start there.


Extrinsics

IndexExtrinsicOriginPurpose
0set_min_relay_fee(fee)ManageOrigin (sudo / gov)Adjusts the minimum fee required in ZK proofs. Capped by MaxMinRelayFee
1set_allowed_selectors(selectors)ManageOriginPublishes the selector list for off-chain relay services
2register_relayer(evm_address, signature)Validator (signed)Binds H160 → AccountId. Requires active-set membership and a signature proving you hold the key
3unregister_relayer()Validator (signed)Removes your own binding. Takes no arguments

register_relayer checks in this order — the first failure is the error you see:

  1. caller is an active validatorNotValidator
  2. the address is usable → InvalidEvmAddress
  3. the signature proves ownership → BadEvmSignature
  4. the H160 is not already bound → AlreadyRegistered
  5. your account has no binding yet → AccountAlreadyRegistered
Unregistering does not stop all fees

A validator that unregisters stops receiving fees resolved through the registry, but still receives them as block author when no relayer resolves. To stop entirely, stop authoring.

set_allowed_selectors is advisory

The list is published for off-chain relay services to read via relay_config(). It is not enforced by the runtime and does not restrict what can be relayed.


Events

relayer

EventMeaning
RelayFeeAccumulated { relayer, asset_id, amount }Fired on every relayed operation — the one to watch for fee telemetry
RelayFeesConsumed { relayer, asset_id, amount }Fees deducted from the pending balance (the claim step)
RelayerRegistered { evm_address, account }Registration completed
RelayerUnregistered { evm_address, account }Binding removed
MinRelayFeeUpdated { new_fee }Governance changed the minimum — wallets should adjust
AllowedSelectorsUpdated { count }Selector list republished

shieldedPool

Fee attribution is decided in the shielded pool, so these three live there — not in relayer. In Polkadot-JS look under shieldedPool.*:

EventMeaning
RelayFeeDiverted { requested, credited, asset_id, amount }A relayer address was named but did not resolve; the block author was credited instead
SelfRelayedFee { author, asset_id, amount }The resolved relayer was the block author
ValidatorFeesClaimed { validator, asset_id, amount, commitment, leaf_index }Claimed fees arrived as a private note

SelfRelayedFee is not an accusation. With N authors in rotation it occurs about 1/N of the time on its own; only a rate sustained well above that is meaningful, and adjudication is off-chain.


Errors

ErrorCause
NotValidatorRegistering from an account that is not in the active set
InvalidEvmAddressThe address cannot be used as a relay address
BadEvmSignatureThe ownership proof does not verify
AlreadyRegisteredThat H160 already belongs to another account
AccountAlreadyRegisteredThis account already has an address — unregister first. Hit when rotating keys
NotRegisteredunregister_relayer from an account with no registration
InsufficientPendingFeesClaiming more than the pending balance
TooManySelectorsMore than 16 selectors passed
MinRelayFeeTooHighFee above MaxMinRelayFee
NotValidator exists in two pallets

relayer.NotValidator means "you are not in the active set, so you cannot register". validatorSet.NotValidator means "this account is not a validator" on a removal call. Same name, different pallet.


Storage

ItemShape
RelayerRegistryH160 → AccountId
RelayerByAccountAccountId → H160 (reverse index)
PendingRelayerFees(AccountId, asset_id) → u128, in planck
MinRelayFeeu128
AllowedSelectorsbounded list, max 16

Leaving the validator set clears your binding but not your fees. PendingRelayerFees is untouched by removal and stays claimable.


RPC methods

relayer_isRelayer(evm_address)              → bool
relayer_pendingFees(account, asset_id) → u128 ← unclaimed balance
relayer_registeredEvmAddress(account) → Option<H160>

@orbinum/protocol wraps these as client.relayerStatus.