datahaven-xyz/datahaven · error · Error
InvalidGateway
InvalidGateway
Error message
InvalidGateway
What it means
`process_message` throws `Error::InvalidGateway` when the message's `gateway` field does not match the configured `T::GatewayAddress` for the inbound queue. This is a safety check ensuring only messages emitted by the canonical Ethereum Gateway contract are processed; anything else (forged, misconfigured, or from a testnet Gateway) is rejected.
Solutions
- Compare `message.gateway` against the configured GatewayAddress for the target network; re-source the message from the correct chain if they differ.
- Ensure the Ethereum network the relayer listens to matches the Gateway address baked into the runtime; fix the relayer's RPC/contract config.
- If the Gateway address legitimately changed, perform a runtime upgrade updating `T::GatewayAddress`.
Example fix
// before: message from wrong network
let message = Message { gateway: sepolia_gateway, .. };
pallet.process_message(relayer, message)?; // InvalidGateway
// after: assert gateway matches runtime config before processing
assert_eq!(message.gateway, <Runtime as Config>::GatewayAddress::get());
pallet.process_message(relayer, message)?; Defensive patterns
Strategy: validation
Validate before calling
if (message.gateway.toLowerCase() !== expectedGatewayAddress.toLowerCase()) throw new Error('gateway mismatch'); Type guard
function isFromKnownGateway(msg, expected) { return typeof msg.gateway === 'string' && msg.gateway.toLowerCase() === expected.toLowerCase(); } Try / catch
try { pallet.process_message(relayer, message); } catch (e) { if (matches!(e, Error::InvalidGateway)) { logWrongChainMessage(message); skip(); } else { throw e; } } Prevention
- Pin relayer RPC to the chain matching the runtime's GatewayAddress
- Compare gateway address to runtime config before processing
- Update runtime GatewayAddress promptly after contract redeploys
- Alert on any InvalidGateway occurrences as possible wrong-chain feeds
When it happens
Trigger: Calling `process_message(relayer, message)` where `message.gateway` (H160) differs from the pallet constant `T::GatewayAddress::get()` — e.g. a message captured on the wrong Ethereum network or a relayer feeding messages from a fork/mimic contract.
Common situations: Pointing the node at Ethereum testnet (Sepolia) while the runtime is configured for mainnet Gateway address (or vice versa); a relayer replaying messages from a local anvil deployment with a different Gateway contract; runtime config drift after a Gateway contract redeploy without a runtime upgrade.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of datahaven-xyz/datahaven@edcb13dbbc (2026-09-13).
Data as JSON: /api/errors/cd3ad008ac897e49.
Report an issue: GitHub.
Appendix: source
Thrown at operator/pallets/inbound-queue-v2/src/lib.rs:222
/// Halt or resume all pallet operations. May only be called by root.
#[pallet::call_index(1)]
#[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))]
pub fn set_operating_mode(
origin: OriginFor<T>,
mode: BasicOperatingMode,
) -> DispatchResult {
ensure_root(origin)?;
OperatingMode::<T>::set(mode);
Self::deposit_event(Event::OperatingModeChanged { mode });
Ok(())
}
}
impl<T: Config> Pallet<T> {
pub fn process_message(relayer: T::AccountId, message: Message) -> DispatchResult {
// Verify that the message was submitted from the known Gateway contract
ensure!(
T::GatewayAddress::get() == message.gateway,
Error::<T>::InvalidGateway
);
let (nonce, relayer_fee) = (message.nonce, message.relayer_fee);
// Verify the message has not been processed
ensure!(!Nonce::<T>::get(nonce.into()), Error::<T>::InvalidNonce);
// Process message
let message_id = T::MessageProcessor::process_message(relayer.clone(), message)?;
// Pay relayer reward if needed
if !relayer_fee.is_zero() {
T::RewardPayment::register_reward(
&relayer,
T::DefaultRewardKind::get(),
relayer_fee,View on GitHub (pinned to edcb13dbbc)