Skip to content
11 changes: 9 additions & 2 deletions frame/ismp-messaging/src/outbound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,15 @@ pub fn post<T: Config>(
let commitment = pallet_ismp::Pallet::<T>::default()
.dispatch_request(
DispatchRequest::Post(post),
// Zero fee: relayer fees are disabled runtime-wide. A non-zero value would
// escrow funds that only a timeout releases.
// Zero fee, deliberately: Orbinum self-relays, and Hyperbridge's docs call
// that the intended integration — the relayer is paid offchain in BRIDGE
// rather than per-message on-chain. `dispatch_request` skips the transfer
// entirely when the fee is zero, so nothing is escrowed and nobody is owed.
//
// A non-zero fee is what Hyperbridge's permissionless relayer network reads
// to decide whether a message is worth delivering. Setting one only makes
// sense alongside dropping self-relay, and `Currency` would have to stop
// being the native token first — an external relayer cannot sell it.
FeeMetadata {
payer: payer::<T>(),
fee: Default::default(),
Expand Down
10 changes: 10 additions & 0 deletions scripts/hyperbridge/relayer.paseo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ type = "grandpa"
# Hyperbridge is a parachain: its GRANDPA finality comes from the RELAY chain
# (Paseo), not from Hyperbridge itself.
rpc = "wss://pas-rpc.stakeworld.io" # dwellir stopped resolving (2026-08-27)
# Required, not optional: `HostConfig` (tesseract/consensus/grandpa/src/lib.rs:85)
# has no default, so omitting it fails with "missing field `slot_duration`" before
# the relayer connects to anything. 6000 on Paseo; Polkadot mainnet would be 12000.
slot_duration = 6000
# How often to exchange consensus proofs, per the upstream docs.
consensus_update_frequency = 60
# Hyperbridge's para id on Paseo. Listing it is what makes the relayer ship
# proofs that verify Hyperbridge *through* its relay's GRANDPA.
para_ids = [4009]
Expand All @@ -68,6 +74,10 @@ consensus_state_id = "ORBI"
type = "grandpa"
# Orbinum is standalone, so this points at Orbinum itself.
rpc = "wss://rpc-1.testnet.orbinum.io"
# Orbinum's own block time, and the value the runtime whitelists Hyperbridge with
# (`HYPERBRIDGE_SLOT_DURATION_MS`). Required, same as above.
slot_duration = 6000
consensus_update_frequency = 60
# Empty: we are not a relay chain with parachains to prove.
para_ids = []

Expand Down
9 changes: 7 additions & 2 deletions template/runtime/src/configs/ismp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,13 @@ impl pallet_ismp::Config for Runtime {

type OffchainDB = ();

/// `POLICY = false` disables relayer fee charging: `on_executed` returns `Pays::No`
/// before touching balances. Switching it on is a mainnet-economics decision.
/// `POLICY = false` makes message *delivery* free for the submitter: `on_executed`
/// returns `Pays::No` before charging anyone (`fee_handler.rs:172`).
///
/// This is the inbound side, and it is separate from the relayer fee an outbound
/// message carries — that one lives in `FeeMetadata` and is zero because Orbinum
/// self-relays. Turning `POLICY` on would bill whoever submits an inbound message
/// for its execution weight, which is a mainnet-economics decision.
type FeeHandler = pallet_ismp::fee_handler::WeightFeeHandler<
AccountId,
Balances,
Expand Down
Loading