{"record":{"id":"cd3ad008ac897e49","repo":"datahaven-xyz/datahaven","slug":"invalidgateway","errorCode":"InvalidGateway","errorMessage":"InvalidGateway","messagePattern":"InvalidGateway","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"operator/pallets/inbound-queue-v2/src/lib.rs","lineNumber":222,"sourceCode":"\n        /// Halt or resume all pallet operations. May only be called by root.\n        #[pallet::call_index(1)]\n        #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))]\n        pub fn set_operating_mode(\n            origin: OriginFor<T>,\n            mode: BasicOperatingMode,\n        ) -> DispatchResult {\n            ensure_root(origin)?;\n            OperatingMode::<T>::set(mode);\n            Self::deposit_event(Event::OperatingModeChanged { mode });\n            Ok(())\n        }\n    }\n\n    impl<T: Config> Pallet<T> {\n        pub fn process_message(relayer: T::AccountId, message: Message) -> DispatchResult {\n            // Verify that the message was submitted from the known Gateway contract\n            ensure!(\n                T::GatewayAddress::get() == message.gateway,\n                Error::<T>::InvalidGateway\n            );\n\n            let (nonce, relayer_fee) = (message.nonce, message.relayer_fee);\n\n            // Verify the message has not been processed\n            ensure!(!Nonce::<T>::get(nonce.into()), Error::<T>::InvalidNonce);\n\n            // Process message\n            let message_id = T::MessageProcessor::process_message(relayer.clone(), message)?;\n\n            // Pay relayer reward if needed\n            if !relayer_fee.is_zero() {\n                T::RewardPayment::register_reward(\n                    &relayer,\n                    T::DefaultRewardKind::get(),\n                    relayer_fee,","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/datahaven-xyz/datahaven/blob/edcb13dbbcd3c29489eaa2480a6f60ee4cb1f3ec/operator/pallets/inbound-queue-v2/src/lib.rs#L204-L240","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","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`."],"exampleFix":"// before: message from wrong network\nlet message = Message { gateway: sepolia_gateway, .. };\npallet.process_message(relayer, message)?; // InvalidGateway\n\n// after: assert gateway matches runtime config before processing\nassert_eq!(message.gateway, <Runtime as Config>::GatewayAddress::get());\npallet.process_message(relayer, message)?;","handlingStrategy":"validation","validationCode":"if (message.gateway.toLowerCase() !== expectedGatewayAddress.toLowerCase()) throw new Error('gateway mismatch');","typeGuard":"function isFromKnownGateway(msg, expected) { return typeof msg.gateway === 'string' && msg.gateway.toLowerCase() === expected.toLowerCase(); }","tryCatchPattern":"try { pallet.process_message(relayer, message); } catch (e) { if (matches!(e, Error::InvalidGateway)) { logWrongChainMessage(message); skip(); } else { throw e; } }","preventionTips":["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"],"tags":["substrate","bridge","gateway-address","relayer","chain-mismatch"],"backgroundTag":"invalid-argument-value","analyzedSha":"edcb13dbbcd3c29489eaa2480a6f60ee4cb1f3ec","analyzedAt":"2026-09-13T19:19:32.206Z","contentChangedAt":"2026-09-13T19:19:32.206Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}