diff --git a/frame/ismp-messaging/src/outbound.rs b/frame/ismp-messaging/src/outbound.rs index 9a04b118..6598f89a 100644 --- a/frame/ismp-messaging/src/outbound.rs +++ b/frame/ismp-messaging/src/outbound.rs @@ -62,8 +62,15 @@ pub fn post( let commitment = pallet_ismp::Pallet::::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::(), fee: Default::default(), diff --git a/scripts/hyperbridge/relayer.paseo.toml b/scripts/hyperbridge/relayer.paseo.toml index ae8c9d9c..e43f17e5 100644 --- a/scripts/hyperbridge/relayer.paseo.toml +++ b/scripts/hyperbridge/relayer.paseo.toml @@ -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] @@ -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 = [] diff --git a/template/runtime/src/configs/ismp/mod.rs b/template/runtime/src/configs/ismp/mod.rs index be8d7b12..23de8299 100644 --- a/template/runtime/src/configs/ismp/mod.rs +++ b/template/runtime/src/configs/ismp/mod.rs @@ -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,