diff --git a/Cargo.lock b/Cargo.lock index 08a18c13b6f43..0a972bc03e70f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25285,10 +25285,10 @@ dependencies = [ "log", "pallet-timestamp 39.0.0-rc1", "parity-scale-codec", - "rand 0.8.5", "scale-info", "serde", "serde_json", +<<<<<<< HEAD "snowbridge-beacon-primitives 0.13.0-rc1", "snowbridge-core 0.13.0-rc1", "snowbridge-ethereum 0.11.0", @@ -25297,6 +25297,16 @@ dependencies = [ "sp-core 35.0.1-rc1", "sp-io 39.0.1-rc1", "sp-runtime 40.2.0-rc1", +======= + "snowbridge-beacon-primitives", + "snowbridge-core", + "snowbridge-ethereum", + "snowbridge-pallet-ethereum-client-fixtures", + "snowbridge-verification-primitives", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", +>>>>>>> 0f3f611 (Snowbridge - Various minor improvements (#8020)) "sp-std 14.0.0", "static_assertions", ] @@ -25308,6 +25318,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3984b98465af1d862d4e87ba783e1731f2a3f851b148d6cb98d526cebd351185" dependencies = [ "hex-literal", +<<<<<<< HEAD "snowbridge-beacon-primitives 0.10.1", "snowbridge-core 0.10.0", "sp-core 34.0.0", @@ -25323,6 +25334,12 @@ dependencies = [ "snowbridge-core 0.13.0-rc1", "snowbridge-inbound-queue-primitives", "sp-core 35.0.1-rc1", +======= + "snowbridge-beacon-primitives", + "snowbridge-core", + "snowbridge-verification-primitives", + "sp-core 28.0.0", +>>>>>>> 0f3f611 (Snowbridge - Various minor improvements (#8020)) "sp-std 14.0.0", ] @@ -25426,7 +25443,10 @@ dependencies = [ "snowbridge-beacon-primitives 0.13.0-rc1", "snowbridge-core 0.13.0-rc1", "snowbridge-inbound-queue-primitives", +<<<<<<< HEAD "snowbridge-pallet-ethereum-client 0.13.0-rc1", +======= +>>>>>>> 0f3f611 (Snowbridge - Various minor improvements (#8020)) "snowbridge-pallet-inbound-queue-v2-fixtures", "snowbridge-test-utils", "sp-core 35.0.1-rc1", @@ -25514,6 +25534,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", +<<<<<<< HEAD "snowbridge-core 0.13.0-rc1", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", @@ -25522,6 +25543,17 @@ dependencies = [ "sp-io 39.0.1-rc1", "sp-keyring 41.0.0-rc1", "sp-runtime 40.2.0-rc1", +======= + "snowbridge-beacon-primitives", + "snowbridge-core", + "snowbridge-merkle-tree", + "snowbridge-outbound-queue-primitives", + "snowbridge-verification-primitives", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", +>>>>>>> 0f3f611 (Snowbridge - Various minor improvements (#8020)) "sp-std 14.0.0", "staging-xcm 16.0.0-rc1", "staging-xcm-builder 19.0.0-rc1", diff --git a/bridges/snowbridge/pallets/ethereum-client/Cargo.toml b/bridges/snowbridge/pallets/ethereum-client/Cargo.toml index c174a2a22215d..adb6c7f8f8c17 100644 --- a/bridges/snowbridge/pallets/ethereum-client/Cargo.toml +++ b/bridges/snowbridge/pallets/ethereum-client/Cargo.toml @@ -32,17 +32,28 @@ sp-io = { optional = true, workspace = true } sp-runtime.workspace = true sp-std.workspace = true pallet-timestamp = { optional = true, workspace = true } +<<<<<<< HEAD snowbridge-beacon-primitives.workspace = true snowbridge-core.workspace = true snowbridge-ethereum.workspace = true snowbridge-inbound-queue-primitives.workspace = true +======= +snowbridge-beacon-primitives = { workspace = true } +snowbridge-core = { workspace = true } +snowbridge-ethereum = { workspace = true } +>>>>>>> 0f3f611 (Snowbridge - Various minor improvements (#8020)) snowbridge-pallet-ethereum-client-fixtures = { optional = true, workspace = true } +snowbridge-verification-primitives = { workspace = true } static_assertions = { workspace = true } [dev-dependencies] hex-literal = { workspace = true, default-features = true } +<<<<<<< HEAD pallet-timestamp = { default-features = true, path = "../../../../substrate/frame/timestamp" } rand = { workspace = true, default-features = true } +======= +pallet-timestamp = { workspace = true, default-features = true } +>>>>>>> 0f3f611 (Snowbridge - Various minor improvements (#8020)) serde = { workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } snowbridge-pallet-ethereum-client-fixtures = { default-features = true, path = "fixtures" } @@ -62,8 +73,8 @@ std = [ "snowbridge-beacon-primitives/std", "snowbridge-core/std", "snowbridge-ethereum/std", - "snowbridge-inbound-queue-primitives/std", "snowbridge-pallet-ethereum-client-fixtures/std", + "snowbridge-verification-primitives/std", "sp-core/std", "sp-io/std", "sp-runtime/std", @@ -77,7 +88,6 @@ runtime-benchmarks = [ "hex-literal", "pallet-timestamp?/runtime-benchmarks", "snowbridge-core/runtime-benchmarks", - "snowbridge-inbound-queue-primitives/runtime-benchmarks", "snowbridge-pallet-ethereum-client-fixtures/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] diff --git a/bridges/snowbridge/pallets/ethereum-client/fixtures/Cargo.toml b/bridges/snowbridge/pallets/ethereum-client/fixtures/Cargo.toml index 06a96c48c41ae..c609c17fb0c74 100644 --- a/bridges/snowbridge/pallets/ethereum-client/fixtures/Cargo.toml +++ b/bridges/snowbridge/pallets/ethereum-client/fixtures/Cargo.toml @@ -19,22 +19,29 @@ exclude-from-umbrella = true [dependencies] hex-literal = { workspace = true, default-features = true } +<<<<<<< HEAD snowbridge-beacon-primitives.workspace = true snowbridge-core.workspace = true snowbridge-inbound-queue-primitives.workspace = true sp-core.workspace = true sp-std.workspace = true +======= +snowbridge-beacon-primitives = { workspace = true } +snowbridge-core = { workspace = true } +snowbridge-verification-primitives = { workspace = true } +sp-core = { workspace = true } +sp-std = { workspace = true } +>>>>>>> 0f3f611 (Snowbridge - Various minor improvements (#8020)) [features] default = ["std"] std = [ "snowbridge-beacon-primitives/std", "snowbridge-core/std", - "snowbridge-inbound-queue-primitives/std", + "snowbridge-verification-primitives/std", "sp-core/std", "sp-std/std", ] runtime-benchmarks = [ "snowbridge-core/runtime-benchmarks", - "snowbridge-inbound-queue-primitives/runtime-benchmarks", ] diff --git a/bridges/snowbridge/pallets/ethereum-client/fixtures/src/lib.rs b/bridges/snowbridge/pallets/ethereum-client/fixtures/src/lib.rs index 01b0f025c5ad9..aa612e59007a5 100644 --- a/bridges/snowbridge/pallets/ethereum-client/fixtures/src/lib.rs +++ b/bridges/snowbridge/pallets/ethereum-client/fixtures/src/lib.rs @@ -9,7 +9,7 @@ use snowbridge_beacon_primitives::{ types::deneb, AncestryProof, BeaconHeader, ExecutionProof, NextSyncCommitteeUpdate, SyncAggregate, SyncCommittee, VersionedExecutionPayloadHeader, }; -use snowbridge_inbound_queue_primitives::{EventProof, InboundQueueFixture, Log, Proof}; +use snowbridge_verification_primitives::{EventFixture, EventProof, Log, Proof}; use sp_core::U256; use sp_std::{boxed::Box, vec}; @@ -1225,8 +1225,8 @@ pub fn make_execution_proof() -> Box { }) } -pub fn make_inbound_fixture() -> InboundQueueFixture { - InboundQueueFixture { +pub fn make_inbound_fixture() -> EventFixture { + EventFixture { event: EventProof { event_log: Log { address: hex!("eda338e4dc46038493b885327842fd3e301cab39").into(), diff --git a/bridges/snowbridge/pallets/ethereum-client/src/impls.rs b/bridges/snowbridge/pallets/ethereum-client/src/impls.rs index 7eda86b06a5c6..8cb959bb174de 100644 --- a/bridges/snowbridge/pallets/ethereum-client/src/impls.rs +++ b/bridges/snowbridge/pallets/ethereum-client/src/impls.rs @@ -6,9 +6,9 @@ use snowbridge_beacon_primitives::ExecutionProof; use snowbridge_beacon_primitives::merkle_proof::{generalized_index_length, subtree_index}; use snowbridge_ethereum::Receipt; -use snowbridge_inbound_queue_primitives::{ +use snowbridge_verification_primitives::{ VerificationError::{self, *}, - *, + Verifier, *, }; impl Verifier for Pallet { diff --git a/bridges/snowbridge/pallets/ethereum-client/src/mock.rs b/bridges/snowbridge/pallets/ethereum-client/src/mock.rs index 1385e0cacd980..9eec93f98c855 100644 --- a/bridges/snowbridge/pallets/ethereum-client/src/mock.rs +++ b/bridges/snowbridge/pallets/ethereum-client/src/mock.rs @@ -5,7 +5,7 @@ use crate::config; use frame_support::{derive_impl, dispatch::DispatchResult, parameter_types}; use pallet_timestamp; use snowbridge_beacon_primitives::{Fork, ForkVersions}; -use snowbridge_inbound_queue_primitives::{Log, Proof}; +use snowbridge_verification_primitives::{Log, Proof}; use sp_std::default::Default; use std::{fs::File, path::PathBuf}; diff --git a/bridges/snowbridge/pallets/ethereum-client/src/mock_electra.rs b/bridges/snowbridge/pallets/ethereum-client/src/mock_electra.rs index 140e9d502034e..d0c9f5bd9eaef 100644 --- a/bridges/snowbridge/pallets/ethereum-client/src/mock_electra.rs +++ b/bridges/snowbridge/pallets/ethereum-client/src/mock_electra.rs @@ -5,7 +5,7 @@ use crate::config; use frame_support::{derive_impl, dispatch::DispatchResult, parameter_types}; use pallet_timestamp; use snowbridge_beacon_primitives::{Fork, ForkVersions}; -use snowbridge_inbound_queue_primitives::{Log, Proof}; +use snowbridge_verification_primitives::{Log, Proof}; use sp_std::default::Default; use std::{fs::File, path::PathBuf}; diff --git a/bridges/snowbridge/pallets/ethereum-client/src/tests.rs b/bridges/snowbridge/pallets/ethereum-client/src/tests.rs index ec43017a95e76..fd27505a547c1 100644 --- a/bridges/snowbridge/pallets/ethereum-client/src/tests.rs +++ b/bridges/snowbridge/pallets/ethereum-client/src/tests.rs @@ -20,7 +20,7 @@ use snowbridge_beacon_primitives::{ types::deneb, Fork, ForkVersions, NextSyncCommitteeUpdate, VersionedExecutionPayloadHeader, }; -use snowbridge_inbound_queue_primitives::{VerificationError, Verifier}; +use snowbridge_verification_primitives::{VerificationError, Verifier}; use sp_core::H256; use sp_runtime::DispatchError; diff --git a/bridges/snowbridge/pallets/ethereum-client/src/tests_electra.rs b/bridges/snowbridge/pallets/ethereum-client/src/tests_electra.rs index 4bac31f0bff3c..2feddf528b4ca 100644 --- a/bridges/snowbridge/pallets/ethereum-client/src/tests_electra.rs +++ b/bridges/snowbridge/pallets/ethereum-client/src/tests_electra.rs @@ -19,7 +19,7 @@ use snowbridge_beacon_primitives::{ types::deneb, Fork, ForkVersions, NextSyncCommitteeUpdate, VersionedExecutionPayloadHeader, }; -use snowbridge_inbound_queue_primitives::{VerificationError, Verifier}; +use snowbridge_verification_primitives::{VerificationError, Verifier}; use sp_core::H256; use sp_runtime::DispatchError; diff --git a/bridges/snowbridge/pallets/inbound-queue-v2/Cargo.toml b/bridges/snowbridge/pallets/inbound-queue-v2/Cargo.toml index fe52c823b9b2d..727cc62dbef7c 100644 --- a/bridges/snowbridge/pallets/inbound-queue-v2/Cargo.toml +++ b/bridges/snowbridge/pallets/inbound-queue-v2/Cargo.toml @@ -50,7 +50,6 @@ bp-relayers = { workspace = true } frame-benchmarking = { workspace = true, default-features = true } hex = { workspace = true, default-features = true } hex-literal = { workspace = true, default-features = true } -snowbridge-pallet-ethereum-client = { workspace = true, default-features = true } snowbridge-test-utils = { workspace = true } sp-keyring = { workspace = true, default-features = true } @@ -89,7 +88,6 @@ runtime-benchmarks = [ "pallet-balances/runtime-benchmarks", "snowbridge-core/runtime-benchmarks", "snowbridge-inbound-queue-primitives/runtime-benchmarks", - "snowbridge-pallet-ethereum-client/runtime-benchmarks", "snowbridge-pallet-inbound-queue-v2-fixtures/runtime-benchmarks", "snowbridge-test-utils/runtime-benchmarks", "sp-runtime/runtime-benchmarks", @@ -101,6 +99,5 @@ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "snowbridge-pallet-ethereum-client/try-runtime", "sp-runtime/try-runtime", ] diff --git a/bridges/snowbridge/pallets/inbound-queue-v2/fixtures/src/register_token.rs b/bridges/snowbridge/pallets/inbound-queue-v2/fixtures/src/register_token.rs index d42899bf8da61..aa13e78542721 100644 --- a/bridges/snowbridge/pallets/inbound-queue-v2/fixtures/src/register_token.rs +++ b/bridges/snowbridge/pallets/inbound-queue-v2/fixtures/src/register_token.rs @@ -7,12 +7,12 @@ use hex_literal::hex; use snowbridge_beacon_primitives::{ types::deneb, AncestryProof, BeaconHeader, ExecutionProof, VersionedExecutionPayloadHeader, }; -use snowbridge_inbound_queue_primitives::{EventProof, InboundQueueFixture, Log, Proof}; +use snowbridge_inbound_queue_primitives::{EventFixture, EventProof, Log, Proof}; use sp_core::U256; use sp_std::vec; -pub fn make_register_token_message() -> InboundQueueFixture { - InboundQueueFixture { +pub fn make_register_token_message() -> EventFixture { + EventFixture { event: EventProof { event_log: Log { address: hex!("b1185ede04202fe62d38f5db72f71e38ff3e8305").into(), diff --git a/bridges/snowbridge/pallets/inbound-queue-v2/src/lib.rs b/bridges/snowbridge/pallets/inbound-queue-v2/src/lib.rs index 03ab4f6dcc08b..57d26c53d1fd8 100644 --- a/bridges/snowbridge/pallets/inbound-queue-v2/src/lib.rs +++ b/bridges/snowbridge/pallets/inbound-queue-v2/src/lib.rs @@ -36,13 +36,6 @@ mod mock; mod test; pub use crate::weights::WeightInfo; -use frame_support::{ - traits::{ - fungible::{Inspect, Mutate}, - tokens::Balance, - }, - weights::WeightToFee, -}; use frame_system::ensure_signed; use snowbridge_core::{ sparse_bitmap::{SparseBitmap, SparseBitmapImpl}, @@ -66,8 +59,6 @@ pub use pallet::*; pub const LOG_TARGET: &str = "snowbridge-pallet-inbound-queue-v2"; pub type AccountIdOf = ::AccountId; -type BalanceOf = - <::Token as Inspect<::AccountId>>::Balance; pub type Nonce = SparseBitmapImpl>; @@ -95,8 +86,6 @@ pub mod pallet { type XcmSender: SendXcm; /// Handler for XCM fees. type XcmExecutor: ExecuteXcm; - /// Ethereum NetworkId - type EthereumNetwork: Get; /// Address of the Gateway contract. #[pallet::constant] type GatewayAddress: Get; @@ -106,8 +95,6 @@ pub mod pallet { type MessageConverter: ConvertMessage; #[cfg(feature = "runtime-benchmarks")] type Helper: BenchmarkHelper; - /// Used for the dry run API implementation. - type Balance: Balance + From; /// Reward discriminator type. type RewardKind: Parameter + MaxEncodedLen + Send + Sync + Copy + Clone; /// The default RewardKind discriminator for rewards allocated to relayers from this pallet. @@ -115,12 +102,9 @@ pub mod pallet { type DefaultRewardKind: Get; /// Relayer reward payment. type RewardPayment: RewardLedger; - type WeightInfo: WeightInfo; - /// Convert a weight value into deductible balance type. - type WeightToFee: WeightToFee>; - type Token: Mutate + Inspect; /// AccountId to Location converter type AccountToLocation: for<'a> TryConvert<&'a Self::AccountId, Location>; + type WeightInfo: WeightInfo; } #[pallet::event] @@ -135,8 +119,6 @@ pub mod pallet { }, /// Set OperatingMode OperatingModeChanged { mode: BasicOperatingMode }, - /// XCM delivery fees were paid. - FeesPaid { paying: Location, fees: Assets }, } #[pallet::error] @@ -264,7 +246,13 @@ pub mod pallet { })?; // Pay relayer reward - T::RewardPayment::register_reward(&relayer, T::DefaultRewardKind::get(), relayer_fee); + if !relayer_fee.is_zero() { + T::RewardPayment::register_reward( + &relayer, + T::DefaultRewardKind::get(), + relayer_fee, + ); + } // Mark message as received Nonce::::set(nonce.into()); @@ -296,7 +284,6 @@ pub mod pallet { ); SendError::Fees })?; - Self::deposit_event(Event::FeesPaid { paying: fee_payer, fees: fee }); T::XcmSender::deliver(ticket) } } diff --git a/bridges/snowbridge/pallets/inbound-queue-v2/src/mock.rs b/bridges/snowbridge/pallets/inbound-queue-v2/src/mock.rs index 05666a3dcb63b..32b0ec1262d1b 100644 --- a/bridges/snowbridge/pallets/inbound-queue-v2/src/mock.rs +++ b/bridges/snowbridge/pallets/inbound-queue-v2/src/mock.rs @@ -4,11 +4,11 @@ use super::*; use crate::{self as inbound_queue_v2}; use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; -use frame_support::{derive_impl, parameter_types, traits::ConstU32, weights::IdentityFee}; +use frame_support::{derive_impl, parameter_types, traits::ConstU32}; use hex_literal::hex; use scale_info::TypeInfo; use snowbridge_beacon_primitives::{ - types::deneb, BeaconHeader, ExecutionProof, Fork, ForkVersions, VersionedExecutionPayloadHeader, + types::deneb, BeaconHeader, ExecutionProof, VersionedExecutionPayloadHeader, }; use snowbridge_core::TokenId; use snowbridge_inbound_queue_primitives::{v2::MessageToXcm, Log, Proof, VerificationError}; @@ -27,7 +27,6 @@ frame_support::construct_runtime!( { System: frame_system::{Pallet, Call, Storage, Event}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - EthereumBeaconClient: snowbridge_pallet_ethereum_client::{Pallet, Call, Storage, Event}, InboundQueue: inbound_queue_v2::{Pallet, Call, Storage, Event}, } ); @@ -56,42 +55,6 @@ impl pallet_balances::Config for Test { type AccountStore = System; } -parameter_types! { - pub const ChainForkVersions: ForkVersions = ForkVersions { - genesis: Fork { - version: [0, 0, 0, 1], // 0x00000001 - epoch: 0, - }, - altair: Fork { - version: [1, 0, 0, 1], // 0x01000001 - epoch: 0, - }, - bellatrix: Fork { - version: [2, 0, 0, 1], // 0x02000001 - epoch: 0, - }, - capella: Fork { - version: [3, 0, 0, 1], // 0x03000001 - epoch: 0, - }, - deneb: Fork { - version: [4, 0, 0, 1], // 0x04000001 - epoch: 0, - }, - electra: Fork { - version: [5, 0, 0, 0], // 0x05000000 - epoch: 80000000000, - } - }; -} - -impl snowbridge_pallet_ethereum_client::Config for Test { - type RuntimeEvent = RuntimeEvent; - type ForkVersions = ChainForkVersions; - type FreeHeadersInterval = ConstU32<32>; - type WeightInfo = (); -} - // Mock verifier pub struct MockVerifier; @@ -107,7 +70,7 @@ impl Verifier for MockVerifier { const GATEWAY_ADDRESS: [u8; 20] = hex!["b1185ede04202fe62d38f5db72f71e38ff3e8305"]; #[cfg(feature = "runtime-benchmarks")] -impl BenchmarkHelper for Test { +impl BenchmarkHelper for Test { // not implemented since the MockVerifier is used for tests fn initialize_storage(_: BeaconHeader, _: H256) {} } @@ -161,12 +124,17 @@ pub enum BridgeReward { Snowbridge, } +parameter_types! { + pub static RegisteredRewardsCount: u128 = 0; +} + impl RewardLedger<::AccountId, BridgeReward, u128> for () { fn register_reward( _relayer: &::AccountId, _reward: BridgeReward, _reward_balance: u128, ) { + RegisteredRewardsCount::set(RegisteredRewardsCount::get().saturating_add(1)); } } @@ -176,7 +144,6 @@ impl inbound_queue_v2::Config for Test { type XcmSender = MockXcmSender; type XcmExecutor = MockXcmExecutor; type RewardPayment = (); - type EthereumNetwork = EthereumNetwork; type GatewayAddress = GatewayAddress; type AssetHubParaId = ConstU32<1000>; type MessageConverter = MessageToXcm< @@ -191,10 +158,7 @@ impl inbound_queue_v2::Config for Test { >; #[cfg(feature = "runtime-benchmarks")] type Helper = Test; - type Balance = u128; type WeightInfo = (); - type WeightToFee = IdentityFee; - type Token = Balances; type AccountToLocation = MockAccountLocationConverter; type RewardKind = BridgeReward; type DefaultRewardKind = SnowbridgeReward; diff --git a/bridges/snowbridge/pallets/inbound-queue-v2/src/test.rs b/bridges/snowbridge/pallets/inbound-queue-v2/src/test.rs index 267485c319521..3f7dec0849d31 100644 --- a/bridges/snowbridge/pallets/inbound-queue-v2/src/test.rs +++ b/bridges/snowbridge/pallets/inbound-queue-v2/src/test.rs @@ -5,7 +5,7 @@ use super::*; use crate::{mock::*, Error}; use codec::Encode; use frame_support::{assert_noop, assert_ok}; -use snowbridge_inbound_queue_primitives::{EventProof, Proof}; +use snowbridge_inbound_queue_primitives::{v2::XcmPayload, EventProof, Proof}; use snowbridge_test_utils::mock_xcm::{set_charge_fees_override, set_sender_override}; use sp_keyring::sr25519::Keyring; use sp_runtime::DispatchError; @@ -37,13 +37,8 @@ fn test_submit_happy_path() { )), "no message received event emitted." ); - assert!( - events.iter().any(|event| matches!( - event.event, - RuntimeEvent::InboundQueue(Event::FeesPaid { .. }) - )), - "no fees paid event emitted." - ); + + assert_eq!(RegisteredRewardsCount::get(), 1, "Relayer reward should have been registered"); }); } @@ -325,3 +320,31 @@ fn test_switch_operating_mode() { assert_ok!(InboundQueue::submit(origin, Box::new(event))); }); } + +#[test] +fn zero_reward_does_not_register_reward() { + new_tester().execute_with(|| { + let relayer: AccountId = Keyring::Bob.into(); + let origin = H160::random(); + assert_ok!(InboundQueue::process_message( + relayer, + Message { + nonce: 0, + assets: vec![], + xcm: XcmPayload::Raw(vec![]), + claimer: None, + execution_fee: 1_000_000_000, + relayer_fee: 0, + gateway: GatewayAddress::get(), + origin, + value: 3_000_000_000, + } + )); + + assert_eq!( + RegisteredRewardsCount::get(), + 0, + "Zero relayer reward should not be registered" + ); + }); +} diff --git a/bridges/snowbridge/pallets/inbound-queue/fixtures/src/register_token.rs b/bridges/snowbridge/pallets/inbound-queue/fixtures/src/register_token.rs index 12ce83e305c6c..63868f36f0997 100644 --- a/bridges/snowbridge/pallets/inbound-queue/fixtures/src/register_token.rs +++ b/bridges/snowbridge/pallets/inbound-queue/fixtures/src/register_token.rs @@ -7,12 +7,12 @@ use hex_literal::hex; use snowbridge_beacon_primitives::{ types::deneb, AncestryProof, BeaconHeader, ExecutionProof, VersionedExecutionPayloadHeader, }; -use snowbridge_inbound_queue_primitives::{EventProof, InboundQueueFixture, Log, Proof}; +use snowbridge_inbound_queue_primitives::{EventFixture, EventProof, Log, Proof}; use sp_core::U256; use sp_std::vec; -pub fn make_register_token_message() -> InboundQueueFixture { - InboundQueueFixture { +pub fn make_register_token_message() -> EventFixture { + EventFixture { event: EventProof { event_log: Log { address: hex!("eda338e4dc46038493b885327842fd3e301cab39").into(), diff --git a/bridges/snowbridge/pallets/inbound-queue/fixtures/src/send_native_eth.rs b/bridges/snowbridge/pallets/inbound-queue/fixtures/src/send_native_eth.rs index 61b8209668f84..e277f27166e08 100755 --- a/bridges/snowbridge/pallets/inbound-queue/fixtures/src/send_native_eth.rs +++ b/bridges/snowbridge/pallets/inbound-queue/fixtures/src/send_native_eth.rs @@ -7,12 +7,12 @@ use hex_literal::hex; use snowbridge_beacon_primitives::{ types::deneb, AncestryProof, BeaconHeader, ExecutionProof, VersionedExecutionPayloadHeader, }; -use snowbridge_inbound_queue_primitives::{EventProof, InboundQueueFixture, Log, Proof}; +use snowbridge_inbound_queue_primitives::{EventFixture, EventProof, Log, Proof}; use sp_core::U256; use sp_std::vec; -pub fn make_send_native_eth_message() -> InboundQueueFixture { - InboundQueueFixture { +pub fn make_send_native_eth_message() -> EventFixture { + EventFixture { event: EventProof { event_log: Log { address: hex!("87d1f7fdfee7f651fabc8bfcb6e086c278b77a7d").into(), diff --git a/bridges/snowbridge/pallets/inbound-queue/fixtures/src/send_token.rs b/bridges/snowbridge/pallets/inbound-queue/fixtures/src/send_token.rs index 588c67088c3e9..bd72afc13e2b7 100755 --- a/bridges/snowbridge/pallets/inbound-queue/fixtures/src/send_token.rs +++ b/bridges/snowbridge/pallets/inbound-queue/fixtures/src/send_token.rs @@ -7,12 +7,12 @@ use hex_literal::hex; use snowbridge_beacon_primitives::{ types::deneb, AncestryProof, BeaconHeader, ExecutionProof, VersionedExecutionPayloadHeader, }; -use snowbridge_inbound_queue_primitives::{EventProof, InboundQueueFixture, Log, Proof}; +use snowbridge_inbound_queue_primitives::{EventFixture, EventProof, Log, Proof}; use sp_core::U256; use sp_std::vec; -pub fn make_send_token_message() -> InboundQueueFixture { - InboundQueueFixture { +pub fn make_send_token_message() -> EventFixture { + EventFixture { event: EventProof { event_log: Log { address: hex!("eda338e4dc46038493b885327842fd3e301cab39").into(), diff --git a/bridges/snowbridge/pallets/inbound-queue/fixtures/src/send_token_to_penpal.rs b/bridges/snowbridge/pallets/inbound-queue/fixtures/src/send_token_to_penpal.rs index cba96a79fd0ab..a61b13f9582a9 100755 --- a/bridges/snowbridge/pallets/inbound-queue/fixtures/src/send_token_to_penpal.rs +++ b/bridges/snowbridge/pallets/inbound-queue/fixtures/src/send_token_to_penpal.rs @@ -7,12 +7,12 @@ use hex_literal::hex; use snowbridge_beacon_primitives::{ types::deneb, AncestryProof, BeaconHeader, ExecutionProof, VersionedExecutionPayloadHeader, }; -use snowbridge_inbound_queue_primitives::{EventProof, InboundQueueFixture, Log, Proof}; +use snowbridge_inbound_queue_primitives::{EventFixture, EventProof, Log, Proof}; use sp_core::U256; use sp_std::vec; -pub fn make_send_token_to_penpal_message() -> InboundQueueFixture { - InboundQueueFixture { +pub fn make_send_token_to_penpal_message() -> EventFixture { + EventFixture { event: EventProof { event_log: Log { address: hex!("eda338e4dc46038493b885327842fd3e301cab39").into(), diff --git a/bridges/snowbridge/pallets/outbound-queue-v2/Cargo.toml b/bridges/snowbridge/pallets/outbound-queue-v2/Cargo.toml index d895e8aba1497..b39dd07b8d376 100644 --- a/bridges/snowbridge/pallets/outbound-queue-v2/Cargo.toml +++ b/bridges/snowbridge/pallets/outbound-queue-v2/Cargo.toml @@ -37,9 +37,11 @@ sp-std = { workspace = true } bp-relayers = { workspace = true } bridge-hub-common = { workspace = true } +snowbridge-beacon-primitives = { workspace = true } snowbridge-core = { workspace = true } snowbridge-merkle-tree = { workspace = true } snowbridge-outbound-queue-primitives = { workspace = true } +snowbridge-verification-primitives = { workspace = true } xcm = { workspace = true } xcm-builder = { workspace = true } @@ -47,7 +49,6 @@ xcm-executor = { workspace = true } [dev-dependencies] pallet-message-queue = { workspace = true } -sp-keyring = { workspace = true, default-features = true } [features] default = ["std"] @@ -63,9 +64,11 @@ std = [ "pallet-message-queue/std", "scale-info/std", "serde/std", + "snowbridge-beacon-primitives/std", "snowbridge-core/std", "snowbridge-merkle-tree/std", "snowbridge-outbound-queue-primitives/std", + "snowbridge-verification-primitives/std", "sp-arithmetic/std", "sp-core/std", "sp-io/std", diff --git a/bridges/snowbridge/pallets/outbound-queue-v2/src/benchmarking.rs b/bridges/snowbridge/pallets/outbound-queue-v2/src/benchmarking.rs index b4ce4d2106564..1af38457a528f 100644 --- a/bridges/snowbridge/pallets/outbound-queue-v2/src/benchmarking.rs +++ b/bridges/snowbridge/pallets/outbound-queue-v2/src/benchmarking.rs @@ -2,10 +2,12 @@ // SPDX-FileCopyrightText: 2023 Snowfork use super::*; +use crate::fixture::make_submit_delivery_receipt_message; use bridge_hub_common::AggregateMessageOrigin; use codec::Encode; use frame_benchmarking::v2::*; use frame_support::{traits::Hooks, BoundedVec}; +use frame_system::RawOrigin; use snowbridge_outbound_queue_primitives::v2::{Command, Initializer, Message}; use sp_core::{H160, H256}; @@ -18,6 +20,7 @@ use crate::Pallet as OutboundQueue; )] mod benchmarks { use super::*; + use frame_support::assert_ok; /// Build `Upgrade` message with `MaxMessagePayloadSize`, in the worst-case. fn build_message() -> (Message, OutboundMessage) { @@ -147,5 +150,33 @@ mod benchmarks { Ok(()) } + #[benchmark] + fn submit_delivery_receipt() -> Result<(), BenchmarkError> { + let caller: T::AccountId = whitelisted_caller(); + + let message = make_submit_delivery_receipt_message(); + + T::Helper::initialize_storage(message.finalized_header, message.block_roots_root); + + let receipt = DeliveryReceipt::try_from(&message.event.event_log).unwrap(); + + let order = PendingOrder { + nonce: receipt.nonce, + fee: 0, + block_number: frame_system::Pallet::::current_block_number(), + }; + >::insert(receipt.nonce, order); + + #[block] + { + assert_ok!(OutboundQueue::::submit_delivery_receipt( + RawOrigin::Signed(caller.clone()).into(), + Box::new(message.event), + )); + } + + Ok(()) + } + impl_benchmark_test_suite!(OutboundQueue, crate::mock::new_tester(), crate::mock::Test,); } diff --git a/bridges/snowbridge/pallets/outbound-queue-v2/src/fixture.rs b/bridges/snowbridge/pallets/outbound-queue-v2/src/fixture.rs new file mode 100644 index 0000000000000..b6c4a9d998265 --- /dev/null +++ b/bridges/snowbridge/pallets/outbound-queue-v2/src/fixture.rs @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +// Generated, do not edit! +// See ethereum client README.md for instructions to generate + +use hex_literal::hex; +use snowbridge_beacon_primitives::{ + types::deneb, AncestryProof, BeaconHeader, ExecutionProof, VersionedExecutionPayloadHeader, +}; +use snowbridge_verification_primitives::{EventFixture, EventProof, Log, Proof}; +use sp_core::U256; +use sp_std::vec; + +pub fn make_submit_delivery_receipt_message() -> EventFixture { + EventFixture { + event: EventProof { + event_log: Log { + address: hex!("b1185ede04202fe62d38f5db72f71e38ff3e8305").into(), + topics: vec![ + hex!("8856ab63954e6c2938803a4654fb704c8779757e7bfdbe94a578e341ec637a95").into(), + hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), + ], + data: hex!("907b6ec7bf3f2496ef79238e0fb19e032bfe444c7ffe906bd340c6c4ffe8511f0000000000000000000000000000000000000000000000000000000000000001d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d").into(), + }, + proof: Proof { + receipt_proof: (vec![ + hex!("8a40611a32af2ad0ad63bf32e8c633ff209e6f701645b8f25e492327cd95d4e0").to_vec(), + ], vec![ + hex!("f9024e822080b9024802f9024401830d716eb9010000200000000000000000000000000000080000000000000000000000000000000000000000000004000000000000000000000000000000000000000000008000000000000000000801000000000000000000000000000000000000000000000000000000020000000008000000000800000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000800000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000020000000000200000000000000000000000000000000000000000000000000000000f90139f87a94b1185ede04202fe62d38f5db72f71e38ff3e8305f842a057f58171b8777633d03aff1e7408b96a3d910c93a7ce433a8cb7fb837dc306a6a09441dceeeffa7e032eedaccf9b7632e60e86711551a82ffbbb0dda8afd9e4ef7a0000000000000000000000000de45448ca2d57797c0bec0ee15a1e42334744219f8bb94b1185ede04202fe62d38f5db72f71e38ff3e8305f842a08856ab63954e6c2938803a4654fb704c8779757e7bfdbe94a578e341ec637a95a00000000000000000000000000000000000000000000000000000000000000000b860907b6ec7bf3f2496ef79238e0fb19e032bfe444c7ffe906bd340c6c4ffe8511f0000000000000000000000000000000000000000000000000000000000000001d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d").to_vec(), + ]), + execution_proof: ExecutionProof { + header: BeaconHeader { + slot: 663, + proposer_index: 4, + parent_root: hex!("478651896411faa949cd0882bb6a82595b71d3eba74cbeb87b5eb8162c7e00f1").into(), + state_root: hex!("4191b7c2a622b8cfa31684e5e06de3b36834e403a6ded2acd32156a488f829b0").into(), + body_root: hex!("72765c81bbad6cd083314506936528719e03d33ee65927167a372febe1fbf734").into(), + }, + ancestry_proof: Some(AncestryProof { + header_branch: vec![ + hex!("478651896411faa949cd0882bb6a82595b71d3eba74cbeb87b5eb8162c7e00f1").into(), + hex!("87314a5200d3a22749bd98ba32af7d0546d25d47cf012dfcc85adc19ad7adfe3").into(), + hex!("e794355aa5b1743ea691e3f051f44a66956892621c0110a12980e66f70dc3d74").into(), + hex!("fe0a3f7035e5d4cc83412939c9d343caa34889bd9655a05e9cc53a09e3aa7e8c").into(), + hex!("0f472e1a66d039197fbe378845e848ec11d5bcde60ac650da812fa1f4461c603").into(), + hex!("018f388291fbd20c15691e4b118a17b870eec7beb837e91fcc839adcb5fb21fc").into(), + hex!("8a016b0d65b61e5026b9357df092bf82b52fa61af3e10d11ba7b24ae30b457ec").into(), + hex!("73af6cacce9735d5576d1defc7fc39061776004ac7d3aba3abf6dfad7b1a3a36").into(), + hex!("6116f4b671f0f26c224ab10c6c330d56c9b5e48fa6e2204035f333bc142f55d2").into(), + hex!("a08d24b9120c5faeb98654664c4a324aaa509031193dbd74930acf26285b26a6").into(), + hex!("ffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b").into(), + hex!("6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220").into(), + hex!("b7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f").into(), + ], + finalized_block_root: hex!("d5793913dc57d9f5b9d50fb8c693504201d6926649834ac90337b673e66f98e0").into(), + }), + execution_header: VersionedExecutionPayloadHeader::Deneb(deneb::ExecutionPayloadHeader { + parent_hash: hex!("35f64f37bea4538092ba578f4851d52375f7f3b2a52c1cb16f22fe512aead95d").into(), + fee_recipient: hex!("0000000000000000000000000000000000000000").into(), + state_root: hex!("dfa305877e67ab0caa827b15d573b58dfe360fe8d484d37228f8ae55ccced61c").into(), + receipts_root: hex!("8a40611a32af2ad0ad63bf32e8c633ff209e6f701645b8f25e492327cd95d4e0").into(), + logs_bloom: hex!("00200000000000000000000000000000080000000000000000000000000000000000000000000004000000000000000000000000000000000000000000008000000000000000000801000000000000000000000000000000000000000000000000000000020000000008000000000800000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000800000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000020000000000200000000000000000000000000000000000000000000000000000000").into(), + prev_randao: hex!("ebdade0d95216bdba380fce14fad97c870d8553fcf0ca37df22331b3ed498db2").into(), + block_number: 663, + gas_limit: 41857321, + gas_used: 881006, + timestamp: 1742914413, + extra_data: hex!("d983010e0c846765746888676f312e32332e348664617277696e").into(), + base_fee_per_gas: U256::from(7u64), + block_hash: hex!("c70c7e5b0a03fa9509e0b4598d65e6e0b6a2477f25064aa3221b39eee17583d4").into(), + transactions_root: hex!("065ecaa208638c4a43d080cd78a1451e406895caaa254b1ad0585c6a9e3c7ac6").into(), + withdrawals_root: hex!("792930bbd5baac43bcc798ee49aa8185ef76bb3b44ba62b91d86ae569e4bb535").into(), + blob_gas_used: 0, + excess_blob_gas: 0, + }), + execution_branch: vec![ + hex!("ef46bf5d8bd654162c1a7f44949fe1f9cb2a3f356d593587a3f1f3f8da14b790").into(), + hex!("b46f0c01805fe212e15907981b757e6c496b0cb06664224655613dcec82505bb").into(), + hex!("db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71").into(), + hex!("b4e39d31736a4064a84ca49c4d372696e92e7c5c7bcbb7219671c24df1dfcafa").into(), + ], + } + }, + }, + finalized_header: BeaconHeader { + slot: 864, + proposer_index: 4, + parent_root: hex!("2839d32d7b5a1dbb9139c5fd11ea549abaac1ead425c79553b8424550fddd389").into(), + state_root: hex!("452daf2471437939f4d65af921a1cfee860b11111771fd55164b37fe25d610de").into(), + body_root: hex!("0bbd0377987d0984e7495bf61219342941e31a0b6fe790453fbc87ec92319097").into(), + }, + block_roots_root: hex!("aca108d3e77ec6b010ca03df025e3b2e84f754d4642e5d8bf0ba9bdf58f42848").into(), + } +} diff --git a/bridges/snowbridge/pallets/outbound-queue-v2/src/lib.rs b/bridges/snowbridge/pallets/outbound-queue-v2/src/lib.rs index 92d53d536c1c4..b15b300e8884d 100644 --- a/bridges/snowbridge/pallets/outbound-queue-v2/src/lib.rs +++ b/bridges/snowbridge/pallets/outbound-queue-v2/src/lib.rs @@ -64,6 +64,9 @@ mod mock; #[cfg(test)] mod test; +#[cfg(feature = "runtime-benchmarks")] +mod fixture; + use alloy_core::{ primitives::{Bytes, FixedBytes}, sol_types::SolValue, @@ -76,7 +79,7 @@ use frame_support::{ traits::{tokens::Balance, EnqueueMessage, Get, ProcessMessageError}, weights::{Weight, WeightToFee}, }; -use snowbridge_core::{BasicOperatingMode, TokenId}; +use snowbridge_core::BasicOperatingMode; use snowbridge_merkle_tree::merkle_root; use snowbridge_outbound_queue_primitives::{ v2::{ @@ -87,14 +90,16 @@ use snowbridge_outbound_queue_primitives::{ }; use sp_core::{H160, H256}; use sp_runtime::{ - traits::{BlockNumberProvider, Hash, MaybeEquivalence}, + traits::{BlockNumberProvider, Hash}, DigestItem, }; use sp_std::prelude::*; pub use types::{PendingOrder, ProcessMessageOriginOf}; pub use weights::WeightInfo; -use xcm::latest::{Location, NetworkId}; -type DeliveryReceiptOf = DeliveryReceipt<::AccountId>; +use xcm::prelude::NetworkId; + +#[cfg(feature = "runtime-benchmarks")] +use snowbridge_beacon_primitives::BeaconHeader; pub use pallet::*; @@ -149,7 +154,8 @@ pub mod pallet { type RewardPayment: RewardLedger; /// Ethereum NetworkId type EthereumNetwork: Get; - type ConvertAssetId: MaybeEquivalence; + #[cfg(feature = "runtime-benchmarks")] + type Helper: BenchmarkHelper; } #[pallet::event] @@ -168,6 +174,25 @@ pub mod pallet { /// The nonce assigned to this message nonce: u64, }, + /// Message was not committed due to some failure condition, like an overweight message. + MessageRejected { + /// ID of the message, if known (e.g. if a message is corrupt, the ID will not be + /// known). + id: Option, + /// The payload of the message. Useful for debugging purposes if the message + /// cannot be decoded. + payload: Vec, + /// The error that was returned. + error: ProcessMessageError, + }, + /// Message was not committed due to being overweight or the current block is full. + MessagePostponed { + /// The payload of the message. Useful for debugging purposes if the message + /// cannot be decoded. + payload: Vec, + /// The error that was returned. + reason: ProcessMessageError, + }, /// Some messages have been committed MessagesCommitted { /// Merkle root of the committed messages @@ -178,7 +203,7 @@ pub mod pallet { /// Set OperatingMode OperatingModeChanged { mode: BasicOperatingMode }, /// Delivery Proof received - MessageDeliveryProofReceived { nonce: u64 }, + MessageDelivered { nonce: u64 }, } #[pallet::error] @@ -244,11 +269,13 @@ pub mod pallet { } } + #[cfg(feature = "runtime-benchmarks")] + pub trait BenchmarkHelper { + fn initialize_storage(beacon_header: BeaconHeader, block_roots_root: H256); + } + #[pallet::call] - impl Pallet - where - T::AccountId: From<[u8; 32]>, - { + impl Pallet { #[pallet::call_index(1)] #[pallet::weight(T::WeightInfo::submit_delivery_receipt())] pub fn submit_delivery_receipt( @@ -261,7 +288,7 @@ pub mod pallet { T::Verifier::verify(&event.event_log, &event.proof) .map_err(|e| Error::::Verification(e))?; - let receipt = DeliveryReceiptOf::::try_from(&event.event_log) + let receipt = DeliveryReceipt::try_from(&event.event_log) .map_err(|_| Error::::InvalidEnvelope)?; Self::process_delivery_receipt(relayer, receipt) @@ -296,17 +323,27 @@ pub mod pallet { // Yield if the maximum number of messages has been processed this block. // This ensures that the weight of `on_finalize` has a known maximum bound. - ensure!( - MessageLeaves::::decode_len().unwrap_or(0) < - T::MaxMessagesPerBlock::get() as usize, - Yield - ); + let current_len = MessageLeaves::::decode_len().unwrap_or(0); + if current_len >= T::MaxMessagesPerBlock::get() as usize { + Self::deposit_event(Event::MessagePostponed { + payload: message.to_vec(), + reason: Yield, + }); + return Err(Yield); + } let nonce = Nonce::::get(); // Decode bytes into Message let Message { origin, id, fee, commands } = - Message::decode(&mut message).map_err(|_| Corrupt)?; + Message::decode(&mut message).map_err(|_| { + Self::deposit_event(Event::MessageRejected { + id: None, + payload: message.to_vec(), + error: Corrupt, + }); + Corrupt + })?; // Convert it to OutboundMessage and save into Messages storage let commands: Vec = commands @@ -321,7 +358,14 @@ pub mod pallet { origin, nonce, topic: id, - commands: commands.clone().try_into().map_err(|_| Corrupt)?, + commands: commands.clone().try_into().map_err(|_| { + Self::deposit_event(Event::MessageRejected { + id: Some(id), + payload: message.to_vec(), + error: Corrupt, + }); + Corrupt + })?, }; Messages::::append(outbound_message); @@ -358,7 +402,14 @@ pub mod pallet { }; >::insert(nonce, order); - Nonce::::set(nonce.checked_add(1).ok_or(Unsupported)?); + Nonce::::set(nonce.checked_add(1).ok_or_else(|| { + Self::deposit_event(Event::MessageRejected { + id: Some(id), + payload: message.to_vec(), + error: Unsupported, + }); + Unsupported + })?); Self::deposit_event(Event::MessageAccepted { id, nonce }); @@ -368,11 +419,8 @@ pub mod pallet { /// Process a delivery receipt from a relayer, to allocate the relayer reward. pub fn process_delivery_receipt( relayer: ::AccountId, - receipt: DeliveryReceiptOf, - ) -> DispatchResult - where - ::AccountId: From<[u8; 32]>, - { + receipt: DeliveryReceipt, + ) -> DispatchResult { // Verify that the message was submitted from the known Gateway contract ensure!(T::GatewayAddress::get() == receipt.gateway, Error::::InvalidGateway); @@ -387,16 +435,9 @@ pub mod pallet { >::remove(nonce); - Self::deposit_event(Event::MessageDeliveryProofReceived { nonce }); + Self::deposit_event(Event::MessageDelivered { nonce }); Ok(()) } - - /// The local component of the message processing fees in native currency - pub(crate) fn calculate_local_fee() -> T::Balance { - T::WeightToFee::weight_to_fee( - &T::WeightInfo::do_process_message().saturating_add(T::WeightInfo::commit_single()), - ) - } } } diff --git a/bridges/snowbridge/pallets/outbound-queue-v2/src/mock.rs b/bridges/snowbridge/pallets/outbound-queue-v2/src/mock.rs index 0263b30bbfe04..f14332cc45a14 100644 --- a/bridges/snowbridge/pallets/outbound-queue-v2/src/mock.rs +++ b/bridges/snowbridge/pallets/outbound-queue-v2/src/mock.rs @@ -83,7 +83,7 @@ impl Verifier for MockVerifier { } } -const GATEWAY_ADDRESS: [u8; 20] = hex!["eda338e4dc46038493b885327842fd3e301cab39"]; +const GATEWAY_ADDRESS: [u8; 20] = hex!["b1185ede04202fe62d38f5db72f71e38ff3e8305"]; const WETH: [u8; 20] = hex!["C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"]; parameter_types! { @@ -141,10 +141,11 @@ impl crate::Config for Test { type WeightToFee = IdentityFee; type WeightInfo = (); type RewardPayment = (); - type ConvertAssetId = (); type EthereumNetwork = EthereumNetwork; type RewardKind = BridgeReward; type DefaultRewardKind = DefaultMyRewardKind; + #[cfg(feature = "runtime-benchmarks")] + type Helper = Test; } fn setup() { @@ -251,3 +252,9 @@ pub fn mock_register_token_message(sibling_para_id: u32) -> Message { .unwrap(), } } + +#[cfg(feature = "runtime-benchmarks")] +impl BenchmarkHelper for Test { + // not implemented since the MockVerifier is used for tests + fn initialize_storage(_: BeaconHeader, _: H256) {} +} diff --git a/bridges/snowbridge/pallets/outbound-queue-v2/src/process_message_impl.rs b/bridges/snowbridge/pallets/outbound-queue-v2/src/process_message_impl.rs index 731aa6fa6d5ca..28eee2b804a58 100644 --- a/bridges/snowbridge/pallets/outbound-queue-v2/src/process_message_impl.rs +++ b/bridges/snowbridge/pallets/outbound-queue-v2/src/process_message_impl.rs @@ -18,6 +18,10 @@ impl ProcessMessage for Pallet { ) -> Result { let weight = T::WeightInfo::do_process_message(); if meter.try_consume(weight).is_err() { + Self::deposit_event(Event::MessagePostponed { + payload: message.to_vec(), + reason: ProcessMessageError::Overweight(weight), + }); return Err(ProcessMessageError::Overweight(weight)) } Self::do_process_message(origin, message) diff --git a/bridges/snowbridge/pallets/outbound-queue-v2/src/send_message_impl.rs b/bridges/snowbridge/pallets/outbound-queue-v2/src/send_message_impl.rs index c7f57ec283d12..95f756c4d4003 100644 --- a/bridges/snowbridge/pallets/outbound-queue-v2/src/send_message_impl.rs +++ b/bridges/snowbridge/pallets/outbound-queue-v2/src/send_message_impl.rs @@ -10,7 +10,7 @@ use frame_support::{ }; use snowbridge_outbound_queue_primitives::{ v2::{Message, SendMessage}, - SendError, SendMessageFeeProvider, + SendError, }; use sp_core::H256; use sp_runtime::BoundedVec; @@ -43,12 +43,3 @@ where Ok(ticket.id) } } - -impl SendMessageFeeProvider for Pallet { - type Balance = T::Balance; - - /// The local component of the message processing fees in native currency - fn local_fee() -> Self::Balance { - Self::calculate_local_fee() - } -} diff --git a/bridges/snowbridge/pallets/outbound-queue-v2/src/test.rs b/bridges/snowbridge/pallets/outbound-queue-v2/src/test.rs index b3651b64b0124..129bdb66c583f 100644 --- a/bridges/snowbridge/pallets/outbound-queue-v2/src/test.rs +++ b/bridges/snowbridge/pallets/outbound-queue-v2/src/test.rs @@ -2,15 +2,13 @@ // SPDX-FileCopyrightText: 2023 Snowfork use crate::{mock::*, *}; use alloy_core::primitives::FixedBytes; - +use codec::Encode; use frame_support::{ - assert_err, assert_noop, assert_ok, + assert_err, assert_ok, traits::{Hooks, ProcessMessage, ProcessMessageError}, weights::WeightMeter, BoundedVec, }; - -use codec::Encode; use hex_literal::hex; use snowbridge_core::{ChannelId, ParaId}; use snowbridge_outbound_queue_primitives::{ @@ -86,7 +84,7 @@ fn process_message_yields_on_max_messages_per_block() { let mut meter = WeightMeter::new(); - assert_noop!( + assert_err!( OutboundQueue::process_message( message.encode().as_slice(), origin, @@ -95,6 +93,18 @@ fn process_message_yields_on_max_messages_per_block() { ), ProcessMessageError::Yield ); + let events = System::events(); + let last_event = events.last().expect("Expected at least one event").event.clone(); + + match last_event { + mock::RuntimeEvent::OutboundQueue(Event::MessagePostponed { + payload: _, + reason: ProcessMessageError::Yield, + }) => {}, + _ => { + panic!("Expected Event::MessagePostponed(Yield) but got {:?}", last_event); + }, + } }) } @@ -116,7 +126,26 @@ fn process_message_fails_on_max_nonce_reached() { &mut meter, &mut [0u8; 32], ); - assert_err!(result, ProcessMessageError::Unsupported) + assert_err!(result, ProcessMessageError::Unsupported); + + let events = System::events(); + let last_event = events.last().expect("Expected at least one event").event.clone(); + + match last_event { + mock::RuntimeEvent::OutboundQueue(Event::MessageRejected { + id: Some(id), + payload: _, + error: ProcessMessageError::Unsupported, + }) => { + assert_eq!( + id, + hex!("0000000000000000000000000000000000000000000000000000000000000001").into() + ); + }, + _ => { + panic!("Expected Event::MessageRejected(Unsupported) but got {:?}", last_event); + }, + } }) } @@ -128,7 +157,7 @@ fn process_message_fails_on_overweight_message() { let origin = AggregateMessageOrigin::SnowbridgeV2(H256::zero()); let message: Message = mock_message(sibling_id); let mut meter = WeightMeter::with_limit(Weight::from_parts(1, 1)); - assert_noop!( + assert_err!( OutboundQueue::process_message( message.encode().as_slice(), origin, @@ -137,6 +166,18 @@ fn process_message_fails_on_overweight_message() { ), ProcessMessageError::Overweight(::WeightInfo::do_process_message()) ); + let events = System::events(); + let last_event = events.last().expect("Expected at least one event").event.clone(); + + match last_event { + mock::RuntimeEvent::OutboundQueue(Event::MessagePostponed { + payload: _, + reason: ProcessMessageError::Overweight(_), + }) => {}, + _ => { + panic!("Expected Event::MessagePostponed(Overweight(_)) but got {:?}", last_event); + }, + } }) } @@ -257,7 +298,7 @@ fn encode_unlock_message() { let message: Message = mock_message(1000); let message_abi_encoded = encode_mock_message(message); println!("{}", HexDisplay::from(&message_abi_encoded)); - assert_eq!(hex!("000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000eda338e4dc46038493b885327842fd3e301cab3900000000000000000000000000000000000000000000000000000000000f4240").to_vec(), message_abi_encoded) + assert_eq!(hex!("000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000b1185ede04202fe62d38f5db72f71e38ff3e830500000000000000000000000000000000000000000000000000000000000f4240").to_vec(), message_abi_encoded) } #[test] diff --git a/bridges/snowbridge/pallets/system-frontend/src/mock.rs b/bridges/snowbridge/pallets/system-frontend/src/mock.rs index ce9790c46c950..fd212ca2e5135 100644 --- a/bridges/snowbridge/pallets/system-frontend/src/mock.rs +++ b/bridges/snowbridge/pallets/system-frontend/src/mock.rs @@ -69,7 +69,7 @@ parameter_types! { pub BridgeHubLocation: Location = Location::new(1, [Parachain(1002)]); pub UniversalLocation: InteriorLocation = [GlobalConsensus(Polkadot), Parachain(1000)].into(); - pub PalletLocation: InteriorLocation = [PalletInstance(80)].into(); + pub PalletLocation: InteriorLocation = [PalletInstance(36)].into(); } impl crate::Config for Test { diff --git a/bridges/snowbridge/pallets/system-v2/src/benchmarking.rs b/bridges/snowbridge/pallets/system-v2/src/benchmarking.rs index 296d6dd3db09f..b734755e3fc0f 100644 --- a/bridges/snowbridge/pallets/system-v2/src/benchmarking.rs +++ b/bridges/snowbridge/pallets/system-v2/src/benchmarking.rs @@ -14,7 +14,7 @@ mod benchmarks { #[benchmark] fn register_token() -> Result<(), BenchmarkError> { - let origin_location = Location::new(1, [Parachain(1000), PalletInstance(80)]); + let origin_location = Location::new(1, [Parachain(1000), PalletInstance(36)]); let origin = ::Helper::make_xcm_origin(origin_location.clone()); let creator = Box::new(VersionedLocation::from(origin_location.clone())); let relay_token_asset_id: Location = Location::parent(); diff --git a/bridges/snowbridge/pallets/system-v2/src/mock.rs b/bridges/snowbridge/pallets/system-v2/src/mock.rs index f3363f50409fb..1a3fa0f0077cf 100644 --- a/bridges/snowbridge/pallets/system-v2/src/mock.rs +++ b/bridges/snowbridge/pallets/system-v2/src/mock.rs @@ -84,7 +84,7 @@ parameter_types! { pub AssetHubParaId: ParaId = ParaId::new(1000); pub TestParaId: u32 = 2000; pub RootLocation: Location = Location::parent(); - pub FrontendLocation: Location = Location::new(1, [Parachain(1000), PalletInstance(80)]); + pub FrontendLocation: Location = Location::new(1, [Parachain(1000), PalletInstance(36)]); } #[cfg(feature = "runtime-benchmarks")] diff --git a/bridges/snowbridge/primitives/inbound-queue/src/lib.rs b/bridges/snowbridge/primitives/inbound-queue/src/lib.rs index ea7323e30acb5..e44d98b698048 100644 --- a/bridges/snowbridge/primitives/inbound-queue/src/lib.rs +++ b/bridges/snowbridge/primitives/inbound-queue/src/lib.rs @@ -5,21 +5,13 @@ pub mod v1; pub mod v2; use codec::Encode; -use snowbridge_beacon_primitives::BeaconHeader; -use sp_core::{blake2_256, RuntimeDebug, H256}; +use sp_core::blake2_256; use sp_std::marker::PhantomData; use xcm::prelude::{AccountKey20, Ethereum, GlobalConsensus, Location}; use xcm_executor::traits::ConvertLocation; pub use snowbridge_verification_primitives::*; -#[derive(Clone, RuntimeDebug)] -pub struct InboundQueueFixture { - pub event: EventProof, - pub finalized_header: BeaconHeader, - pub block_roots_root: H256, -} - /// DEPRECATED in favor of [xcm_builder::ExternalConsensusLocationsConverterFor] pub struct EthereumLocationsConverterFor(PhantomData); impl ConvertLocation for EthereumLocationsConverterFor diff --git a/bridges/snowbridge/primitives/outbound-queue/src/v1/message.rs b/bridges/snowbridge/primitives/outbound-queue/src/v1/message.rs index fcfb9d787ff47..9f96f05e0bf0e 100644 --- a/bridges/snowbridge/primitives/outbound-queue/src/v1/message.rs +++ b/bridges/snowbridge/primitives/outbound-queue/src/v1/message.rs @@ -136,12 +136,12 @@ impl Command { match self { Command::AgentExecute { .. } => 0, Command::Upgrade { .. } => 1, - Command::SetOperatingMode { .. } => 2, - Command::SetTokenTransferFees { .. } => 3, - Command::SetPricingParameters { .. } => 4, - Command::UnlockNativeToken { .. } => 5, - Command::RegisterForeignToken { .. } => 6, - Command::MintForeignToken { .. } => 7, + Command::SetOperatingMode { .. } => 5, + Command::SetTokenTransferFees { .. } => 7, + Command::SetPricingParameters { .. } => 8, + Command::UnlockNativeToken { .. } => 9, + Command::RegisterForeignToken { .. } => 10, + Command::MintForeignToken { .. } => 11, } } diff --git a/bridges/snowbridge/primitives/outbound-queue/src/v2/converter/convert.rs b/bridges/snowbridge/primitives/outbound-queue/src/v2/converter/convert.rs index eafb113eb7d45..e8b38c4e698f4 100644 --- a/bridges/snowbridge/primitives/outbound-queue/src/v2/converter/convert.rs +++ b/bridges/snowbridge/primitives/outbound-queue/src/v2/converter/convert.rs @@ -45,6 +45,7 @@ pub enum XcmConverterError { TransactParamsDecodeFailed, FeeAssetResolutionFailed, CallContractValueInsufficient, + NoCommands, } macro_rules! match_expression { @@ -260,11 +261,6 @@ where ) .ok_or(BeneficiaryResolutionFailed)?; - // Make sure there are reserved assets. - if enas.is_none() && pnas.is_none() { - return Err(NoReserveAssets); - } - let mut commands: Vec = Vec::new(); // ENA transfer commands @@ -298,6 +294,8 @@ where } } + ensure!(commands.len() > 0, NoCommands); + // ensure SetTopic exists let topic_id = match_expression!(self.next()?, SetTopic(id), id).ok_or(SetTopicExpected)?; diff --git a/bridges/snowbridge/primitives/outbound-queue/src/v2/converter/tests.rs b/bridges/snowbridge/primitives/outbound-queue/src/v2/converter/tests.rs index 1ea980c1d9139..092137c80c6b0 100644 --- a/bridges/snowbridge/primitives/outbound-queue/src/v2/converter/tests.rs +++ b/bridges/snowbridge/primitives/outbound-queue/src/v2/converter/tests.rs @@ -801,7 +801,7 @@ fn xcm_converter_convert_without_withdraw_asset_yields_deposit_expected() { } #[test] -fn xcm_converter_convert_without_assets_yields_no_reserve_assets() { +fn xcm_converter_convert_without_assets_yields_no_commands() { let network = BridgedNetwork::get(); let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); @@ -825,7 +825,7 @@ fn xcm_converter_convert_without_assets_yields_no_reserve_assets() { let mut converter = XcmConverter::::new(&message, network); let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::NoReserveAssets)); + assert_eq!(result.err(), Some(XcmConverterError::NoCommands)); } #[test] diff --git a/bridges/snowbridge/primitives/outbound-queue/src/v2/delivery_receipt.rs b/bridges/snowbridge/primitives/outbound-queue/src/v2/delivery_receipt.rs index 98410eef3493c..852de849177b1 100644 --- a/bridges/snowbridge/primitives/outbound-queue/src/v2/delivery_receipt.rs +++ b/bridges/snowbridge/primitives/outbound-queue/src/v2/delivery_receipt.rs @@ -13,10 +13,7 @@ sol! { /// Delivery receipt #[derive(Clone, RuntimeDebug)] -pub struct DeliveryReceipt -where - AccountId: From<[u8; 32]> + Clone, -{ +pub struct DeliveryReceipt { /// The address of the outbound queue on Ethereum that emitted this message as an event log pub gateway: H160, /// The nonce of the dispatched message @@ -26,7 +23,7 @@ where /// Delivery status pub success: bool, /// The reward address - pub reward_address: AccountId, + pub reward_address: [u8; 32], } #[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)] @@ -35,10 +32,7 @@ pub enum DeliveryReceiptDecodeError { DecodeAccountFailed, } -impl TryFrom<&Log> for DeliveryReceipt -where - AccountId: From<[u8; 32]> + Clone, -{ +impl TryFrom<&Log> for DeliveryReceipt { type Error = DeliveryReceiptDecodeError; fn try_from(log: &Log) -> Result { @@ -47,14 +41,12 @@ where let event = InboundMessageDispatched::decode_raw_log(topics, &log.data, true) .map_err(|_| DeliveryReceiptDecodeError::DecodeLogFailed)?; - let account: AccountId = AccountId::from(event.reward_address.0); - Ok(Self { gateway: log.address, nonce: event.nonce, topic: H256::from_slice(event.topic.as_ref()), success: event.success, - reward_address: account, + reward_address: event.reward_address.0, }) } } diff --git a/bridges/snowbridge/primitives/verification/src/lib.rs b/bridges/snowbridge/primitives/verification/src/lib.rs index f8414398af327..1e508f48da437 100644 --- a/bridges/snowbridge/primitives/verification/src/lib.rs +++ b/bridges/snowbridge/primitives/verification/src/lib.rs @@ -5,7 +5,7 @@ use codec::{Decode, DecodeWithMemTracking, Encode}; use frame_support::PalletError; use scale_info::TypeInfo; -use snowbridge_beacon_primitives::ExecutionProof; +use snowbridge_beacon_primitives::{BeaconHeader, ExecutionProof}; use sp_core::{RuntimeDebug, H160, H256}; use sp_std::prelude::*; @@ -70,3 +70,10 @@ pub struct Proof { // Proof that an execution header was finalized by the beacon chain pub execution_proof: ExecutionProof, } + +#[derive(Clone, RuntimeDebug)] +pub struct EventFixture { + pub event: EventProof, + pub finalized_header: BeaconHeader, + pub block_roots_root: H256, +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs index 06a16443f59f7..6a8271524155c 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -21,7 +21,7 @@ use hex_literal::hex; use rococo_westend_system_emulated_network::BridgeHubRococoParaSender as BridgeHubRococoSender; use snowbridge_inbound_queue_primitives::{ v1::{Command, Destination, MessageV1, VersionedMessage}, - InboundQueueFixture, + EventFixture, }; use snowbridge_outbound_queue_primitives::OperatingMode; use snowbridge_pallet_inbound_queue_fixtures::{ @@ -57,7 +57,7 @@ pub enum SnowbridgeControl { Control(ControlCall), } -pub fn send_inbound_message(fixture: InboundQueueFixture) -> DispatchResult { +pub fn send_inbound_message(fixture: EventFixture) -> DispatchResult { EthereumBeaconClient::store_finalized_header( fixture.finalized_header, fixture.block_roots_root, diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs index 724444a3f7101..eef3081f5a8c2 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs @@ -31,7 +31,7 @@ use rococo_westend_system_emulated_network::{ use snowbridge_core::{AssetMetadata, TokenIdOf}; use snowbridge_inbound_queue_primitives::{ v1::{Command, Destination, MessageV1, VersionedMessage}, - InboundQueueFixture, + EventFixture, }; use snowbridge_pallet_inbound_queue_fixtures::send_native_eth::make_send_native_eth_message; use sp_core::H256; @@ -61,7 +61,7 @@ pub enum SnowbridgeControl { Control(ControlCall), } -pub fn send_inbound_message(fixture: InboundQueueFixture) -> DispatchResult { +pub fn send_inbound_message(fixture: EventFixture) -> DispatchResult { EthereumBeaconClient::store_finalized_header( fixture.finalized_header, fixture.block_roots_root, diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_v2_outbound.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_v2_outbound.rs index ec25a499290d5..f3cf7bb0b1890 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_v2_outbound.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge_v2_outbound.rs @@ -38,7 +38,7 @@ pub enum EthereumSystemFrontendCall { #[allow(clippy::large_enum_variant)] #[derive(Encode, Decode, Debug, PartialEq, Clone, TypeInfo)] pub enum EthereumSystemFrontend { - #[codec(index = 80)] + #[codec(index = 36)] EthereumSystemFrontend(EthereumSystemFrontendCall), } @@ -106,8 +106,8 @@ fn send_weth_from_asset_hub_to_ethereum() { let receipt = DeliveryReceipt { gateway: EthereumGatewayAddress::get(), nonce: 0, + reward_address: reward_account.into(), topic: H256::zero(), - reward_address: reward_account, success: true, }; @@ -262,8 +262,8 @@ fn transfer_relay_token_from_ah() { let receipt = DeliveryReceipt { gateway: EthereumGatewayAddress::get(), nonce: 0, + reward_address: reward_account.into(), topic: H256::zero(), - reward_address: reward_account, success: true, }; @@ -349,8 +349,8 @@ fn send_weth_and_dot_from_asset_hub_to_ethereum() { let receipt = DeliveryReceipt { gateway: EthereumGatewayAddress::get(), nonce: 0, + reward_address: reward_account.into(), topic: H256::zero(), - reward_address: reward_account, success: true, }; @@ -445,8 +445,8 @@ fn transact_with_agent_from_asset_hub() { let receipt = DeliveryReceipt { gateway: EthereumGatewayAddress::get(), nonce: 0, + reward_address: reward_account.into(), topic: H256::zero(), - reward_address: reward_account, success: true, }; @@ -462,6 +462,90 @@ fn transact_with_agent_from_asset_hub() { }); } +#[test] +fn transact_with_agent_from_asset_hub_without_any_asset_transfer() { + fund_on_bh(); + + register_assets_on_ah(); + + fund_on_ah(); + + AssetHubWestend::execute_with(|| { + type RuntimeOrigin = ::RuntimeOrigin; + + let local_fee_asset = + Asset { id: AssetId(Location::parent()), fun: Fungible(LOCAL_FEE_AMOUNT_IN_DOT) }; + + let remote_fee_asset = + Asset { id: AssetId(ethereum()), fun: Fungible(REMOTE_FEE_AMOUNT_IN_ETHER) }; + + let assets = vec![local_fee_asset.clone(), remote_fee_asset.clone()]; + + let beneficiary = + Location::new(0, [AccountKey20 { network: None, key: AGENT_ADDRESS.into() }]); + + let transact_info = + ContractCall::V1 { target: Default::default(), calldata: vec![], gas: 40000, value: 0 }; + + let xcms = VersionedXcm::from(Xcm(vec![ + WithdrawAsset(assets.clone().into()), + PayFees { asset: local_fee_asset.clone() }, + InitiateTransfer { + destination: ethereum(), + remote_fees: Some(AssetTransferFilter::ReserveWithdraw(Definite( + remote_fee_asset.clone().into(), + ))), + preserve_origin: true, + assets: BoundedVec::new(), + remote_xcm: Xcm(vec![ + DepositAsset { assets: Wild(AllCounted(2)), beneficiary }, + Transact { + origin_kind: OriginKind::SovereignAccount, + fallback_max_weight: None, + call: transact_info.encode().into(), + }, + ]), + }, + ])); + + ::PolkadotXcm::execute( + RuntimeOrigin::signed(AssetHubWestendSender::get()), + bx!(xcms), + Weight::from(EXECUTION_WEIGHT), + ) + .unwrap(); + }); + + BridgeHubWestend::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + // Check that Ethereum message was queue in the Outbound Queue + assert_expected_events!( + BridgeHubWestend, + vec![RuntimeEvent::EthereumOutboundQueueV2(snowbridge_pallet_outbound_queue_v2::Event::MessageQueued{ .. }) => {},] + ); + + let relayer = BridgeHubWestendSender::get(); + let reward_account = AssetHubWestendReceiver::get(); + let receipt = DeliveryReceipt { + gateway: EthereumGatewayAddress::get(), + nonce: 0, + reward_address: reward_account.into(), + success: true, + topic: Default::default(), + }; + + // Submit a delivery receipt + assert_ok!(EthereumOutboundQueueV2::process_delivery_receipt(relayer, receipt)); + + assert_expected_events!( + BridgeHubWestend, + vec![ + RuntimeEvent::BridgeRelayers(pallet_bridge_relayers::Event::RewardRegistered { .. }) => {}, + ] + ); + }); +} + #[test] fn register_token_from_penpal() { fund_on_bh(); @@ -562,8 +646,8 @@ fn register_token_from_penpal() { let receipt = DeliveryReceipt { gateway: EthereumGatewayAddress::get(), nonce: 0, + reward_address: reward_account.into(), topic: H256::zero(), - reward_address: reward_account, success: true, }; @@ -573,7 +657,7 @@ fn register_token_from_penpal() { assert_expected_events!( BridgeHubWestend, vec![ - RuntimeEvent::EthereumOutboundQueueV2(snowbridge_pallet_outbound_queue_v2::Event::MessageDeliveryProofReceived { .. }) => {}, + RuntimeEvent::EthereumOutboundQueueV2(snowbridge_pallet_outbound_queue_v2::Event::MessageDelivered { .. }) => {}, ] ); }); @@ -727,8 +811,8 @@ fn invalid_nonce_for_delivery_receipt_fails() { let receipt = DeliveryReceipt { gateway: EthereumGatewayAddress::get(), nonce: 0, + reward_address: reward_account.into(), topic: H256::zero(), - reward_address: reward_account, success: true, }; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/bridge_to_ethereum_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/bridge_to_ethereum_config.rs index 76eed793e2dcc..7d3f2346e1fa3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/bridge_to_ethereum_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/bridge_to_ethereum_config.rs @@ -26,7 +26,7 @@ use frame_support::{parameter_types, traits::EitherOf}; use frame_system::EnsureRootWithSuccess; use parachains_common::AssetIdForTrustBackedAssets; use snowbridge_runtime_common::{ForeignAssetOwner, LocalAssetOwner}; -use testnet_parachains_constants::westend::snowbridge::EthereumNetwork; +use testnet_parachains_constants::westend::snowbridge::{EthereumNetwork, FRONTEND_PALLET_INDEX}; use xcm::prelude::{Asset, InteriorLocation, Location, PalletInstance, Parachain}; use xcm_executor::XcmExecutor; @@ -86,7 +86,7 @@ parameter_types! { ); pub storage DeliveryFee: Asset = (Location::parent(), 80_000_000_000u128).into(); pub BridgeHubLocation: Location = Location::new(1, [Parachain(westend_runtime_constants::system_parachain::BRIDGE_HUB_ID)]); - pub SystemFrontendPalletLocation: InteriorLocation = [PalletInstance(80)].into(); + pub SystemFrontendPalletLocation: InteriorLocation = [PalletInstance(FRONTEND_PALLET_INDEX)].into(); pub const RootLocation: Location = Location::here(); } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index fb9d647dba25a..bdded9985a3f7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1153,6 +1153,8 @@ construct_runtime!( // Bridge utilities. ToRococoXcmRouter: pallet_xcm_bridge_hub_router:: = 34, MessageQueue: pallet_message_queue = 35, + // Snowbridge + SnowbridgeSystemFrontend: snowbridge_pallet_system_frontend = 36, // Handy utilities. Utility: pallet_utility = 40, @@ -1177,9 +1179,6 @@ construct_runtime!( StateTrieMigration: pallet_state_trie_migration = 70, - // Snowbridge - SnowbridgeSystemFrontend: snowbridge_pallet_system_frontend = 80, - // TODO: the pallet instance should be removed once all pools have migrated // to the new account IDs. AssetConversionMigration: pallet_asset_conversion_ops = 200, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_ethereum_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_ethereum_config.rs index 6428b08598ae4..fa031fa9532dd 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_ethereum_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_ethereum_config.rs @@ -134,11 +134,7 @@ impl snowbridge_pallet_inbound_queue_v2::Config for Runtime { type Helper = Runtime; type WeightInfo = crate::weights::snowbridge_pallet_inbound_queue_v2::WeightInfo; type AssetHubParaId = ConstU32; - type EthereumNetwork = EthereumNetwork; type XcmExecutor = XcmExecutor; - type Token = Balances; - type Balance = Balance; - type WeightToFee = WeightToFee; type MessageConverter = snowbridge_inbound_queue_primitives::v2::MessageToXcm< CreateAssetCall, CreateForeignAssetDeposit, @@ -191,12 +187,12 @@ impl snowbridge_pallet_outbound_queue_v2::Config for Runtime { type Verifier = snowbridge_pallet_ethereum_client::Pallet; type GatewayAddress = EthereumGatewayAddress; type WeightInfo = crate::weights::snowbridge_pallet_outbound_queue_v2::WeightInfo; - type ConvertAssetId = EthereumSystem; type EthereumNetwork = EthereumNetwork; type RewardKind = BridgeReward; - type DefaultRewardKind = SnowbridgeReward; type RewardPayment = BridgeRelayers; + #[cfg(feature = "runtime-benchmarks")] + type Helper = Runtime; } #[cfg(any(feature = "std", feature = "fast-runtime", feature = "runtime-benchmarks", test))] @@ -313,7 +309,8 @@ pub mod benchmark_helpers { use hex_literal::hex; use snowbridge_beacon_primitives::BeaconHeader; use snowbridge_pallet_inbound_queue::BenchmarkHelper; - use snowbridge_pallet_inbound_queue_v2::BenchmarkHelper as BenchmarkHelperV2; + use snowbridge_pallet_inbound_queue_v2::BenchmarkHelper as InboundQueueBenchmarkHelperV2; + use snowbridge_pallet_outbound_queue_v2::BenchmarkHelper as OutboundQueueBenchmarkHelperV2; use sp_core::H256; use xcm::latest::{Assets, Location, SendError, SendResult, SendXcm, Xcm, XcmHash}; @@ -331,7 +328,13 @@ pub mod benchmark_helpers { } } - impl BenchmarkHelperV2 for Runtime { + impl InboundQueueBenchmarkHelperV2 for Runtime { + fn initialize_storage(beacon_header: BeaconHeader, block_roots_root: H256) { + EthereumBeaconClient::store_finalized_header(beacon_header, block_roots_root).unwrap(); + } + } + + impl OutboundQueueBenchmarkHelperV2 for Runtime { fn initialize_storage(beacon_header: BeaconHeader, block_roots_root: H256) { EthereumBeaconClient::store_finalized_header(beacon_header, block_roots_root).unwrap(); } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/snowbridge_pallet_outbound_queue_v2.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/snowbridge_pallet_outbound_queue_v2.rs index 24533f9e871d3..0f1a9d360e714 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/snowbridge_pallet_outbound_queue_v2.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/snowbridge_pallet_outbound_queue_v2.rs @@ -16,7 +16,7 @@ //! Autogenerated weights for `snowbridge_pallet_outbound_queue_v2` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-03-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-03-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `yangdebijibendiannao.local`, CPU: `` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 @@ -71,8 +71,8 @@ impl snowbridge_pallet_outbound_queue_v2::WeightInfo fo // Proof Size summary in bytes: // Measured: `1128` // Estimated: `2613` - // Minimum execution time: 24_000_000 picoseconds. - Weight::from_parts(25_000_000, 0) + // Minimum execution time: 25_000_000 picoseconds. + Weight::from_parts(26_000_000, 0) .saturating_add(Weight::from_parts(0, 2613)) .saturating_add(T::DbWeight::get().reads(1)) } @@ -82,8 +82,8 @@ impl snowbridge_pallet_outbound_queue_v2::WeightInfo fo // Proof Size summary in bytes: // Measured: `135` // Estimated: `1620` - // Minimum execution time: 8_000_000 picoseconds. - Weight::from_parts(9_000_000, 0) + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(10_000_000, 0) .saturating_add(Weight::from_parts(0, 1620)) .saturating_add(T::DbWeight::get().reads(1)) } @@ -100,29 +100,6 @@ impl snowbridge_pallet_outbound_queue_v2::WeightInfo fo .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(2)) } - - /// Storage: `EthereumBeaconClient::LatestFinalizedBlockRoot` (r:1 w:0) - /// Proof: `EthereumBeaconClient::LatestFinalizedBlockRoot` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) - /// Storage: `EthereumBeaconClient::FinalizedBeaconState` (r:1 w:0) - /// Proof: `EthereumBeaconClient::FinalizedBeaconState` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: UNKNOWN KEY `0xaed97c7854d601808b98ae43079dafb3` (r:1 w:0) - /// Proof: UNKNOWN KEY `0xaed97c7854d601808b98ae43079dafb3` (r:1 w:0) - /// Storage: `EthereumOutboundQueueV2::PendingOrders` (r:1 w:1) - /// Proof: `EthereumOutboundQueueV2::PendingOrders` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) - /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) - /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `BridgeRelayers::RelayerRewards` (r:1 w:1) - /// Proof: `BridgeRelayers::RelayerRewards` (`max_values`: None, `max_size`: Some(74), added: 2549, mode: `MaxEncodedLen`) - fn submit_delivery_receipt() -> Weight { - // Proof Size summary in bytes: - // Measured: `309` - // Estimated: `3774` - // Minimum execution time: 59_000_000 picoseconds. - Weight::from_parts(60_000_000, 0) - .saturating_add(Weight::from_parts(0, 3774)) - .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(2)) - } /// Storage: `EthereumOutboundQueueV2::Nonce` (r:1 w:1) /// Proof: `EthereumOutboundQueueV2::Nonce` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) /// Storage: `EthereumOutboundQueueV2::PendingOrders` (r:0 w:32) @@ -135,10 +112,28 @@ impl snowbridge_pallet_outbound_queue_v2::WeightInfo fo // Proof Size summary in bytes: // Measured: `113` // Estimated: `1493` - // Minimum execution time: 500_000_000 picoseconds. - Weight::from_parts(506_000_000, 0) + // Minimum execution time: 502_000_000 picoseconds. + Weight::from_parts(521_000_000, 0) .saturating_add(Weight::from_parts(0, 1493)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(35)) } + /// Storage: `EthereumBeaconClient::LatestFinalizedBlockRoot` (r:1 w:0) + /// Proof: `EthereumBeaconClient::LatestFinalizedBlockRoot` (`max_values`: Some(1), `max_size`: Some(32), added: 527, mode: `MaxEncodedLen`) + /// Storage: `EthereumBeaconClient::FinalizedBeaconState` (r:1 w:0) + /// Proof: `EthereumBeaconClient::FinalizedBeaconState` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0xaed97c7854d601808b98ae43079dafb3` (r:1 w:0) + /// Proof: UNKNOWN KEY `0xaed97c7854d601808b98ae43079dafb3` (r:1 w:0) + /// Storage: `EthereumOutboundQueueV2::PendingOrders` (r:1 w:1) + /// Proof: `EthereumOutboundQueueV2::PendingOrders` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + fn submit_delivery_receipt() -> Weight { + // Proof Size summary in bytes: + // Measured: `320` + // Estimated: `3785` + // Minimum execution time: 67_000_000 picoseconds. + Weight::from_parts(68_000_000, 0) + .saturating_add(Weight::from_parts(0, 3785)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } } diff --git a/cumulus/parachains/runtimes/constants/src/westend.rs b/cumulus/parachains/runtimes/constants/src/westend.rs index cc72b6c74aa85..97e078770ce37 100644 --- a/cumulus/parachains/runtimes/constants/src/westend.rs +++ b/cumulus/parachains/runtimes/constants/src/westend.rs @@ -178,7 +178,7 @@ pub mod snowbridge { pub const INBOUND_QUEUE_PALLET_INDEX_V1: u8 = 80; pub const INBOUND_QUEUE_PALLET_INDEX_V2: u8 = 91; - pub const FRONTEND_PALLET_INDEX: u8 = 80; + pub const FRONTEND_PALLET_INDEX: u8 = 36; parameter_types! { /// Network and location for the Ethereum chain. On Westend, the Ethereum chain bridged