diff --git a/Cargo.lock b/Cargo.lock
index 2e60b28f40e1..daf7be7e5452 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2069,6 +2069,7 @@ dependencies = [
"snowbridge-rococo-common",
"snowbridge-router-primitives",
"snowbridge-runtime-common",
+ "snowbridge-runtime-test-common",
"snowbridge-system",
"snowbridge-system-runtime-api",
"sp-api",
@@ -17249,7 +17250,7 @@ dependencies = [
[[package]]
name = "snowbridge-beacon-primitives"
-version = "0.0.1"
+version = "0.9.0"
dependencies = [
"byte-slice-cast",
"frame-support",
@@ -17272,7 +17273,7 @@ dependencies = [
[[package]]
name = "snowbridge-core"
-version = "0.1.1"
+version = "0.9.0"
dependencies = [
"ethabi-decode",
"frame-support",
@@ -17294,7 +17295,7 @@ dependencies = [
[[package]]
name = "snowbridge-ethereum"
-version = "0.1.0"
+version = "0.9.0"
dependencies = [
"ethabi-decode",
"ethbloom",
@@ -17315,7 +17316,7 @@ dependencies = [
[[package]]
name = "snowbridge-ethereum-beacon-client"
-version = "0.0.1"
+version = "0.9.0"
dependencies = [
"bp-runtime",
"byte-slice-cast",
@@ -17343,7 +17344,7 @@ dependencies = [
[[package]]
name = "snowbridge-inbound-queue"
-version = "0.1.1"
+version = "0.9.0"
dependencies = [
"alloy-primitives",
"alloy-rlp",
@@ -17372,7 +17373,7 @@ dependencies = [
[[package]]
name = "snowbridge-outbound-queue"
-version = "0.1.1"
+version = "0.9.0"
dependencies = [
"bridge-hub-common",
"ethabi-decode",
@@ -17395,7 +17396,7 @@ dependencies = [
[[package]]
name = "snowbridge-outbound-queue-merkle-tree"
-version = "0.1.1"
+version = "0.9.0"
dependencies = [
"parity-scale-codec",
"scale-info",
@@ -17405,7 +17406,7 @@ dependencies = [
[[package]]
name = "snowbridge-outbound-queue-runtime-api"
-version = "0.1.0"
+version = "0.9.0"
dependencies = [
"frame-support",
"parity-scale-codec",
@@ -17419,7 +17420,7 @@ dependencies = [
[[package]]
name = "snowbridge-rococo-common"
-version = "0.0.1"
+version = "0.9.0"
dependencies = [
"frame-support",
"log",
@@ -17428,7 +17429,7 @@ dependencies = [
[[package]]
name = "snowbridge-router-primitives"
-version = "0.1.1"
+version = "0.9.0"
dependencies = [
"ethabi-decode",
"frame-support",
@@ -17450,7 +17451,7 @@ dependencies = [
[[package]]
name = "snowbridge-runtime-common"
-version = "0.1.1"
+version = "0.9.0"
dependencies = [
"frame-support",
"frame-system",
@@ -17462,9 +17463,82 @@ dependencies = [
"staging-xcm-executor",
]
+[[package]]
+name = "snowbridge-runtime-test-common"
+version = "0.9.0"
+dependencies = [
+ "assets-common",
+ "cumulus-pallet-aura-ext",
+ "cumulus-pallet-dmp-queue",
+ "cumulus-pallet-parachain-system",
+ "cumulus-pallet-session-benchmarking",
+ "cumulus-pallet-xcm",
+ "cumulus-pallet-xcmp-queue",
+ "cumulus-primitives-core",
+ "cumulus-primitives-utility",
+ "frame-benchmarking",
+ "frame-executive",
+ "frame-support",
+ "frame-system",
+ "frame-system-benchmarking",
+ "frame-system-rpc-runtime-api",
+ "frame-try-runtime",
+ "hex-literal",
+ "log",
+ "pallet-aura",
+ "pallet-authorship",
+ "pallet-balances",
+ "pallet-collator-selection",
+ "pallet-message-queue",
+ "pallet-multisig",
+ "pallet-session",
+ "pallet-timestamp",
+ "pallet-transaction-payment",
+ "pallet-transaction-payment-rpc-runtime-api",
+ "pallet-utility",
+ "pallet-xcm",
+ "pallet-xcm-benchmarks",
+ "parachains-common",
+ "parachains-runtimes-test-utils",
+ "parity-scale-codec",
+ "polkadot-core-primitives",
+ "polkadot-parachain-primitives",
+ "polkadot-runtime-common",
+ "scale-info",
+ "serde",
+ "smallvec",
+ "snowbridge-beacon-primitives",
+ "snowbridge-core",
+ "snowbridge-ethereum-beacon-client",
+ "snowbridge-inbound-queue",
+ "snowbridge-outbound-queue",
+ "snowbridge-outbound-queue-runtime-api",
+ "snowbridge-router-primitives",
+ "snowbridge-system",
+ "snowbridge-system-runtime-api",
+ "sp-api",
+ "sp-block-builder",
+ "sp-consensus-aura",
+ "sp-core",
+ "sp-genesis-builder",
+ "sp-inherents",
+ "sp-io",
+ "sp-offchain",
+ "sp-runtime",
+ "sp-session",
+ "sp-std 8.0.0",
+ "sp-storage 13.0.0",
+ "sp-transaction-pool",
+ "sp-version",
+ "staging-parachain-info",
+ "staging-xcm",
+ "staging-xcm-builder",
+ "staging-xcm-executor",
+]
+
[[package]]
name = "snowbridge-system"
-version = "0.1.1"
+version = "0.9.0"
dependencies = [
"ethabi-decode",
"frame-benchmarking",
@@ -17485,7 +17559,7 @@ dependencies = [
[[package]]
name = "snowbridge-system-runtime-api"
-version = "0.1.0"
+version = "0.9.0"
dependencies = [
"parity-scale-codec",
"snowbridge-core",
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml
index f664017b0e5e..474bd124d999 100644
--- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml
@@ -128,6 +128,7 @@ bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", fe
"integrity-test",
] }
sp-keyring = { path = "../../../../../substrate/primitives/keyring" }
+snowbridge-runtime-test-common = { path = "../../../../../../parachain/runtime/test-common" }
[features]
default = ["std"]
@@ -257,6 +258,7 @@ runtime-benchmarks = [
"snowbridge-rococo-common/runtime-benchmarks",
"snowbridge-router-primitives/runtime-benchmarks",
"snowbridge-runtime-common/runtime-benchmarks",
+ "snowbridge-runtime-test-common/runtime-benchmarks",
"snowbridge-system/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs
new file mode 100644
index 000000000000..8c6d61842b6f
--- /dev/null
+++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/snowbridge.rs
@@ -0,0 +1,109 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Cumulus is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Cumulus. If not, see .
+
+#![cfg(test)]
+
+use bridge_hub_rococo_runtime::{
+ xcm_config::XcmConfig, MessageQueueServiceWeight, Runtime, RuntimeEvent, SessionKeys,
+};
+use codec::Decode;
+use cumulus_primitives_core::XcmError::{FailedToTransactAsset, NotHoldingFees};
+use frame_support::parameter_types;
+use parachains_common::{AccountId, AuraId, Balance};
+use snowbridge_ethereum_beacon_client::WeightInfo;
+use sp_core::H160;
+use sp_keyring::AccountKeyring::Alice;
+
+parameter_types! {
+ pub const DefaultBridgeHubEthereumBaseFee: Balance = 2_750_872_500_000;
+}
+
+fn collator_session_keys() -> bridge_hub_test_utils::CollatorSessionKeys {
+ bridge_hub_test_utils::CollatorSessionKeys::new(
+ AccountId::from(Alice),
+ AccountId::from(Alice),
+ SessionKeys { aura: AuraId::from(Alice.public()) },
+ )
+}
+
+#[test]
+pub fn transfer_token_to_ethereum_works() {
+ snowbridge_runtime_test_common::send_transfer_token_message_success::(
+ collator_session_keys(),
+ 1013,
+ 1000,
+ H160::random(),
+ H160::random(),
+ DefaultBridgeHubEthereumBaseFee::get(),
+ Box::new(|runtime_event_encoded: Vec| {
+ match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) {
+ Ok(RuntimeEvent::EthereumOutboundQueue(event)) => Some(event),
+ _ => None,
+ }
+ }),
+ )
+}
+
+#[test]
+pub fn unpaid_transfer_token_to_ethereum_fails_with_barrier() {
+ snowbridge_runtime_test_common::send_unpaid_transfer_token_message::(
+ collator_session_keys(),
+ 1013,
+ 1000,
+ H160::random(),
+ H160::random(),
+ )
+}
+
+#[test]
+pub fn transfer_token_to_ethereum_fee_not_enough() {
+ snowbridge_runtime_test_common::send_transfer_token_message_failure::(
+ collator_session_keys(),
+ 1013,
+ 1000,
+ DefaultBridgeHubEthereumBaseFee::get() + 1_000_000_000,
+ H160::random(),
+ H160::random(),
+ // fee not enough
+ 1_000_000_000,
+ NotHoldingFees,
+ )
+}
+
+#[test]
+pub fn transfer_token_to_ethereum_insufficient_fund() {
+ snowbridge_runtime_test_common::send_transfer_token_message_failure::(
+ collator_session_keys(),
+ 1013,
+ 1000,
+ 1_000_000_000,
+ H160::random(),
+ H160::random(),
+ DefaultBridgeHubEthereumBaseFee::get(),
+ FailedToTransactAsset("InsufficientBalance"),
+ )
+}
+
+#[test]
+fn max_message_queue_service_weight_is_more_than_beacon_extrinsic_weights() {
+ let max_message_queue_weight = MessageQueueServiceWeight::get();
+ let force_checkpoint =
+ ::WeightInfo::force_checkpoint();
+ let submit_checkpoint =
+ ::WeightInfo::submit();
+ max_message_queue_weight.all_gt(force_checkpoint);
+ max_message_queue_weight.all_gt(submit_checkpoint);
+}