Adds Snowbridge to Rococo runtime (#2522)

# Description

Adds Snowbridge to the Rococo bridge hub runtime. Includes config
changes required in Rococo asset hub.

---------

Co-authored-by: Alistair Singh <alistair.singh7@gmail.com>
Co-authored-by: ron <yrong1997@gmail.com>
Co-authored-by: Vincent Geddes <vincent.geddes@hey.com>
Co-authored-by: claravanstaden <Cats 4 life!>
This commit is contained in:
Clara van Staden
2023-12-21 18:06:36 +02:00
committed by GitHub
parent 9f5221cc2f
commit 18d53dbf91
151 changed files with 19379 additions and 149 deletions
@@ -38,6 +38,7 @@ decl_test_parachains! {
XcmpMessageHandler: asset_hub_rococo_runtime::XcmpQueue,
LocationToAccountId: asset_hub_rococo_runtime::xcm_config::LocationToAccountId,
ParachainInfo: asset_hub_rococo_runtime::ParachainInfo,
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
},
pallets = {
PolkadotXcm: asset_hub_rococo_runtime::PolkadotXcm,
@@ -38,6 +38,7 @@ decl_test_parachains! {
XcmpMessageHandler: asset_hub_westend_runtime::XcmpQueue,
LocationToAccountId: asset_hub_westend_runtime::xcm_config::LocationToAccountId,
ParachainInfo: asset_hub_westend_runtime::ParachainInfo,
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
},
pallets = {
PolkadotXcm: asset_hub_westend_runtime::PolkadotXcm,
@@ -25,3 +25,11 @@ parachains-common = { path = "../../../../../../../parachains/common" }
cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false }
emulated-integration-tests-common = { path = "../../../../common", default-features = false }
bridge-hub-rococo-runtime = { path = "../../../../../../runtimes/bridge-hubs/bridge-hub-rococo" }
bridge-hub-common = { path = "../../../../../../runtimes/bridge-hubs/common", default-features = false }
# Snowbridge
snowbridge-core = { path = "../../../../../../../../bridges/snowbridge/parachain/primitives/core", default-features = false }
snowbridge-router-primitives = { path = "../../../../../../../../bridges/snowbridge/parachain/primitives/router", default-features = false }
snowbridge-system = { path = "../../../../../../../../bridges/snowbridge/parachain/pallets/system", default-features = false }
snowbridge-inbound-queue = { path = "../../../../../../../../bridges/snowbridge/parachain/pallets/inbound-queue", default-features = false }
snowbridge-outbound-queue = { path = "../../../../../../../../bridges/snowbridge/parachain/pallets/outbound-queue", default-features = false }
@@ -22,6 +22,7 @@ use emulated_integration_tests_common::{
};
use parachains_common::Balance;
pub const ASSETHUB_PARA_ID: u32 = 1000;
pub const PARA_ID: u32 = 1013;
pub const ED: Balance = parachains_common::rococo::currency::EXISTENTIAL_DEPOSIT;
@@ -64,6 +65,11 @@ pub fn genesis() -> Storage {
owner: Some(get_account_id_from_seed::<sr25519::Public>(accounts::BOB)),
..Default::default()
},
ethereum_system: bridge_hub_rococo_runtime::EthereumSystemConfig {
para_id: PARA_ID.into(),
asset_hub_para_id: ASSETHUB_PARA_ID.into(),
..Default::default()
},
..Default::default()
};
@@ -36,10 +36,14 @@ decl_test_parachains! {
XcmpMessageHandler: bridge_hub_rococo_runtime::XcmpQueue,
LocationToAccountId: bridge_hub_rococo_runtime::xcm_config::LocationToAccountId,
ParachainInfo: bridge_hub_rococo_runtime::ParachainInfo,
MessageOrigin: bridge_hub_common::AggregateMessageOrigin,
},
pallets = {
PolkadotXcm: bridge_hub_rococo_runtime::PolkadotXcm,
Balances: bridge_hub_rococo_runtime::Balances,
EthereumSystem: bridge_hub_rococo_runtime::EthereumSystem,
EthereumInboundQueue: bridge_hub_rococo_runtime::EthereumInboundQueue,
EthereumOutboundQueue: bridge_hub_rococo_runtime::EthereumOutboundQueue,
}
},
}
@@ -25,3 +25,4 @@ parachains-common = { path = "../../../../../../../parachains/common" }
cumulus-primitives-core = { path = "../../../../../../../primitives/core", default-features = false }
emulated-integration-tests-common = { path = "../../../../common", default-features = false }
bridge-hub-westend-runtime = { path = "../../../../../../runtimes/bridge-hubs/bridge-hub-westend" }
bridge-hub-common = { path = "../../../../../../runtimes/bridge-hubs/common", default-features = false }
@@ -36,6 +36,7 @@ decl_test_parachains! {
XcmpMessageHandler: bridge_hub_westend_runtime::XcmpQueue,
LocationToAccountId: bridge_hub_westend_runtime::xcm_config::LocationToAccountId,
ParachainInfo: bridge_hub_westend_runtime::ParachainInfo,
MessageOrigin: bridge_hub_common::AggregateMessageOrigin,
},
pallets = {
PolkadotXcm: bridge_hub_westend_runtime::PolkadotXcm,
@@ -36,6 +36,7 @@ decl_test_parachains! {
XcmpMessageHandler: collectives_westend_runtime::XcmpQueue,
LocationToAccountId: collectives_westend_runtime::xcm_config::LocationToAccountId,
ParachainInfo: collectives_westend_runtime::ParachainInfo,
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
},
pallets = {
PolkadotXcm: collectives_westend_runtime::PolkadotXcm,
@@ -40,10 +40,12 @@ decl_test_parachains! {
XcmpMessageHandler: penpal_runtime::XcmpQueue,
LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId,
ParachainInfo: penpal_runtime::ParachainInfo,
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
},
pallets = {
PolkadotXcm: penpal_runtime::PolkadotXcm,
Assets: penpal_runtime::Assets,
ForeignAssets: penpal_runtime::ForeignAssets,
Balances: penpal_runtime::Balances,
}
},
@@ -57,10 +59,12 @@ decl_test_parachains! {
XcmpMessageHandler: penpal_runtime::XcmpQueue,
LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId,
ParachainInfo: penpal_runtime::ParachainInfo,
MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin,
},
pallets = {
PolkadotXcm: penpal_runtime::PolkadotXcm,
Assets: penpal_runtime::Assets,
ForeignAssets: penpal_runtime::ForeignAssets,
Balances: penpal_runtime::Balances,
}
},
@@ -19,3 +19,4 @@ asset-hub-rococo-emulated-chain = { path = "../../chains/parachains/assets/asset
asset-hub-westend-emulated-chain = { path = "../../chains/parachains/assets/asset-hub-westend" }
bridge-hub-rococo-emulated-chain = { path = "../../chains/parachains/bridges/bridge-hub-rococo" }
bridge-hub-westend-emulated-chain = { path = "../../chains/parachains/bridges/bridge-hub-westend" }
penpal-emulated-chain = { path = "../../chains/parachains/testing/penpal" }
@@ -17,6 +17,7 @@ pub use asset_hub_rococo_emulated_chain;
pub use asset_hub_westend_emulated_chain;
pub use bridge_hub_rococo_emulated_chain;
pub use bridge_hub_westend_emulated_chain;
pub use penpal_emulated_chain;
pub use rococo_emulated_chain;
pub use westend_emulated_chain;
@@ -24,6 +25,7 @@ use asset_hub_rococo_emulated_chain::AssetHubRococo;
use asset_hub_westend_emulated_chain::AssetHubWestend;
use bridge_hub_rococo_emulated_chain::BridgeHubRococo;
use bridge_hub_westend_emulated_chain::BridgeHubWestend;
use penpal_emulated_chain::PenpalA;
use rococo_emulated_chain::Rococo;
use westend_emulated_chain::Westend;
@@ -43,6 +45,7 @@ decl_test_networks! {
parachains = vec![
AssetHubRococo,
BridgeHubRococo,
PenpalA,
],
bridge = RococoWestendMockBridge
@@ -92,5 +95,6 @@ decl_test_sender_receiver_accounts_parameter_types! {
BridgeHubRococoPara { sender: ALICE, receiver: BOB },
WestendRelay { sender: ALICE, receiver: BOB },
AssetHubWestendPara { sender: ALICE, receiver: BOB },
BridgeHubWestendPara { sender: ALICE, receiver: BOB }
BridgeHubWestendPara { sender: ALICE, receiver: BOB },
PenpalAPara { sender: ALICE, receiver: BOB }
}
@@ -12,8 +12,12 @@ workspace = true
[dependencies]
codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false }
scale-info = { version = "2.10.0", default-features = false, features = ["derive"] }
hex = "0.4.3"
hex-literal = "0.4.1"
# Substrate
sp-core = { path = "../../../../../../../substrate/primitives/core", default-features = false }
frame-support = { path = "../../../../../../../substrate/frame/support", default-features = false }
pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-features = false }
pallet-balances = { path = "../../../../../../../substrate/frame/balances", default-features = false }
@@ -37,3 +41,14 @@ cumulus-pallet-dmp-queue = { path = "../../../../../../pallets/dmp-queue", defau
bridge-hub-rococo-runtime = { path = "../../../../../../parachains/runtimes/bridge-hubs/bridge-hub-rococo", default-features = false }
emulated-integration-tests-common = { path = "../../../common", default-features = false }
rococo-westend-system-emulated-network = { path = "../../../networks/rococo-westend-system" }
penpal-runtime = { path = "../../../../../runtimes/testing/penpal", default-features = false }
rococo-system-emulated-network = { path = "../../../networks/rococo-system" }
asset-hub-rococo-runtime = { path = "../../../../../runtimes/assets/asset-hub-rococo", default-features = false }
# Snowbridge
snowbridge-core = { path = "../../../../../../../bridges/snowbridge/parachain/primitives/core", default-features = false }
snowbridge-router-primitives = { path = "../../../../../../../bridges/snowbridge/parachain/primitives/router", default-features = false }
snowbridge-system = { path = "../../../../../../../bridges/snowbridge/parachain/pallets/system", default-features = false }
snowbridge-inbound-queue = { path = "../../../../../../../bridges/snowbridge/parachain/pallets/inbound-queue", default-features = false }
snowbridge-outbound-queue = { path = "../../../../../../../bridges/snowbridge/parachain/pallets/outbound-queue", default-features = false }
snowbridge-rococo-common = { path = "../../../../../../../bridges/snowbridge/parachain/runtime/rococo-common", default-features = false }
@@ -43,6 +43,11 @@ pub use emulated_integration_tests_common::{
PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3,
};
pub use parachains_common::{AccountId, Balance};
pub use rococo_system_emulated_network::{
penpal_emulated_chain::PenpalAParaPallet as PenpalAPallet,
BridgeHubRococoParaReceiver as BridgeHubRococoReceiver, PenpalAPara as PenpalA,
PenpalAParaReceiver as PenpalAReceiver, PenpalAParaSender as PenpalASender,
};
pub use rococo_westend_system_emulated_network::{
asset_hub_rococo_emulated_chain::{
genesis::ED as ASSET_HUB_ROCOCO_ED, AssetHubRococoParaPallet as AssetHubRococoPallet,
@@ -53,12 +58,13 @@ pub use rococo_westend_system_emulated_network::{
bridge_hub_rococo_emulated_chain::{
genesis::ED as BRIDGE_HUB_ROCOCO_ED, BridgeHubRococoParaPallet as BridgeHubRococoPallet,
},
rococo_emulated_chain::RococoRelayPallet as RococoPallet,
rococo_emulated_chain::{genesis::ED as ROCOCO_ED, RococoRelayPallet as RococoPallet},
AssetHubRococoPara as AssetHubRococo, AssetHubRococoParaReceiver as AssetHubRococoReceiver,
AssetHubRococoParaSender as AssetHubRococoSender, AssetHubWestendPara as AssetHubWestend,
AssetHubWestendParaReceiver as AssetHubWestendReceiver, BridgeHubRococoPara as BridgeHubRococo,
BridgeHubRococoParaSender as BridgeHubRococoSender, BridgeHubWestendPara as BridgeHubWestend,
RococoRelay as Rococo,
RococoRelay as Rococo, RococoRelayReceiver as RococoReceiver,
RococoRelaySender as RococoSender,
};
pub const ASSET_ID: u32 = 1;
@@ -17,6 +17,7 @@ use crate::*;
mod asset_transfers;
mod send_xcm;
mod snowbridge;
mod teleport;
pub(crate) fn asset_hub_westend_location() -> MultiLocation {
@@ -0,0 +1,505 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::*;
use codec::{Decode, Encode};
use emulated_integration_tests_common::xcm_emulator::ConvertLocation;
use frame_support::pallet_prelude::TypeInfo;
use hex_literal::hex;
use snowbridge_core::outbound::OperatingMode;
use snowbridge_rococo_common::EthereumNetwork;
use snowbridge_router_primitives::inbound::{
Command, Destination, GlobalConsensusEthereumConvertsFor, MessageV1, VersionedMessage,
};
use snowbridge_system;
use sp_core::H256;
const INITIAL_FUND: u128 = 5_000_000_000 * ROCOCO_ED;
const CHAIN_ID: u64 = 11155111;
const TREASURY_ACCOUNT: [u8; 32] =
hex!("6d6f646c70792f74727372790000000000000000000000000000000000000000");
const WETH: [u8; 20] = hex!("87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A7d");
const ETHEREUM_DESTINATION_ADDRESS: [u8; 20] = hex!("44a57ee2f2FCcb85FDa2B0B18EBD0D8D2333700e");
const XCM_FEE: u128 = 4_000_000_000;
#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
pub enum ControlCall {
#[codec(index = 3)]
CreateAgent,
#[codec(index = 4)]
CreateChannel { mode: OperatingMode },
}
#[allow(clippy::large_enum_variant)]
#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
pub enum SnowbridgeControl {
#[codec(index = 83)]
Control(ControlCall),
}
#[test]
fn create_agent() {
let origin_para: u32 = 1001;
BridgeHubRococo::fund_para_sovereign(origin_para.into(), INITIAL_FUND);
let sudo_origin = <Rococo as Chain>::RuntimeOrigin::root();
let destination = Rococo::child_location_of(BridgeHubRococo::para_id()).into();
let create_agent_call = SnowbridgeControl::Control(ControlCall::CreateAgent {});
let remote_xcm = VersionedXcm::from(Xcm(vec![
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
DescendOrigin(X1(Parachain(origin_para))),
Transact {
require_weight_at_most: 3000000000.into(),
origin_kind: OriginKind::Xcm,
call: create_agent_call.encode().into(),
},
]));
//Rococo Global Consensus
// Send XCM message from Relay Chain to Bridge Hub source Parachain
Rococo::execute_with(|| {
assert_ok!(<Rococo as RococoPallet>::XcmPallet::send(
sudo_origin,
bx!(destination),
bx!(remote_xcm),
));
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
assert_expected_events!(
Rococo,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
]
);
});
BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubRococo,
vec![
RuntimeEvent::EthereumSystem(snowbridge_system::Event::CreateAgent {
..
}) => {},
]
);
});
}
#[test]
fn create_channel() {
let origin_para: u32 = 1001;
BridgeHubRococo::fund_para_sovereign(origin_para.into(), INITIAL_FUND);
let sudo_origin = <Rococo as Chain>::RuntimeOrigin::root();
let destination: VersionedMultiLocation =
Rococo::child_location_of(BridgeHubRococo::para_id()).into();
let create_agent_call = SnowbridgeControl::Control(ControlCall::CreateAgent {});
let create_agent_xcm = VersionedXcm::from(Xcm(vec![
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
DescendOrigin(X1(Parachain(origin_para))),
Transact {
require_weight_at_most: 3000000000.into(),
origin_kind: OriginKind::Xcm,
call: create_agent_call.encode().into(),
},
]));
let create_channel_call =
SnowbridgeControl::Control(ControlCall::CreateChannel { mode: OperatingMode::Normal });
let create_channel_xcm = VersionedXcm::from(Xcm(vec![
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
DescendOrigin(X1(Parachain(origin_para))),
Transact {
require_weight_at_most: 3000000000.into(),
origin_kind: OriginKind::Xcm,
call: create_channel_call.encode().into(),
},
]));
//Rococo Global Consensus
// Send XCM message from Relay Chain to Bridge Hub source Parachain
Rococo::execute_with(|| {
assert_ok!(<Rococo as RococoPallet>::XcmPallet::send(
sudo_origin.clone(),
bx!(destination.clone()),
bx!(create_agent_xcm),
));
assert_ok!(<Rococo as RococoPallet>::XcmPallet::send(
sudo_origin,
bx!(destination),
bx!(create_channel_xcm),
));
type RuntimeEvent = <Rococo as Chain>::RuntimeEvent;
assert_expected_events!(
Rococo,
vec![
RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {},
]
);
});
BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubRococo,
vec![
RuntimeEvent::EthereumSystem(snowbridge_system::Event::CreateChannel {
..
}) => {},
]
);
});
}
#[test]
fn register_weth_token_from_ethereum_to_asset_hub() {
BridgeHubRococo::fund_para_sovereign(AssetHubRococo::para_id().into(), INITIAL_FUND);
let message_id_: H256 = [1; 32].into();
BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
type EthereumInboundQueue =
<BridgeHubRococo as BridgeHubRococoPallet>::EthereumInboundQueue;
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::RegisterToken { token: WETH.into(), fee: XCM_FEE },
});
let (xcm, _) = EthereumInboundQueue::do_convert(message_id_, message).unwrap();
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubRococo::para_id().into()).unwrap();
assert_expected_events!(
BridgeHubRococo,
vec![
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
]
);
});
AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::ForeignAssets(pallet_assets::Event::Created { .. }) => {},
]
);
});
}
#[test]
fn send_token_from_ethereum_to_penpal() {
let asset_hub_sovereign = BridgeHubRococo::sovereign_account_id_of(MultiLocation {
parents: 1,
interior: X1(Parachain(AssetHubRococo::para_id().into())),
});
BridgeHubRococo::fund_accounts(vec![(asset_hub_sovereign.clone(), INITIAL_FUND)]);
PenpalA::fund_accounts(vec![
(PenpalAReceiver::get(), INITIAL_FUND),
(PenpalASender::get(), INITIAL_FUND),
]);
let weth_asset_location: MultiLocation =
(Parent, Parent, EthereumNetwork::get(), AccountKey20 { network: None, key: WETH }).into();
let weth_asset_id = weth_asset_location.into();
let origin_location = (Parent, Parent, EthereumNetwork::get()).into();
// Fund ethereum sovereign in asset hub
let ethereum_sovereign: AccountId =
GlobalConsensusEthereumConvertsFor::<AccountId>::convert_location(&origin_location)
.unwrap();
AssetHubRococo::fund_accounts(vec![(ethereum_sovereign.clone(), INITIAL_FUND)]);
// Create asset on assethub.
AssetHubRococo::execute_with(|| {
assert_ok!(<AssetHubRococo as AssetHubRococoPallet>::ForeignAssets::create(
pallet_xcm::Origin::Xcm(origin_location).into(),
weth_asset_id,
asset_hub_sovereign.clone().into(),
1000,
));
assert!(<AssetHubRococo as AssetHubRococoPallet>::ForeignAssets::asset_exists(
weth_asset_id
));
});
// Create asset on penpal.
PenpalA::execute_with(|| {
assert_ok!(<PenpalA as PenpalAPallet>::ForeignAssets::create(
<PenpalA as Chain>::RuntimeOrigin::signed(PenpalASender::get()),
weth_asset_id,
asset_hub_sovereign.into(),
1000,
));
assert!(<PenpalA as PenpalAPallet>::ForeignAssets::asset_exists(weth_asset_id));
});
let message_id_: H256 = [1; 32].into();
BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
type EthereumInboundQueue =
<BridgeHubRococo as BridgeHubRococoPallet>::EthereumInboundQueue;
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::SendToken {
token: WETH.into(),
destination: Destination::ForeignAccountId32 {
para_id: 2000,
id: PenpalAReceiver::get().into(),
fee: XCM_FEE,
},
amount: 1_000_000_000,
fee: XCM_FEE,
},
});
let (xcm, _) = EthereumInboundQueue::do_convert(message_id_, message).unwrap();
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubRococo::para_id().into()).unwrap();
assert_expected_events!(
BridgeHubRococo,
vec![
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
]
);
});
AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {},
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
]
);
});
PenpalA::execute_with(|| {
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
assert_expected_events!(
PenpalA,
vec![
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {},
]
);
});
}
#[test]
fn send_token_from_ethereum_to_asset_hub() {
BridgeHubRococo::fund_para_sovereign(AssetHubRococo::para_id().into(), INITIAL_FUND);
// Fund ethereum sovereign in asset hub
AssetHubRococo::fund_accounts(vec![(AssetHubRococoReceiver::get(), INITIAL_FUND)]);
let message_id_: H256 = [1; 32].into();
BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
type EthereumInboundQueue =
<BridgeHubRococo as BridgeHubRococoPallet>::EthereumInboundQueue;
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::RegisterToken { token: WETH.into(), fee: XCM_FEE },
});
let (xcm, _) = EthereumInboundQueue::do_convert(message_id_, message).unwrap();
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubRococo::para_id().into()).unwrap();
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::SendToken {
token: WETH.into(),
destination: Destination::AccountId32 { id: AssetHubRococoReceiver::get().into() },
amount: 1_000_000_000,
fee: XCM_FEE,
},
});
let (xcm, _) = EthereumInboundQueue::do_convert(message_id_, message).unwrap();
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubRococo::para_id().into()).unwrap();
assert_expected_events!(
BridgeHubRococo,
vec![
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
]
);
});
AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {},
]
);
});
}
#[test]
fn send_weth_asset_from_asset_hub_to_ethereum() {
use asset_hub_rococo_runtime::xcm_config::bridging::to_ethereum::DefaultBridgeHubEthereumBaseFee;
let assethub_sovereign = BridgeHubRococo::sovereign_account_id_of(MultiLocation {
parents: 1,
interior: X1(Parachain(AssetHubRococo::para_id().into())),
});
AssetHubRococo::force_default_xcm_version(Some(XCM_VERSION));
BridgeHubRococo::force_default_xcm_version(Some(XCM_VERSION));
AssetHubRococo::force_xcm_version(
MultiLocation {
parents: 2,
interior: X1(GlobalConsensus(Ethereum { chain_id: CHAIN_ID })),
},
XCM_VERSION,
);
BridgeHubRococo::fund_accounts(vec![(assethub_sovereign.clone(), INITIAL_FUND)]);
AssetHubRococo::fund_accounts(vec![(AssetHubRococoReceiver::get(), INITIAL_FUND)]);
const WETH_AMOUNT: u128 = 1_000_000_000;
let message_id_: H256 = [1; 32].into();
BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
type EthereumInboundQueue =
<BridgeHubRococo as BridgeHubRococoPallet>::EthereumInboundQueue;
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::RegisterToken { token: WETH.into(), fee: XCM_FEE },
});
let (xcm, _) = EthereumInboundQueue::do_convert(message_id_, message).unwrap();
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubRococo::para_id().into()).unwrap();
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::SendToken {
token: WETH.into(),
destination: Destination::AccountId32 { id: AssetHubRococoReceiver::get().into() },
amount: WETH_AMOUNT,
fee: XCM_FEE,
},
});
let (xcm, _) = EthereumInboundQueue::do_convert(message_id_, message).unwrap();
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubRococo::para_id().into()).unwrap();
assert_expected_events!(
BridgeHubRococo,
vec![
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
]
);
});
AssetHubRococo::execute_with(|| {
type RuntimeEvent = <AssetHubRococo as Chain>::RuntimeEvent;
type RuntimeOrigin = <AssetHubRococo as Chain>::RuntimeOrigin;
assert_expected_events!(
AssetHubRococo,
vec![
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {},
]
);
let assets = vec![MultiAsset {
id: Concrete(MultiLocation {
parents: 2,
interior: X2(
GlobalConsensus(Ethereum { chain_id: CHAIN_ID }),
AccountKey20 { network: None, key: WETH },
),
}),
fun: Fungible(WETH_AMOUNT),
}];
let multi_assets = VersionedMultiAssets::V3(MultiAssets::from(assets));
let destination = VersionedMultiLocation::V3(MultiLocation {
parents: 2,
interior: X1(GlobalConsensus(Ethereum { chain_id: CHAIN_ID })),
});
let beneficiary = VersionedMultiLocation::V3(MultiLocation {
parents: 0,
interior: X1(AccountKey20 { network: None, key: ETHEREUM_DESTINATION_ADDRESS.into() }),
});
let free_balance_before = <AssetHubRococo as AssetHubRococoPallet>::Balances::free_balance(
AssetHubRococoReceiver::get(),
);
<AssetHubRococo as AssetHubRococoPallet>::PolkadotXcm::reserve_transfer_assets(
RuntimeOrigin::signed(AssetHubRococoReceiver::get()),
Box::new(destination),
Box::new(beneficiary),
Box::new(multi_assets),
0,
)
.unwrap();
let free_balance_after = <AssetHubRococo as AssetHubRococoPallet>::Balances::free_balance(
AssetHubRococoReceiver::get(),
);
// assert at least DefaultBridgeHubEthereumBaseFee charged from the sender
let free_balance_diff = free_balance_before - free_balance_after;
assert!(free_balance_diff > DefaultBridgeHubEthereumBaseFee::get());
});
BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;
assert_expected_events!(
BridgeHubRococo,
vec![
RuntimeEvent::EthereumOutboundQueue(snowbridge_outbound_queue::Event::MessageQueued {..}) => {},
]
);
let events = BridgeHubRococo::events();
assert!(
events.iter().any(|event| matches!(
event,
RuntimeEvent::Balances(pallet_balances::Event::Deposit{ who, amount })
if *who == TREASURY_ACCOUNT.into() && *amount == 16903333
)),
"Snowbridge sovereign takes local fee."
);
assert!(
events.iter().any(|event| matches!(
event,
RuntimeEvent::Balances(pallet_balances::Event::Deposit{ who, amount })
if *who == assethub_sovereign && *amount == 2680000000000,
)),
"AssetHub sovereign takes remote fee."
);
});
}
@@ -90,6 +90,8 @@ bp-asset-hub-rococo = { path = "../../../../../bridges/primitives/chain-asset-hu
bp-asset-hub-westend = { path = "../../../../../bridges/primitives/chain-asset-hub-westend", default-features = false }
bp-bridge-hub-rococo = { path = "../../../../../bridges/primitives/chain-bridge-hub-rococo", default-features = false }
bp-bridge-hub-westend = { path = "../../../../../bridges/primitives/chain-bridge-hub-westend", default-features = false }
snowbridge-router-primitives = { path = "../../../../../bridges/snowbridge/parachain/primitives/router", default-features = false }
snowbridge-rococo-common = { path = "../../../../../bridges/snowbridge/parachain/runtime/rococo-common", default-features = false }
[dev-dependencies]
asset-test-utils = { path = "../test-utils" }
@@ -137,6 +139,8 @@ runtime-benchmarks = [
"parachains-common/runtime-benchmarks",
"polkadot-parachain-primitives/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
"snowbridge-rococo-common/runtime-benchmarks",
"snowbridge-router-primitives/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"xcm-executor/runtime-benchmarks",
@@ -227,6 +231,8 @@ std = [
"primitive-types/std",
"rococo-runtime-constants/std",
"scale-info/std",
"snowbridge-rococo-common/std",
"snowbridge-router-primitives/std",
"sp-api/std",
"sp-block-builder/std",
"sp-consensus-aura/std",
@@ -30,11 +30,12 @@ pub mod xcm_config;
use assets_common::{
foreign_creators::ForeignCreators,
local_and_foreign_assets::{LocalFromLeft, TargetFromLeft},
matching::FromSiblingParachain,
matching::{FromNetwork, FromSiblingParachain},
AssetIdForTrustBackedAssetsConvert, MultiLocationForAssetId,
};
use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases;
use cumulus_primitives_core::AggregateMessageOrigin;
use snowbridge_rococo_common::EthereumNetwork;
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
@@ -379,7 +380,10 @@ impl pallet_assets::Config<ForeignAssetsInstance> for Runtime {
type AssetIdParameter = MultiLocationForAssetId;
type Currency = Balances;
type CreateOrigin = ForeignCreators<
(FromSiblingParachain<parachain_info::Pallet<Runtime>>,),
(
FromSiblingParachain<parachain_info::Pallet<Runtime>>,
FromNetwork<xcm_config::UniversalLocation, EthereumNetwork>,
),
ForeignCreatorsSovereignAccountOf,
AccountId,
>;
@@ -913,7 +917,6 @@ construct_runtime!(
// Bridge utilities.
ToWestendXcmRouter: pallet_xcm_bridge_hub_router::<Instance3>::{Pallet, Storage, Call} = 45,
// The main stage.
Assets: pallet_assets::<Instance1>::{Pallet, Call, Storage, Event<T>} = 50,
Uniques: pallet_uniques::{Pallet, Call, Storage, Event<T>} = 51,
@@ -21,7 +21,7 @@ use super::{
};
use assets_common::{
local_and_foreign_assets::MatchesLocalAndForeignAssetsMultiLocation,
matching::{FromSiblingParachain, IsForeignConcreteAsset},
matching::{FromNetwork, FromSiblingParachain, IsForeignConcreteAsset},
};
use frame_support::{
match_types, parameter_types,
@@ -39,6 +39,8 @@ use parachains_common::{
};
use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_common::xcm_sender::ExponentialPrice;
use snowbridge_rococo_common::EthereumNetwork;
use snowbridge_router_primitives::inbound::GlobalConsensusEthereumConvertsFor;
use sp_runtime::traits::{AccountIdConversion, ConvertInto};
use xcm::latest::prelude::*;
#[allow(deprecated)]
@@ -50,9 +52,10 @@ use xcm_builder::{
GlobalConsensusParachainConvertsFor, HashedDescription, IsConcrete, LocalMint,
NetworkExportTableItem, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
SignedToAccountId32, SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus,
TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin,
WithUniqueTopic, XcmFeeManagerFromComponents, XcmFeeToAccount,
SignedToAccountId32, SovereignPaidRemoteExporter, SovereignSignedViaLocation, StartsWith,
StartsWithExplicitGlobalConsensus, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents,
XcmFeeToAccount,
};
use xcm_executor::{traits::WithOriginFilter, XcmExecutor};
@@ -90,6 +93,9 @@ pub type LocationToAccountId = (
// Different global consensus parachain sovereign account.
// (Used for over-bridge transfers and reserve processing)
GlobalConsensusParachainConvertsFor<UniversalLocation, AccountId>,
// Ethereum contract sovereign account.
// (Used to get convert ethereum contract locations to sovereign account)
GlobalConsensusEthereumConvertsFor<AccountId>,
);
/// Means for transacting the native currency on this chain.
@@ -259,10 +265,11 @@ impl Contains<RuntimeCall> for SafeCallFilter {
// Allow to change dedicated storage items (called by governance-like)
match call {
RuntimeCall::System(frame_system::Call::set_storage { items })
if items.iter().all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterByteFee::key())) ||
items
.iter()
.all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterBaseFee::key())) =>
if items.iter().all(|(k, _)| {
k.eq(&bridging::XcmBridgeHubRouterByteFee::key()) |
k.eq(&bridging::XcmBridgeHubRouterBaseFee::key()) |
k.eq(&bridging::to_ethereum::BridgeHubEthereumBaseFee::key())
}) =>
return true,
_ => (),
};
@@ -534,7 +541,10 @@ impl xcm_executor::Config for XcmConfig {
// as reserve locations (we trust the Bridge Hub to relay the message that a reserve is being
// held). Asset Hub may _act_ as a reserve location for ROC and assets created
// under `pallet-assets`. Users must use teleport where allowed (e.g. ROC with the Relay Chain).
type IsReserve = (bridging::to_westend::IsTrustedBridgedReserveLocationForConcreteAsset,);
type IsReserve = (
bridging::to_westend::IsTrustedBridgedReserveLocationForConcreteAsset,
bridging::to_ethereum::IsTrustedBridgedReserveLocationForForeignAsset,
);
type IsTeleporter = TrustedTeleporters;
type UniversalLocation = UniversalLocation;
type Barrier = Barrier;
@@ -585,7 +595,8 @@ impl xcm_executor::Config for XcmConfig {
XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>,
>;
type MessageExporter = ();
type UniversalAliases = (bridging::to_westend::UniversalAliases,);
type UniversalAliases =
(bridging::to_westend::UniversalAliases, bridging::to_ethereum::UniversalAliases);
type CallDispatcher = WithOriginFilter<SafeCallFilter>;
type SafeCallFilter = SafeCallFilter;
type Aliasers = Nothing;
@@ -613,6 +624,9 @@ pub type XcmRouter = WithUniqueTopic<(
// Router which wraps and sends xcm to BridgeHub to be delivered to the Westend
// GlobalConsensus
ToWestendXcmRouter,
// Router which wraps and sends xcm to BridgeHub to be delivered to the Ethereum
// GlobalConsensus
SovereignPaidRemoteExporter<bridging::EthereumNetworkExportTable, XcmpQueue, UniversalLocation>,
)>;
impl pallet_xcm::Config for Runtime {
@@ -658,6 +672,7 @@ pub type ForeignCreatorsSovereignAccountOf = (
SiblingParachainConvertsVia<Sibling, AccountId>,
AccountId32Aliases<RelayNetwork, AccountId>,
ParentIsPreset<AccountId>,
GlobalConsensusEthereumConvertsFor<AccountId>,
);
/// Simple conversion of `u32` into an `AssetId` for use in benchmarking.
@@ -706,10 +721,17 @@ pub mod bridging {
sp_std::vec::Vec::new().into_iter()
.chain(to_westend::BridgeTable::get())
.collect();
pub EthereumBridgeTable: sp_std::vec::Vec<NetworkExportTableItem> =
sp_std::vec::Vec::new().into_iter()
.chain(to_ethereum::BridgeTable::get())
.collect();
}
pub type NetworkExportTable = xcm_builder::NetworkExportTable<BridgeTable>;
pub type EthereumNetworkExportTable = xcm_builder::NetworkExportTable<EthereumBridgeTable>;
pub mod to_westend {
use super::*;
@@ -786,6 +808,56 @@ pub mod bridging {
}
}
pub mod to_ethereum {
use super::*;
parameter_types! {
/// User fee for ERC20 token transfer back to Ethereum.
/// (initially was calculated by test `OutboundQueue::calculate_fees` - ETH/ROC 1/400 and fee_per_gas 20 GWEI = 2200698000000 + *25%)
/// Needs to be more than fee calculated from DefaultFeeConfig FeeConfigRecord in snowbridge:parachain/pallets/outbound-queue/src/lib.rs
/// Polkadot uses 10 decimals, Kusama and Rococo 12 decimals.
pub const DefaultBridgeHubEthereumBaseFee: Balance = 2_750_872_500_000;
pub storage BridgeHubEthereumBaseFee: Balance = DefaultBridgeHubEthereumBaseFee::get();
pub SiblingBridgeHubWithEthereumInboundQueueInstance: MultiLocation = MultiLocation::new(
1,
X2(
Parachain(SiblingBridgeHubParaId::get()),
PalletInstance(snowbridge_rococo_common::INBOUND_QUEUE_MESSAGES_PALLET_INDEX)
)
);
/// Set up exporters configuration.
/// `Option<MultiAsset>` represents static "base fee" which is used for total delivery fee calculation.
pub BridgeTable: sp_std::vec::Vec<NetworkExportTableItem> = sp_std::vec![
NetworkExportTableItem::new(
EthereumNetwork::get(),
Some(sp_std::vec![Junctions::Here]),
SiblingBridgeHub::get(),
Some((
XcmBridgeHubRouterFeeAssetId::get(),
BridgeHubEthereumBaseFee::get(),
).into())
),
];
/// Universal aliases
pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter(
sp_std::vec![
(SiblingBridgeHubWithEthereumInboundQueueInstance::get(), GlobalConsensus(EthereumNetwork::get())),
]
);
}
pub type IsTrustedBridgedReserveLocationForForeignAsset =
matching::IsForeignConcreteAsset<FromNetwork<UniversalLocation, EthereumNetwork>>;
impl Contains<(MultiLocation, Junction)> for UniversalAliases {
fn contains(alias: &(MultiLocation, Junction)) -> bool {
UniversalAliases::get().contains(alias)
}
}
}
/// Benchmarks helper for bridging configuration.
#[cfg(feature = "runtime-benchmarks")]
pub struct BridgingBenchmarksHelper;
@@ -865,3 +865,55 @@ fn change_xcm_bridge_hub_router_byte_fee_by_governance_works() {
},
)
}
#[test]
fn change_xcm_bridge_hub_router_base_fee_by_governance_works() {
asset_test_utils::test_cases::change_storage_constant_by_governance_works::<
Runtime,
bridging::XcmBridgeHubRouterBaseFee,
Balance,
>(
collator_session_keys(),
1000,
Box::new(|call| RuntimeCall::System(call).encode()),
|| {
(
bridging::XcmBridgeHubRouterBaseFee::key().to_vec(),
bridging::XcmBridgeHubRouterBaseFee::get(),
)
},
|old_value| {
if let Some(new_value) = old_value.checked_add(1) {
new_value
} else {
old_value.checked_sub(1).unwrap()
}
},
)
}
#[test]
fn change_xcm_bridge_hub_ethereum_base_fee_by_governance_works() {
asset_test_utils::test_cases::change_storage_constant_by_governance_works::<
Runtime,
bridging::to_ethereum::BridgeHubEthereumBaseFee,
Balance,
>(
collator_session_keys(),
1000,
Box::new(|call| RuntimeCall::System(call).encode()),
|| {
(
bridging::to_ethereum::BridgeHubEthereumBaseFee::key().to_vec(),
bridging::to_ethereum::BridgeHubEthereumBaseFee::get(),
)
},
|old_value| {
if let Some(new_value) = old_value.checked_add(1) {
new_value
} else {
old_value.checked_sub(1).unwrap()
}
},
)
}
@@ -58,6 +58,37 @@ impl<SelfParaId: Get<ParaId>> ContainsPair<MultiLocation, MultiLocation>
}
}
/// Checks if `a` is from the expected global consensus network. Checks that `MultiLocation-a`
/// starts with `MultiLocation-b`, and that network is a foreign consensus system.
pub struct FromNetwork<UniversalLocation, ExpectedNetworkId>(
sp_std::marker::PhantomData<(UniversalLocation, ExpectedNetworkId)>,
);
impl<UniversalLocation: Get<InteriorMultiLocation>, ExpectedNetworkId: Get<NetworkId>>
ContainsPair<MultiLocation, MultiLocation> for FromNetwork<UniversalLocation, ExpectedNetworkId>
{
fn contains(&a: &MultiLocation, b: &MultiLocation) -> bool {
// `a` needs to be from `b` at least
if !a.starts_with(b) {
return false
}
let universal_source = UniversalLocation::get();
// ensure that `a`` is remote and from the expected network
match ensure_is_remote(universal_source, a) {
Ok((network_id, _)) => network_id == ExpectedNetworkId::get(),
Err(e) => {
log::trace!(
target: "xcm::contains",
"FromNetwork origin: {:?} is not remote to the universal_source: {:?} {:?}",
a, universal_source, e
);
false
},
}
}
}
/// Adapter verifies if it is allowed to receive `MultiAsset` from `MultiLocation`.
///
/// Note: `MultiLocation` has to be from a different global consensus.
@@ -95,3 +126,92 @@ impl<
Reserves::contains(asset, origin)
}
}
#[cfg(test)]
mod tests {
use super::*;
use frame_support::parameter_types;
parameter_types! {
pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(Rococo), Parachain(1000));
pub ExpectedNetworkId: NetworkId = Wococo;
}
#[test]
fn from_network_contains_works() {
// asset and origin from foreign consensus works
let asset: MultiLocation = (
Parent,
Parent,
GlobalConsensus(Wococo),
Parachain(1000),
PalletInstance(1),
GeneralIndex(1),
)
.into();
let origin: MultiLocation =
(Parent, Parent, GlobalConsensus(Wococo), Parachain(1000)).into();
assert!(FromNetwork::<UniversalLocation, ExpectedNetworkId>::contains(&asset, &origin));
// asset and origin from local consensus fails
let asset: MultiLocation = (
Parent,
Parent,
GlobalConsensus(Rococo),
Parachain(1000),
PalletInstance(1),
GeneralIndex(1),
)
.into();
let origin: MultiLocation =
(Parent, Parent, GlobalConsensus(Rococo), Parachain(1000)).into();
assert!(!FromNetwork::<UniversalLocation, ExpectedNetworkId>::contains(&asset, &origin));
// asset and origin from here fails
let asset: MultiLocation = (PalletInstance(1), GeneralIndex(1)).into();
let origin: MultiLocation = Here.into();
assert!(!FromNetwork::<UniversalLocation, ExpectedNetworkId>::contains(&asset, &origin));
// asset from different consensus fails
let asset: MultiLocation = (
Parent,
Parent,
GlobalConsensus(Polkadot),
Parachain(1000),
PalletInstance(1),
GeneralIndex(1),
)
.into();
let origin: MultiLocation =
(Parent, Parent, GlobalConsensus(Wococo), Parachain(1000)).into();
assert!(!FromNetwork::<UniversalLocation, ExpectedNetworkId>::contains(&asset, &origin));
// origin from different consensus fails
let asset: MultiLocation = (
Parent,
Parent,
GlobalConsensus(Wococo),
Parachain(1000),
PalletInstance(1),
GeneralIndex(1),
)
.into();
let origin: MultiLocation =
(Parent, Parent, GlobalConsensus(Polkadot), Parachain(1000)).into();
assert!(!FromNetwork::<UniversalLocation, ExpectedNetworkId>::contains(&asset, &origin));
// asset and origin from unexpected consensus fails
let asset: MultiLocation = (
Parent,
Parent,
GlobalConsensus(Polkadot),
Parachain(1000),
PalletInstance(1),
GeneralIndex(1),
)
.into();
let origin: MultiLocation =
(Parent, Parent, GlobalConsensus(Polkadot), Parachain(1000)).into();
assert!(!FromNetwork::<UniversalLocation, ExpectedNetworkId>::contains(&asset, &origin));
}
}
@@ -106,6 +106,21 @@ pallet-bridge-relayers = { path = "../../../../../bridges/modules/relayers", def
pallet-xcm-bridge-hub = { path = "../../../../../bridges/modules/xcm-bridge-hub", default-features = false }
bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", default-features = false }
# Ethereum Bridge (Snowbridge)
snowbridge-beacon-primitives = { path = "../../../../../bridges/snowbridge/parachain/primitives/beacon", default-features = false }
snowbridge-system = { path = "../../../../../bridges/snowbridge/parachain/pallets/system", default-features = false }
snowbridge-system-runtime-api = { path = "../../../../../bridges/snowbridge/parachain/pallets/system/runtime-api", default-features = false }
snowbridge-core = { path = "../../../../../bridges/snowbridge/parachain/primitives/core", default-features = false }
snowbridge-ethereum-beacon-client = { path = "../../../../../bridges/snowbridge/parachain/pallets/ethereum-beacon-client", default-features = false }
snowbridge-inbound-queue = { path = "../../../../../bridges/snowbridge/parachain/pallets/inbound-queue", default-features = false }
snowbridge-outbound-queue = { path = "../../../../../bridges/snowbridge/parachain/pallets/outbound-queue", default-features = false }
snowbridge-outbound-queue-runtime-api = { path = "../../../../../bridges/snowbridge/parachain/pallets/outbound-queue/runtime-api", default-features = false }
snowbridge-router-primitives = { path = "../../../../../bridges/snowbridge/parachain/primitives/router", default-features = false }
snowbridge-runtime-common = { path = "../../../../../bridges/snowbridge/parachain/runtime/runtime-common", default-features = false }
snowbridge-rococo-common = { path = "../../../../../bridges/snowbridge/parachain/runtime/rococo-common", default-features = false }
bridge-hub-common = { path = "../common", default-features = false }
[dev-dependencies]
static_assertions = "1.1"
bridge-hub-test-utils = { path = "../test-utils" }
@@ -131,6 +146,7 @@ std = [
"bp-rococo/std",
"bp-runtime/std",
"bp-westend/std",
"bridge-hub-common/std",
"bridge-runtime-common/std",
"codec/std",
"cumulus-pallet-aura-ext/std",
@@ -174,6 +190,17 @@ std = [
"rococo-runtime-constants/std",
"scale-info/std",
"serde",
"snowbridge-beacon-primitives/std",
"snowbridge-core/std",
"snowbridge-ethereum-beacon-client/std",
"snowbridge-inbound-queue/std",
"snowbridge-outbound-queue-runtime-api/std",
"snowbridge-outbound-queue/std",
"snowbridge-rococo-common/std",
"snowbridge-router-primitives/std",
"snowbridge-runtime-common/std",
"snowbridge-system-runtime-api/std",
"snowbridge-system/std",
"sp-api/std",
"sp-block-builder/std",
"sp-consensus-aura/std",
@@ -189,12 +216,15 @@ std = [
"sp-transaction-pool/std",
"sp-version/std",
"substrate-wasm-builder",
"substrate-wasm-builder",
"xcm-builder/std",
"xcm-executor/std",
"xcm/std",
]
runtime-benchmarks = [
"beacon-spec-mainnet",
"bridge-hub-common/runtime-benchmarks",
"bridge-runtime-common/runtime-benchmarks",
"cumulus-pallet-parachain-system/runtime-benchmarks",
"cumulus-pallet-session-benchmarking/runtime-benchmarks",
@@ -221,6 +251,14 @@ runtime-benchmarks = [
"parachains-common/runtime-benchmarks",
"polkadot-parachain-primitives/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
"snowbridge-core/runtime-benchmarks",
"snowbridge-ethereum-beacon-client/runtime-benchmarks",
"snowbridge-inbound-queue/runtime-benchmarks",
"snowbridge-outbound-queue/runtime-benchmarks",
"snowbridge-rococo-common/runtime-benchmarks",
"snowbridge-router-primitives/runtime-benchmarks",
"snowbridge-runtime-common/runtime-benchmarks",
"snowbridge-system/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"xcm-executor/runtime-benchmarks",
@@ -253,10 +291,17 @@ try-runtime = [
"pallet-xcm/try-runtime",
"parachain-info/try-runtime",
"polkadot-runtime-common/try-runtime",
"snowbridge-ethereum-beacon-client/try-runtime",
"snowbridge-inbound-queue/try-runtime",
"snowbridge-outbound-queue/try-runtime",
"snowbridge-system/try-runtime",
"sp-runtime/try-runtime",
]
experimental = ["pallet-aura/experimental"]
beacon-spec-mainnet = [
"snowbridge-ethereum-beacon-client/beacon-spec-mainnet",
]
# A feature that should be enabled when the runtime should be built for on-chain
# deployment. This will disable stuff that shouldn't be part of the on-chain wasm
@@ -0,0 +1,30 @@
// 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 <http://www.gnu.org/licenses/>.
use crate::{
xcm_config::{AgentIdOf, UniversalLocation},
Runtime,
};
use snowbridge_rococo_common::EthereumNetwork;
use snowbridge_router_primitives::outbound::EthereumBlobExporter;
/// Exports message to the Ethereum Gateway contract.
pub type SnowbridgeExporter = EthereumBlobExporter<
UniversalLocation,
EthereumNetwork,
snowbridge_outbound_queue::Pallet<Runtime>,
AgentIdOf,
>;
@@ -30,18 +30,24 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
pub mod bridge_common_config;
pub mod bridge_to_bulletin_config;
pub mod bridge_to_ethereum_config;
pub mod bridge_to_westend_config;
mod weights;
pub mod xcm_config;
use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases;
use snowbridge_beacon_primitives::{Fork, ForkVersions};
use snowbridge_core::{
gwei, meth, outbound::Message, AgentId, AllowSiblingsOnly, PricingParameters, Rewards,
};
use snowbridge_router_primitives::inbound::MessageToXcm;
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H160};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::Block as BlockT,
traits::{Block as BlockT, Keccak256},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult,
ApplyExtrinsicResult, FixedU128,
};
use sp_std::prelude::*;
@@ -49,7 +55,7 @@ use sp_std::prelude::*;
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use cumulus_primitives_core::ParaId;
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
@@ -63,17 +69,25 @@ use frame_system::{
limits::{BlockLength, BlockWeights},
EnsureRoot,
};
use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling};
pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
pub use sp_runtime::{MultiAddress, Perbill, Permill};
use xcm_config::{XcmOriginToTransactDispatchOrigin, XcmRouter};
use bp_runtime::HeaderId;
#[cfg(not(feature = "runtime-benchmarks"))]
use bridge_hub_common::BridgeHubMessageRouter;
use bridge_hub_common::{
message_queue::{NarrowOriginToSibling, ParaIdToSibling},
AggregateMessageOrigin,
};
use pallet_xcm::EnsureXcm;
pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
pub use sp_runtime::{MultiAddress, Perbill, Permill};
use xcm::VersionedMultiLocation;
use xcm_config::{TreasuryAccount, XcmOriginToTransactDispatchOrigin, XcmRouter};
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate};
use rococo_runtime_constants::system_parachain::{ASSET_HUB_ID, BRIDGE_HUB_ID};
use xcm::latest::prelude::*;
use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight};
@@ -85,6 +99,19 @@ use parachains_common::{
HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION,
};
#[cfg(feature = "runtime-benchmarks")]
use crate::xcm_config::benchmark_helpers::DoNothingRouter;
#[cfg(feature = "runtime-benchmarks")]
use snowbridge_beacon_primitives::CompactExecutionHeader;
#[cfg(feature = "runtime-benchmarks")]
use snowbridge_core::RingBufferMap;
#[cfg(feature = "runtime-benchmarks")]
pub use snowbridge_ethereum_beacon_client::ExecutionHeaderBuffer;
#[cfg(feature = "runtime-benchmarks")]
use snowbridge_inbound_queue::BenchmarkHelper;
#[cfg(feature = "runtime-benchmarks")]
use sp_core::H256;
/// The address format for describing accounts.
pub type Address = MultiAddress<AccountId, ()>;
@@ -124,6 +151,12 @@ pub type Migrations = (
pallet_multisig::migrations::v1::MigrateToV1<Runtime>,
InitStorageVersions,
cumulus_pallet_xcmp_queue::migration::v4::MigrationToV4<Runtime>,
// unreleased
snowbridge_system::migration::v0::InitializeOnUpgrade<
Runtime,
ConstU32<BRIDGE_HUB_ID>,
ConstU32<ASSET_HUB_ID>,
>,
);
/// Migration to initialize storage versions for pallets added after genesis.
@@ -325,21 +358,27 @@ impl cumulus_pallet_parachain_system::Config for Runtime {
impl parachain_info::Config for Runtime {}
parameter_types! {
pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block;
/// Amount of weight that can be spent per block to service messages. This was increased
/// from 35% to 60% of the max block weight to accommodate the Ethereum beacon light client
/// extrinsics. The force_checkpoint and submit extrinsics (for submit, optionally) includes
/// the sync committee's pubkeys (512 x 48 bytes)
pub MessageQueueServiceWeight: Weight = Perbill::from_percent(60) * RuntimeBlockWeights::get().max_block;
}
impl pallet_message_queue::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = weights::pallet_message_queue::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor<
cumulus_primitives_core::AggregateMessageOrigin,
>;
type MessageProcessor =
pallet_message_queue::mock_helpers::NoopMessageProcessor<AggregateMessageOrigin>;
#[cfg(not(feature = "runtime-benchmarks"))]
type MessageProcessor = xcm_builder::ProcessXcmMessage<
AggregateMessageOrigin,
xcm_executor::XcmExecutor<xcm_config::XcmConfig>,
RuntimeCall,
type MessageProcessor = BridgeHubMessageRouter<
xcm_builder::ProcessXcmMessage<
AggregateMessageOrigin,
xcm_executor::XcmExecutor<xcm_config::XcmConfig>,
RuntimeCall,
>,
EthereumOutboundQueue,
>;
type Size = u32;
// The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin:
@@ -456,6 +495,151 @@ impl pallet_utility::Config for Runtime {
type WeightInfo = weights::pallet_utility::WeightInfo<Runtime>;
}
// Ethereum Bridge
#[cfg(not(feature = "runtime-benchmarks"))]
parameter_types! {
pub storage EthereumGatewayAddress: H160 = H160::zero();
}
#[cfg(feature = "runtime-benchmarks")]
parameter_types! {
pub storage EthereumGatewayAddress: H160 = H160(hex_literal::hex!("EDa338E4dC46038493b885327842fD3E301CaB39"));
}
parameter_types! {
pub const CreateAssetCall: [u8;2] = [53, 0];
pub const CreateAssetDeposit: u128 = (UNITS / 10) + EXISTENTIAL_DEPOSIT;
pub const InboundQueuePalletInstance: u8 = snowbridge_rococo_common::INBOUND_QUEUE_MESSAGES_PALLET_INDEX;
pub Parameters: PricingParameters<u128> = PricingParameters {
exchange_rate: FixedU128::from_rational(1, 400),
fee_per_gas: gwei(20),
rewards: Rewards { local: 1 * UNITS, remote: meth(1) }
};
}
#[cfg(feature = "runtime-benchmarks")]
impl<T: snowbridge_ethereum_beacon_client::Config> BenchmarkHelper<T> for Runtime {
fn initialize_storage(block_hash: H256, header: CompactExecutionHeader) {
<ExecutionHeaderBuffer<T>>::insert(block_hash, header);
}
}
impl snowbridge_inbound_queue::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Verifier = snowbridge_ethereum_beacon_client::Pallet<Runtime>;
type Token = Balances;
#[cfg(not(feature = "runtime-benchmarks"))]
type XcmSender = XcmRouter;
#[cfg(feature = "runtime-benchmarks")]
type XcmSender = DoNothingRouter;
type ChannelLookup = EthereumSystem;
type GatewayAddress = EthereumGatewayAddress;
#[cfg(feature = "runtime-benchmarks")]
type Helper = Runtime;
type MessageConverter = MessageToXcm<
CreateAssetCall,
CreateAssetDeposit,
InboundQueuePalletInstance,
AccountId,
Balance,
>;
type WeightToFee = WeightToFee;
type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
type MaxMessageSize = ConstU32<2048>;
type WeightInfo = weights::snowbridge_inbound_queue::WeightInfo<Runtime>;
type PricingParameters = EthereumSystem;
}
impl snowbridge_outbound_queue::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Hashing = Keccak256;
type MessageQueue = MessageQueue;
type Decimals = ConstU8<12>;
type MaxMessagePayloadSize = ConstU32<2048>;
type MaxMessagesPerBlock = ConstU32<32>;
type GasMeter = snowbridge_core::outbound::ConstantGasMeter;
type Balance = Balance;
type WeightToFee = WeightToFee;
type WeightInfo = weights::snowbridge_outbound_queue::WeightInfo<Runtime>;
type PricingParameters = EthereumSystem;
type Channels = EthereumSystem;
}
#[cfg(not(feature = "beacon-spec-mainnet"))]
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,
},
};
pub const MaxExecutionHeadersToKeep:u32 = 1000;
}
#[cfg(feature = "beacon-spec-mainnet")]
parameter_types! {
pub const ChainForkVersions: ForkVersions = ForkVersions {
genesis: Fork {
version: [0, 0, 16, 32], // 0x00001020
epoch: 0,
},
altair: Fork {
version: [1, 0, 16, 32], // 0x01001020
epoch: 36660,
},
bellatrix: Fork {
version: [2, 0, 16, 32], // 0x02001020
epoch: 112260,
},
capella: Fork {
version: [3, 0, 16, 32], // 0x03001020
epoch: 162304,
},
};
pub const MaxExecutionHeadersToKeep:u32 = 8192 * 2;
}
impl snowbridge_ethereum_beacon_client::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type ForkVersions = ChainForkVersions;
type MaxExecutionHeadersToKeep = MaxExecutionHeadersToKeep;
type WeightInfo = weights::snowbridge_ethereum_beacon_client::WeightInfo<Runtime>;
}
#[cfg(feature = "runtime-benchmarks")]
impl snowbridge_system::BenchmarkHelper<RuntimeOrigin> for () {
fn make_xcm_origin(location: xcm::latest::MultiLocation) -> RuntimeOrigin {
RuntimeOrigin::from(pallet_xcm::Origin::Xcm(location))
}
}
impl snowbridge_system::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OutboundQueue = EthereumOutboundQueue;
type SiblingOrigin = EnsureXcm<AllowSiblingsOnly>;
type AgentIdOf = xcm_config::AgentIdOf;
type TreasuryAccount = TreasuryAccount;
type Token = Balances;
type WeightInfo = weights::snowbridge_system::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type Helper = ();
type DefaultPricingParameters = Parameters;
type InboundDeliveryCost = EthereumInboundQueue;
}
// Create the runtime by composing the FRAME pallets that were previously configured.
construct_runtime!(
pub enum Runtime
@@ -515,6 +699,11 @@ construct_runtime!(
// With-Rococo Bulletin bridge hub pallet.
XcmOverPolkadotBulletin: pallet_xcm_bridge_hub::<Instance2>::{Pallet} = 62,
EthereumInboundQueue: snowbridge_inbound_queue::{Pallet, Call, Storage, Event<T>} = 80,
EthereumOutboundQueue: snowbridge_outbound_queue::{Pallet, Call, Storage, Event<T>} = 81,
EthereumBeaconClient: snowbridge_ethereum_beacon_client::{Pallet, Call, Storage, Event<T>} = 82,
EthereumSystem: snowbridge_system::{Pallet, Call, Storage, Config<T>, Event<T>} = 83,
// Message Queue. Importantly, is registered last so that messages are processed after
// the `on_initialize` hooks of bridging pallets.
MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event<T>} = 250,
@@ -564,6 +753,11 @@ mod benches {
[pallet_bridge_messages, RococoToWestend]
[pallet_bridge_messages, RococoToRococoBulletin]
[pallet_bridge_relayers, BridgeRelayersBench::<Runtime>]
// Ethereum Bridge
[snowbridge_inbound_queue, EthereumInboundQueue]
[snowbridge_outbound_queue, EthereumOutboundQueue]
[snowbridge_system, EthereumSystem]
[snowbridge_ethereum_beacon_client, EthereumBeaconClient]
);
}
@@ -792,6 +986,22 @@ impl_runtime_apis! {
}
}
impl snowbridge_outbound_queue_runtime_api::OutboundQueueApi<Block, Balance> for Runtime {
fn prove_message(leaf_index: u64) -> Option<snowbridge_outbound_queue::MerkleProof> {
snowbridge_outbound_queue::api::prove_message::<Runtime>(leaf_index)
}
fn calculate_fee(message: Message) -> Option<Balance> {
snowbridge_outbound_queue::api::calculate_fee::<Runtime>(message)
}
}
impl snowbridge_system_runtime_api::ControlApi<Block> for Runtime {
fn agent_id(location: VersionedMultiLocation) -> Option<AgentId> {
snowbridge_system::api::agent_id::<Runtime>(location)
}
}
#[cfg(feature = "try-runtime")]
impl frame_try_runtime::TryRuntime<Block> for Runtime {
fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
@@ -40,6 +40,10 @@ pub mod pallet_utility;
pub mod pallet_xcm;
pub mod paritydb_weights;
pub mod rocksdb_weights;
pub mod snowbridge_ethereum_beacon_client;
pub mod snowbridge_inbound_queue;
pub mod snowbridge_outbound_queue;
pub mod snowbridge_system;
pub mod xcm;
pub use block_weights::constants::BlockExecutionWeight;
@@ -0,0 +1,151 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Autogenerated weights for `snowbridge_ethereum_beacon_client`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-06-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `ip-172-31-8-124`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-rococo-dev"), DB CACHE: 1024
// Executed Command:
// target/release/polkadot-parachain
// benchmark
// pallet
// --base-path
// /mnt/scratch/benchmark
// --chain=bridge-hub-rococo-dev
// --pallet=snowbridge_ethereum_beacon_client
// --extrinsic=*
// --execution=wasm
// --wasm-execution=compiled
// --steps
// 50
// --repeat
// 20
// --output
// ./parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_ethereum_beacon_client.rs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use frame_support::{traits::Get, weights::Weight};
use core::marker::PhantomData;
/// Weight functions for `snowbridge_ethereum_beacon_client`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> snowbridge_ethereum_beacon_client::WeightInfo for WeightInfo<T> {
/// Storage: EthereumBeaconClient FinalizedBeaconStateIndex (r:1 w:1)
/// Proof: EthereumBeaconClient FinalizedBeaconStateIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient FinalizedBeaconStateMapping (r:1 w:1)
/// Proof: EthereumBeaconClient FinalizedBeaconStateMapping (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient NextSyncCommittee (r:0 w:1)
/// Proof: EthereumBeaconClient NextSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient InitialCheckpointRoot (r:0 w:1)
/// Proof: EthereumBeaconClient InitialCheckpointRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient ValidatorsRoot (r:0 w:1)
/// Proof: EthereumBeaconClient ValidatorsRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient LatestFinalizedBlockRoot (r:0 w:1)
/// Proof: EthereumBeaconClient LatestFinalizedBlockRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient CurrentSyncCommittee (r:0 w:1)
/// Proof: EthereumBeaconClient CurrentSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient LatestExecutionState (r:0 w:1)
/// Proof: EthereumBeaconClient LatestExecutionState (max_values: Some(1), max_size: Some(80), added: 575, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient FinalizedBeaconState (r:0 w:1)
/// Proof: EthereumBeaconClient FinalizedBeaconState (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen)
fn force_checkpoint() -> Weight {
// Proof Size summary in bytes:
// Measured: `42`
// Estimated: `3501`
// Minimum execution time: 97_185_781_000 picoseconds.
Weight::from_parts(97_263_571_000, 0)
.saturating_add(Weight::from_parts(0, 3501))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(9))
}
/// Storage: EthereumBeaconClient LatestFinalizedBlockRoot (r:1 w:1)
/// Proof: EthereumBeaconClient LatestFinalizedBlockRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient FinalizedBeaconState (r:1 w:1)
/// Proof: EthereumBeaconClient FinalizedBeaconState (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient LatestExecutionState (r:1 w:0)
/// Proof: EthereumBeaconClient LatestExecutionState (max_values: Some(1), max_size: Some(80), added: 575, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient NextSyncCommittee (r:1 w:0)
/// Proof: EthereumBeaconClient NextSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient CurrentSyncCommittee (r:1 w:0)
/// Proof: EthereumBeaconClient CurrentSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient ValidatorsRoot (r:1 w:0)
/// Proof: EthereumBeaconClient ValidatorsRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient FinalizedBeaconStateIndex (r:1 w:1)
/// Proof: EthereumBeaconClient FinalizedBeaconStateIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient FinalizedBeaconStateMapping (r:1 w:1)
/// Proof: EthereumBeaconClient FinalizedBeaconStateMapping (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen)
fn submit() -> Weight {
// Proof Size summary in bytes:
// Measured: `92753`
// Estimated: `93857`
// Minimum execution time: 25_999_968_000 picoseconds.
Weight::from_parts(26_051_019_000, 0)
.saturating_add(Weight::from_parts(0, 93857))
.saturating_add(T::DbWeight::get().reads(8))
.saturating_add(T::DbWeight::get().writes(4))
}
/// 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: EthereumBeaconClient LatestExecutionState (r:1 w:0)
/// Proof: EthereumBeaconClient LatestExecutionState (max_values: Some(1), max_size: Some(80), added: 575, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient NextSyncCommittee (r:1 w:1)
/// Proof: EthereumBeaconClient NextSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient CurrentSyncCommittee (r:1 w:0)
/// Proof: EthereumBeaconClient CurrentSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient ValidatorsRoot (r:1 w:0)
/// Proof: EthereumBeaconClient ValidatorsRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen)
fn submit_with_sync_committee() -> Weight {
// Proof Size summary in bytes:
// Measured: `92717`
// Estimated: `93857`
// Minimum execution time: 122_354_917_000 picoseconds.
Weight::from_parts(122_461_312_000, 0)
.saturating_add(Weight::from_parts(0, 93857))
.saturating_add(T::DbWeight::get().reads(6))
.saturating_add(T::DbWeight::get().writes(1))
}
/// 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: EthereumBeaconClient LatestExecutionState (r:1 w:1)
/// Proof: EthereumBeaconClient LatestExecutionState (max_values: Some(1), max_size: Some(80), added: 575, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient ExecutionHeaderIndex (r:1 w:1)
/// Proof: EthereumBeaconClient ExecutionHeaderIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient ExecutionHeaderMapping (r:1 w:1)
/// Proof: EthereumBeaconClient ExecutionHeaderMapping (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient ExecutionHeaders (r:0 w:1)
/// Proof: EthereumBeaconClient ExecutionHeaders (max_values: None, max_size: Some(136), added: 2611, mode: MaxEncodedLen)
fn submit_execution_header() -> Weight {
// Proof Size summary in bytes:
// Measured: `386`
// Estimated: `3537`
// Minimum execution time: 108_761_000 picoseconds.
Weight::from_parts(113_158_000, 0)
.saturating_add(Weight::from_parts(0, 3537))
.saturating_add(T::DbWeight::get().reads(5))
.saturating_add(T::DbWeight::get().writes(4))
}
}
@@ -0,0 +1,69 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Autogenerated weights for `snowbridge_inbound_queue`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-09-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `macbook pro 14 m2`, CPU: `m2-arm64`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-rococo-dev"), DB CACHE: 1024
// Executed Command:
// target/release/polkadot-parachain
// benchmark
// pallet
// --chain=bridge-hub-rococo-dev
// --pallet=snowbridge_inbound_queue
// --extrinsic=*
// --execution=wasm
// --wasm-execution=compiled
// --steps
// 50
// --repeat
// 20
// --output
// ./parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_inbound_queue.rs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use frame_support::{traits::Get, weights::Weight};
use core::marker::PhantomData;
/// Weight functions for `snowbridge_inbound_queue`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> snowbridge_inbound_queue::WeightInfo for WeightInfo<T> {
/// Storage: EthereumInboundQueue PalletOperatingMode (r:1 w:0)
/// Proof: EthereumInboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen)
/// Storage: EthereumBeaconClient ExecutionHeaders (r:1 w:0)
/// Proof: EthereumBeaconClient ExecutionHeaders (max_values: None, max_size: Some(136), added: 2611, mode: MaxEncodedLen)
/// Storage: EthereumInboundQueue Nonce (r:1 w:1)
/// Proof: EthereumInboundQueue Nonce (max_values: None, max_size: Some(20), added: 2495, mode: MaxEncodedLen)
/// Storage: System Account (r:1 w:1)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
fn submit() -> Weight {
// Proof Size summary in bytes:
// Measured: `457`
// Estimated: `3601`
// Minimum execution time: 69_000_000 picoseconds.
Weight::from_parts(70_000_000, 0)
.saturating_add(Weight::from_parts(0, 3601))
.saturating_add(T::DbWeight::get().reads(4))
.saturating_add(T::DbWeight::get().writes(2))
}
}
@@ -0,0 +1,87 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Autogenerated weights for `snowbridge_outbound_queue`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-10-20, STEPS: `2`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `192.168.1.13`, CPU: `<UNKNOWN>`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-rococo-dev"), DB CACHE: 1024
// Executed Command:
// ../target/release/polkadot-parachain
// benchmark
// pallet
// --chain=bridge-hub-rococo-dev
// --pallet=snowbridge_outbound_queue
// --extrinsic=*
// --execution=wasm
// --wasm-execution=compiled
// --output
// ../parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use frame_support::{traits::Get, weights::Weight};
use core::marker::PhantomData;
/// Weight functions for `snowbridge_outbound_queue`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> snowbridge_outbound_queue::WeightInfo for WeightInfo<T> {
/// Storage: EthereumOutboundQueue MessageLeaves (r:1 w:1)
/// Proof Skipped: EthereumOutboundQueue MessageLeaves (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: EthereumOutboundQueue PendingHighPriorityMessageCount (r:1 w:1)
/// Proof: EthereumOutboundQueue PendingHighPriorityMessageCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
/// Storage: EthereumOutboundQueue Nonce (r:1 w:1)
/// Proof: EthereumOutboundQueue Nonce (max_values: None, max_size: Some(20), added: 2495, mode: MaxEncodedLen)
/// Storage: EthereumOutboundQueue Messages (r:1 w:1)
/// Proof Skipped: EthereumOutboundQueue Messages (max_values: Some(1), max_size: None, mode: Measured)
fn do_process_message() -> Weight {
// Proof Size summary in bytes:
// Measured: `42`
// Estimated: `3485`
// Minimum execution time: 39_000_000 picoseconds.
Weight::from_parts(39_000_000, 3485)
.saturating_add(T::DbWeight::get().reads(4_u64))
.saturating_add(T::DbWeight::get().writes(4_u64))
}
/// Storage: EthereumOutboundQueue MessageLeaves (r:1 w:0)
/// Proof Skipped: EthereumOutboundQueue MessageLeaves (max_values: Some(1), max_size: None, mode: Measured)
/// Storage: System Digest (r:1 w:1)
/// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured)
fn commit() -> Weight {
// Proof Size summary in bytes:
// Measured: `1094`
// Estimated: `2579`
// Minimum execution time: 28_000_000 picoseconds.
Weight::from_parts(28_000_000, 2579)
.saturating_add(T::DbWeight::get().reads(2_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
fn commit_single() -> Weight {
// Proof Size summary in bytes:
// Measured: `1094`
// Estimated: `2579`
// Minimum execution time: 9_000_000 picoseconds.
Weight::from_parts(9_000_000, 1586)
.saturating_add(T::DbWeight::get().reads(2_u64))
.saturating_add(T::DbWeight::get().writes(1_u64))
}
}
@@ -0,0 +1,256 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Autogenerated weights for `snowbridge_system`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-10-09, STEPS: `2`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `crake.local`, CPU: `<UNKNOWN>`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-rococo-dev"), DB CACHE: 1024
// Executed Command:
// target/release/polkadot-parachain
// benchmark
// pallet
// --chain
// bridge-hub-rococo-dev
// --pallet=snowbridge_system
// --extrinsic=*
// --execution=wasm
// --wasm-execution=compiled
// --output
// parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_system.rs
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use frame_support::{traits::Get, weights::Weight};
use core::marker::PhantomData;
/// Weight functions for `snowbridge_system`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> snowbridge_system::WeightInfo for WeightInfo<T> {
/// Storage: ParachainInfo ParachainId (r:1 w:0)
/// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
/// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0)
/// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen)
/// Storage: MessageQueue BookStateFor (r:1 w:1)
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
/// Storage: MessageQueue ServiceHead (r:1 w:1)
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
/// Storage: MessageQueue Pages (r:0 w:1)
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
fn upgrade() -> Weight {
// Proof Size summary in bytes:
// Measured: `80`
// Estimated: `3517`
// Minimum execution time: 47_000_000 picoseconds.
Weight::from_parts(47_000_000, 0)
.saturating_add(Weight::from_parts(0, 3517))
.saturating_add(T::DbWeight::get().reads(4))
.saturating_add(T::DbWeight::get().writes(3))
}
/// Storage: EthereumSystem Agents (r:1 w:1)
/// Proof: EthereumSystem Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen)
/// Storage: System Account (r:2 w:2)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, 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: EthereumOutboundQueue PalletOperatingMode (r:1 w:0)
/// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen)
/// Storage: MessageQueue BookStateFor (r:1 w:1)
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
/// Storage: MessageQueue ServiceHead (r:1 w:1)
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
/// Storage: MessageQueue Pages (r:0 w:1)
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
fn create_agent() -> Weight {
// Proof Size summary in bytes:
// Measured: `187`
// Estimated: `6196`
// Minimum execution time: 87_000_000 picoseconds.
Weight::from_parts(87_000_000, 0)
.saturating_add(Weight::from_parts(0, 6196))
.saturating_add(T::DbWeight::get().reads(7))
.saturating_add(T::DbWeight::get().writes(6))
}
/// Storage: System Account (r:2 w:2)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
/// Storage: EthereumSystem Agents (r:1 w:0)
/// Proof: EthereumSystem Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen)
/// Storage: EthereumSystem Channels (r:1 w:1)
/// Proof: EthereumSystem Channels (max_values: None, max_size: Some(12), added: 2487, 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: EthereumOutboundQueue PalletOperatingMode (r:1 w:0)
/// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen)
/// Storage: MessageQueue BookStateFor (r:1 w:1)
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
/// Storage: MessageQueue Pages (r:1 w:1)
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
fn create_channel() -> Weight {
// Proof Size summary in bytes:
// Measured: `602`
// Estimated: `69050`
// Minimum execution time: 84_000_000 picoseconds.
Weight::from_parts(84_000_000, 0)
.saturating_add(Weight::from_parts(0, 69050))
.saturating_add(T::DbWeight::get().reads(8))
.saturating_add(T::DbWeight::get().writes(5))
}
/// Storage: EthereumSystem Channels (r:1 w:0)
/// Proof: EthereumSystem Channels (max_values: None, max_size: Some(12), added: 2487, mode: MaxEncodedLen)
/// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0)
/// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen)
/// Storage: MessageQueue BookStateFor (r:2 w:2)
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
/// Storage: MessageQueue ServiceHead (r:1 w:0)
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
/// Storage: MessageQueue Pages (r:0 w:1)
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
fn update_channel() -> Weight {
// Proof Size summary in bytes:
// Measured: `256`
// Estimated: `6044`
// Minimum execution time: 41_000_000 picoseconds.
Weight::from_parts(41_000_000, 0)
.saturating_add(Weight::from_parts(0, 6044))
.saturating_add(T::DbWeight::get().reads(5))
.saturating_add(T::DbWeight::get().writes(3))
}
/// Storage: EthereumSystem Channels (r:1 w:0)
/// Proof: EthereumSystem Channels (max_values: None, max_size: Some(12), added: 2487, mode: MaxEncodedLen)
/// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0)
/// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen)
/// Storage: MessageQueue BookStateFor (r:2 w:2)
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
/// Storage: MessageQueue ServiceHead (r:1 w:0)
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
/// Storage: MessageQueue Pages (r:0 w:1)
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
fn force_update_channel() -> Weight {
// Proof Size summary in bytes:
// Measured: `256`
// Estimated: `6044`
// Minimum execution time: 41_000_000 picoseconds.
Weight::from_parts(41_000_000, 0)
.saturating_add(Weight::from_parts(0, 6044))
.saturating_add(T::DbWeight::get().reads(5))
.saturating_add(T::DbWeight::get().writes(3))
}
/// Storage: ParachainInfo ParachainId (r:1 w:0)
/// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
/// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0)
/// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen)
/// Storage: MessageQueue BookStateFor (r:1 w:1)
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
/// Storage: MessageQueue ServiceHead (r:1 w:1)
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
/// Storage: MessageQueue Pages (r:0 w:1)
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
fn set_operating_mode() -> Weight {
// Proof Size summary in bytes:
// Measured: `80`
// Estimated: `3517`
// Minimum execution time: 30_000_000 picoseconds.
Weight::from_parts(30_000_000, 0)
.saturating_add(Weight::from_parts(0, 3517))
.saturating_add(T::DbWeight::get().reads(4))
.saturating_add(T::DbWeight::get().writes(3))
}
/// Storage: EthereumSystem Agents (r:1 w:0)
/// Proof: EthereumSystem Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen)
/// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0)
/// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen)
/// Storage: MessageQueue BookStateFor (r:2 w:2)
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
/// Storage: MessageQueue ServiceHead (r:1 w:0)
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
/// Storage: MessageQueue Pages (r:0 w:1)
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
fn transfer_native_from_agent() -> Weight {
// Proof Size summary in bytes:
// Measured: `252`
// Estimated: `6044`
// Minimum execution time: 43_000_000 picoseconds.
Weight::from_parts(43_000_000, 0)
.saturating_add(Weight::from_parts(0, 6044))
.saturating_add(T::DbWeight::get().reads(5))
.saturating_add(T::DbWeight::get().writes(3))
}
/// Storage: EthereumSystem Agents (r:1 w:0)
/// Proof: EthereumSystem Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen)
/// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0)
/// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen)
/// Storage: MessageQueue BookStateFor (r:2 w:2)
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
/// Storage: MessageQueue ServiceHead (r:1 w:0)
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
/// Storage: MessageQueue Pages (r:0 w:1)
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
fn force_transfer_native_from_agent() -> Weight {
// Proof Size summary in bytes:
// Measured: `252`
// Estimated: `6044`
// Minimum execution time: 42_000_000 picoseconds.
Weight::from_parts(42_000_000, 0)
.saturating_add(Weight::from_parts(0, 6044))
.saturating_add(T::DbWeight::get().reads(5))
.saturating_add(T::DbWeight::get().writes(3))
}
/// Storage: ParachainInfo ParachainId (r:1 w:0)
/// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
/// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0)
/// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen)
/// Storage: MessageQueue BookStateFor (r:1 w:1)
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
/// Storage: MessageQueue ServiceHead (r:1 w:1)
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
/// Storage: MessageQueue Pages (r:0 w:1)
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
fn set_token_transfer_fees() -> Weight {
// Proof Size summary in bytes:
// Measured: `80`
// Estimated: `3517`
// Minimum execution time: 31_000_000 picoseconds.
Weight::from_parts(42_000_000, 3517)
.saturating_add(T::DbWeight::get().reads(4_u64))
.saturating_add(T::DbWeight::get().writes(3_u64))
}
/// Storage: ParachainInfo ParachainId (r:1 w:0)
/// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
/// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0)
/// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen)
/// Storage: MessageQueue BookStateFor (r:1 w:1)
/// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen)
/// Storage: MessageQueue ServiceHead (r:1 w:1)
/// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen)
/// Storage: MessageQueue Pages (r:0 w:1)
/// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen)
fn set_pricing_parameters() -> Weight {
// Proof Size summary in bytes:
// Measured: `80`
// Estimated: `3517`
// Minimum execution time: 31_000_000 picoseconds.
Weight::from_parts(42_000_000, 3517)
.saturating_add(T::DbWeight::get().reads(4_u64))
.saturating_add(T::DbWeight::get().writes(3_u64))
}
}
@@ -26,6 +26,7 @@ use crate::{
},
bridge_to_bulletin_config::WithRococoBulletinMessagesInstance,
bridge_to_westend_config::WithBridgeHubWestendMessagesInstance,
EthereumGatewayAddress,
};
use bp_messages::LaneId;
use bp_relayers::{PayRewardFromAccount, RewardsAccountOwner, RewardsAccountParams};
@@ -46,24 +47,26 @@ use parachains_common::{
};
use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_common::xcm_sender::ExponentialPrice;
use sp_core::Get;
use snowbridge_core::DescribeHere;
use snowbridge_rococo_common::EthereumNetwork;
use snowbridge_runtime_common::XcmExportFeeToSibling;
use sp_core::{Get, H256};
use sp_runtime::traits::AccountIdConversion;
use sp_std::marker::PhantomData;
use xcm::latest::prelude::*;
#[allow(deprecated)]
use xcm_builder::CurrencyAdapter;
use xcm_builder::{
deposit_or_burn_fee, AccountId32Aliases, AllowExplicitUnpaidExecutionFrom,
AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, HandleFee, IsConcrete,
ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents,
CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal,
DescribeFamily, EnsureXcmOrigin, HandleFee, HashedDescription, IsConcrete, ParentAsSuperuser,
ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
XcmFeeToAccount,
};
use xcm_executor::{
traits::{FeeReason, TransactAsset, WithOriginFilter},
traits::{FeeManager, FeeReason, FeeReason::Export, TransactAsset, WithOriginFilter},
XcmExecutor,
};
@@ -160,7 +163,8 @@ impl Contains<RuntimeCall> for SafeCallFilter {
RuntimeCall::System(frame_system::Call::set_storage { items })
if items.iter().all(|(k, _)| {
k.eq(&DeliveryRewardInBalance::key()) |
k.eq(&RequiredStakeForStakeAndSlash::key())
k.eq(&RequiredStakeForStakeAndSlash::key()) |
k.eq(&EthereumGatewayAddress::key())
}) =>
return true,
_ => (),
@@ -217,7 +221,15 @@ impl Contains<RuntimeCall> for SafeCallFilter {
RuntimeCall::BridgePolkadotBulletinMessages(pallet_bridge_messages::Call::<
Runtime,
WithRococoBulletinMessagesInstance,
>::set_operating_mode { .. })
>::set_operating_mode { .. }) |
RuntimeCall::EthereumBeaconClient(
snowbridge_ethereum_beacon_client::Call::force_checkpoint { .. } |
snowbridge_ethereum_beacon_client::Call::set_operating_mode { .. },
) | RuntimeCall::EthereumInboundQueue(
snowbridge_inbound_queue::Call::set_operating_mode { .. },
) | RuntimeCall::EthereumOutboundQueue(
snowbridge_outbound_queue::Call::set_operating_mode { .. },
) | RuntimeCall::EthereumSystem(..)
)
}
}
@@ -291,7 +303,7 @@ impl xcm_executor::Config for XcmConfig {
type SubscriptionService = PolkadotXcm;
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type FeeManager = XcmFeeManagerFromComponents<
type FeeManager = XcmFeeManagerFromComponentsBridgeHub<
WaivedLocations,
(
XcmExportFeeToRelayerRewardAccounts<
@@ -301,12 +313,21 @@ impl xcm_executor::Config for XcmConfig {
crate::bridge_to_westend_config::BridgeHubWestendChainId,
crate::bridge_to_westend_config::AssetHubRococoToAssetHubWestendMessagesLane,
>,
XcmExportFeeToSibling<
bp_rococo::Balance,
AccountId,
TokenLocation,
EthereumNetwork,
Self::AssetTransactor,
crate::EthereumOutboundQueue,
>,
XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>,
),
>;
type MessageExporter = (
crate::bridge_to_westend_config::ToBridgeHubWestendHaulBlobExporter,
crate::bridge_to_bulletin_config::ToRococoBulletinHaulBlobExporter,
crate::bridge_to_ethereum_config::SnowbridgeExporter,
);
type UniversalAliases = Nothing;
type CallDispatcher = WithOriginFilter<SafeCallFilter>;
@@ -367,6 +388,10 @@ impl cumulus_pallet_xcm::Config for Runtime {
type XcmExecutor = XcmExecutor<XcmConfig>;
}
/// Creates an AgentId from a MultiLocation. An AgentId is a unique mapping to a Agent contract on
/// Ethereum which acts as the sovereign account for the MultiLocation.
pub type AgentIdOf = HashedDescription<H256, (DescribeHere, DescribeFamily<DescribeAllTerminal>)>;
/// A `HandleFee` implementation that simply deposits the fees for `ExportMessage` XCM instructions
/// into the accounts that are used for paying the relayer rewards.
/// Burns the fees in case of a failure.
@@ -459,3 +484,41 @@ impl<
fee
}
}
pub struct XcmFeeManagerFromComponentsBridgeHub<WaivedLocations, HandleFee>(
PhantomData<(WaivedLocations, HandleFee)>,
);
impl<WaivedLocations: Contains<MultiLocation>, FeeHandler: HandleFee> FeeManager
for XcmFeeManagerFromComponentsBridgeHub<WaivedLocations, FeeHandler>
{
fn is_waived(origin: Option<&MultiLocation>, fee_reason: FeeReason) -> bool {
let Some(loc) = origin else { return false };
if let Export { network, destination: Here } = fee_reason {
return !(network == EthereumNetwork::get())
}
WaivedLocations::contains(loc)
}
fn handle_fee(fee: MultiAssets, context: Option<&XcmContext>, reason: FeeReason) {
FeeHandler::handle_fee(fee, context, reason);
}
}
#[cfg(feature = "runtime-benchmarks")]
pub mod benchmark_helpers {
use crate::{MultiAssets, MultiLocation, SendError, SendResult, SendXcm, Xcm, XcmHash};
pub struct DoNothingRouter;
impl SendXcm for DoNothingRouter {
type Ticket = ();
fn validate(
_dest: &mut Option<MultiLocation>,
_msg: &mut Option<Xcm<()>>,
) -> SendResult<()> {
Ok(((), MultiAssets::new()))
}
fn deliver(_: ()) -> Result<XcmHash, SendError> {
Ok([0; 32])
}
}
}
@@ -20,13 +20,14 @@ use bp_polkadot_core::Signature;
use bridge_hub_rococo_runtime::{
bridge_common_config, bridge_to_bulletin_config, bridge_to_westend_config,
xcm_config::{RelayNetwork, TokenLocation, XcmConfig},
AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, Executive, ExistentialDeposit,
ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SessionKeys,
SignedExtra, TransactionPayment, UncheckedExtrinsic,
AllPalletsWithoutSystem, BridgeRejectObsoleteHeadersAndMessages, EthereumGatewayAddress,
Executive, ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall,
RuntimeEvent, RuntimeOrigin, SessionKeys, SignedExtra, TransactionPayment, UncheckedExtrinsic,
};
use codec::{Decode, Encode};
use frame_support::{dispatch::GetDispatchInfo, parameter_types, traits::ConstU8};
use parachains_common::{rococo::fee::WeightToFee, AccountId, AuraId, Balance};
use sp_core::H160;
use sp_keyring::AccountKeyring::Alice;
use sp_runtime::{
generic::{Era, SignedPayload},
@@ -182,6 +183,21 @@ mod bridge_hub_westend_tests {
>(collator_session_keys(), bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID)
}
#[test]
fn change_ethereum_gateway_by_governance_works() {
bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::<
Runtime,
EthereumGatewayAddress,
H160,
>(
collator_session_keys(),
bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID,
Box::new(|call| RuntimeCall::System(call).encode()),
|| (EthereumGatewayAddress::key().to_vec(), EthereumGatewayAddress::get()),
|_| [1; 20].into(),
)
}
#[test]
fn change_delivery_reward_by_governance_works() {
bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::<
@@ -95,6 +95,7 @@ pallet-bridge-parachains = { path = "../../../../../bridges/modules/parachains",
pallet-bridge-relayers = { path = "../../../../../bridges/modules/relayers", default-features = false }
pallet-xcm-bridge-hub = { path = "../../../../../bridges/modules/xcm-bridge-hub", default-features = false }
bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", default-features = false }
bridge-hub-common = { path = "../../bridge-hubs/common", default-features = false }
[dev-dependencies]
static_assertions = "1.1"
@@ -117,6 +118,7 @@ std = [
"bp-rococo/std",
"bp-runtime/std",
"bp-westend/std",
"bridge-hub-common/std",
"bridge-runtime-common/std",
"codec/std",
"cumulus-pallet-aura-ext/std",
@@ -181,6 +183,7 @@ std = [
]
runtime-benchmarks = [
"bridge-hub-common/runtime-benchmarks",
"bridge-runtime-common/runtime-benchmarks",
"cumulus-pallet-parachain-system/runtime-benchmarks",
"cumulus-pallet-session-benchmarking/runtime-benchmarks",
@@ -33,8 +33,7 @@ mod weights;
pub mod xcm_config;
use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases;
use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling};
use cumulus_primitives_core::ParaId;
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
@@ -49,6 +48,10 @@ use sp_std::prelude::*;
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use bridge_hub_common::{
message_queue::{NarrowOriginToSibling, ParaIdToSibling},
AggregateMessageOrigin,
};
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
@@ -328,9 +331,8 @@ impl pallet_message_queue::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = weights::pallet_message_queue::WeightInfo<Runtime>;
#[cfg(feature = "runtime-benchmarks")]
type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor<
cumulus_primitives_core::AggregateMessageOrigin,
>;
type MessageProcessor =
pallet_message_queue::mock_helpers::NoopMessageProcessor<AggregateMessageOrigin>;
#[cfg(not(feature = "runtime-benchmarks"))]
type MessageProcessor = xcm_builder::ProcessXcmMessage<
AggregateMessageOrigin,
@@ -0,0 +1,42 @@
[package]
name = "bridge-hub-common"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
description = "Bridge hub common utilities"
license = "Apache-2.0"
[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
scale-info = { version = "2.10.0", default-features = false, features = ["derive"] }
frame-support = { path = "../../../../../substrate/frame/support", default-features = false }
sp-std = { path = "../../../../../substrate/primitives/std", default-features = false }
sp-core = { path = "../../../../../substrate/primitives/core", default-features = false }
sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-features = false }
cumulus-primitives-core = { path = "../../../../primitives/core", default-features = false }
xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false }
pallet-message-queue = { path = "../../../../../substrate/frame/message-queue", default-features = false }
snowbridge-core = { path = "../../../../../bridges/snowbridge/parachain/primitives/core", default-features = false }
[features]
default = ["std"]
std = [
"codec/std",
"cumulus-primitives-core/std",
"frame-support/std",
"pallet-message-queue/std",
"scale-info/std",
"snowbridge-core/std",
"sp-core/std",
"sp-runtime/std",
"sp-std/std",
"xcm/std",
]
runtime-benchmarks = [
"cumulus-primitives-core/runtime-benchmarks",
"frame-support/runtime-benchmarks",
"pallet-message-queue/runtime-benchmarks",
"snowbridge-core/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
@@ -0,0 +1,34 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Custom digest items
use codec::{Decode, Encode};
use sp_core::{RuntimeDebug, H256};
use sp_runtime::generic::DigestItem;
/// Custom header digest items, inserted as DigestItem::Other
#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, RuntimeDebug)]
pub enum CustomDigestItem {
#[codec(index = 0)]
/// Merkle root of outbound Snowbridge messages.
Snowbridge(H256),
}
/// Convert custom application digest item into a concrete digest item
impl From<CustomDigestItem> for DigestItem {
fn from(val: CustomDigestItem) -> Self {
DigestItem::Other(val.encode())
}
}
@@ -0,0 +1,21 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![cfg_attr(not(feature = "std"), no_std)]
pub mod digest_item;
pub mod message_queue;
pub use digest_item::CustomDigestItem;
pub use message_queue::{AggregateMessageOrigin, BridgeHubMessageRouter};
@@ -0,0 +1,146 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Runtime configuration for MessageQueue pallet
use codec::{Decode, Encode, MaxEncodedLen};
use cumulus_primitives_core::{AggregateMessageOrigin as CumulusAggregateMessageOrigin, ParaId};
use frame_support::{
traits::{ProcessMessage, ProcessMessageError, QueueFootprint, QueuePausedQuery},
weights::WeightMeter,
};
use pallet_message_queue::OnQueueChanged;
use scale_info::TypeInfo;
use snowbridge_core::ChannelId;
use sp_std::{marker::PhantomData, prelude::*};
use xcm::v3::{Junction, MultiLocation};
/// The aggregate origin of an inbound message.
/// This is specialized for BridgeHub, as the snowbridge-outbound-queue pallet is also using
/// the shared MessageQueue pallet.
#[derive(Encode, Decode, Copy, MaxEncodedLen, Clone, Eq, PartialEq, TypeInfo, Debug)]
pub enum AggregateMessageOrigin {
/// The message came from the para-chain itself.
Here,
/// The message came from the relay-chain.
///
/// This is used by the DMP queue.
Parent,
/// The message came from a sibling para-chain.
///
/// This is used by the HRMP queue.
Sibling(ParaId),
/// The message came from a snowbridge channel.
///
/// This is used by Snowbridge inbound queue.
Snowbridge(ChannelId),
}
impl From<AggregateMessageOrigin> for MultiLocation {
fn from(origin: AggregateMessageOrigin) -> Self {
use AggregateMessageOrigin::*;
match origin {
Here => MultiLocation::here(),
Parent => MultiLocation::parent(),
Sibling(id) => MultiLocation::new(1, Junction::Parachain(id.into())),
// NOTE: We don't need this conversion for Snowbridge. However we have to
// implement it anyway as xcm_builder::ProcessXcmMessage requires it.
Snowbridge(_) => MultiLocation::default(),
}
}
}
impl From<CumulusAggregateMessageOrigin> for AggregateMessageOrigin {
fn from(origin: CumulusAggregateMessageOrigin) -> Self {
match origin {
CumulusAggregateMessageOrigin::Here => Self::Here,
CumulusAggregateMessageOrigin::Parent => Self::Parent,
CumulusAggregateMessageOrigin::Sibling(id) => Self::Sibling(id),
}
}
}
#[cfg(feature = "runtime-benchmarks")]
impl From<u32> for AggregateMessageOrigin {
fn from(x: u32) -> Self {
match x {
0 => Self::Here,
1 => Self::Parent,
p => Self::Sibling(ParaId::from(p)),
}
}
}
/// Routes messages to either the XCMP or Snowbridge processor.
pub struct BridgeHubMessageRouter<XcmpProcessor, SnowbridgeProcessor>(
PhantomData<(XcmpProcessor, SnowbridgeProcessor)>,
)
where
XcmpProcessor: ProcessMessage<Origin = AggregateMessageOrigin>,
SnowbridgeProcessor: ProcessMessage<Origin = AggregateMessageOrigin>;
impl<XcmpProcessor, SnowbridgeProcessor> ProcessMessage
for BridgeHubMessageRouter<XcmpProcessor, SnowbridgeProcessor>
where
XcmpProcessor: ProcessMessage<Origin = AggregateMessageOrigin>,
SnowbridgeProcessor: ProcessMessage<Origin = AggregateMessageOrigin>,
{
type Origin = AggregateMessageOrigin;
fn process_message(
message: &[u8],
origin: Self::Origin,
meter: &mut WeightMeter,
id: &mut [u8; 32],
) -> Result<bool, ProcessMessageError> {
use AggregateMessageOrigin::*;
match origin {
Here | Parent | Sibling(_) =>
XcmpProcessor::process_message(message, origin, meter, id),
Snowbridge(_) => SnowbridgeProcessor::process_message(message, origin, meter, id),
}
}
}
/// Narrow the scope of the `Inner` query from `AggregateMessageOrigin` to `ParaId`.
///
/// All non-`Sibling` variants will be ignored.
pub struct NarrowOriginToSibling<Inner>(PhantomData<Inner>);
impl<Inner: QueuePausedQuery<ParaId>> QueuePausedQuery<AggregateMessageOrigin>
for NarrowOriginToSibling<Inner>
{
fn is_paused(origin: &AggregateMessageOrigin) -> bool {
match origin {
AggregateMessageOrigin::Sibling(id) => Inner::is_paused(id),
_ => false,
}
}
}
impl<Inner: OnQueueChanged<ParaId>> OnQueueChanged<AggregateMessageOrigin>
for NarrowOriginToSibling<Inner>
{
fn on_queue_changed(origin: AggregateMessageOrigin, fp: QueueFootprint) {
if let AggregateMessageOrigin::Sibling(id) = origin {
Inner::on_queue_changed(id, fp)
}
}
}
/// Convert a sibling `ParaId` to an `AggregateMessageOrigin`.
pub struct ParaIdToSibling;
impl sp_runtime::traits::Convert<ParaId, AggregateMessageOrigin> for ParaIdToSibling {
fn convert(para_id: ParaId) -> AggregateMessageOrigin {
AggregateMessageOrigin::Sibling(para_id)
}
}
@@ -78,10 +78,13 @@ cumulus-primitives-utility = { path = "../../../../primitives/utility", default-
pallet-collator-selection = { path = "../../../../pallets/collator-selection", default-features = false }
parachain-info = { package = "staging-parachain-info", path = "../../../pallets/parachain-info", default-features = false }
parachains-common = { path = "../../../common", default-features = false }
assets-common = { path = "../../assets/common", default-features = false }
snowbridge-rococo-common = { path = "../../../../../bridges/snowbridge/parachain/runtime/rococo-common", default-features = false }
[features]
default = ["std"]
std = [
"assets-common/std",
"codec/std",
"cumulus-pallet-aura-ext/std",
"cumulus-pallet-dmp-queue/std",
@@ -118,6 +121,7 @@ std = [
"polkadot-primitives/std",
"polkadot-runtime-common/std",
"scale-info/std",
"snowbridge-rococo-common/std",
"sp-api/std",
"sp-block-builder/std",
"sp-consensus-aura/std",
@@ -138,6 +142,7 @@ std = [
]
runtime-benchmarks = [
"assets-common/runtime-benchmarks",
"cumulus-pallet-dmp-queue/runtime-benchmarks",
"cumulus-pallet-parachain-system/runtime-benchmarks",
"cumulus-pallet-session-benchmarking/runtime-benchmarks",
@@ -161,6 +166,7 @@ runtime-benchmarks = [
"polkadot-parachain-primitives/runtime-benchmarks",
"polkadot-primitives/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
"snowbridge-rococo-common/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"xcm-executor/runtime-benchmarks",
@@ -32,6 +32,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
mod weights;
pub mod xcm_config;
use assets_common::MultiLocationForAssetId;
use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases;
use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use frame_support::{
@@ -458,6 +459,41 @@ impl pallet_assets::Config<pallet_assets::Instance1> for Runtime {
type BenchmarkHelper = ();
}
parameter_types! {
// we just reuse the same deposits
pub const ForeignAssetsAssetDeposit: Balance = AssetDeposit::get();
pub const ForeignAssetsAssetAccountDeposit: Balance = AssetAccountDeposit::get();
pub const ForeignAssetsApprovalDeposit: Balance = ApprovalDeposit::get();
pub const ForeignAssetsAssetsStringLimit: u32 = AssetsStringLimit::get();
pub const ForeignAssetsMetadataDepositBase: Balance = MetadataDepositBase::get();
pub const ForeignAssetsMetadataDepositPerByte: Balance = MetadataDepositPerByte::get();
}
/// Another pallet assets instance to store foreign assets from bridgehub.
pub type ForeignAssetsInstance = pallet_assets::Instance2;
impl pallet_assets::Config<ForeignAssetsInstance> for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type AssetId = MultiLocationForAssetId;
type AssetIdParameter = MultiLocationForAssetId;
type Currency = Balances;
type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
type ForceOrigin = EnsureRoot<AccountId>;
type AssetDeposit = ForeignAssetsAssetDeposit;
type MetadataDepositBase = ForeignAssetsMetadataDepositBase;
type MetadataDepositPerByte = ForeignAssetsMetadataDepositPerByte;
type ApprovalDeposit = ForeignAssetsApprovalDeposit;
type StringLimit = ForeignAssetsAssetsStringLimit;
type Freezer = ();
type Extra = ();
type WeightInfo = pallet_assets::weights::SubstrateWeight<Runtime>;
type CallbackHandle = ();
type AssetAccountDeposit = ForeignAssetsAssetAccountDeposit;
type RemoveItemsLimit = frame_support::traits::ConstU32<1000>;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = xcm_config::XcmBenchmarkHelper;
}
parameter_types! {
pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4);
@@ -626,6 +662,7 @@ construct_runtime!(
// The main stage.
Assets: pallet_assets::<Instance1>::{Pallet, Call, Storage, Event<T>} = 50,
ForeignAssets: pallet_assets::<Instance2>::{Pallet, Call, Storage, Event<T>} = 51,
Sudo: pallet_sudo::{Pallet, Call, Storage, Event<T>, Config<T>} = 255,
}
@@ -24,8 +24,8 @@
//! soon.
use super::{
AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Balance, Balances,
ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
WeightToFee, XcmpQueue,
ForeignAssets, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent,
RuntimeOrigin, WeightToFee, XcmpQueue,
};
use core::marker::PhantomData;
use frame_support::{
@@ -42,18 +42,19 @@ use pallet_assets::Instance1;
use pallet_xcm::XcmPassthrough;
use polkadot_parachain_primitives::primitives::Sibling;
use polkadot_runtime_common::impls::ToAuthor;
use snowbridge_rococo_common::EthereumNetwork;
use sp_runtime::traits::Zero;
use xcm::latest::prelude::*;
#[allow(deprecated)]
use xcm_builder::CurrencyAdapter;
use xcm_builder::{
AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses,
AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex,
ConvertedConcreteId, DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin,
FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentAsSuperuser,
ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic,
ConvertedConcreteId, CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry,
EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset,
NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, StartsWith, TakeWeightCredit, TrailingSetTopicAsId,
UsingComponents, WithComputedOrigin, WithUniqueTopic,
};
use xcm_executor::{traits::JustTry, XcmExecutor};
@@ -125,8 +126,28 @@ pub type FungiblesTransactor = FungiblesAdapter<
CheckingAccount,
>;
/// `AssetId/Balance` converter for `TrustBackedAssets`
pub type ForeignAssetsConvertedConcreteId =
assets_common::ForeignAssetsConvertedConcreteId<StartsWith<RelayLocation>, Balance>;
/// Means for transacting foreign assets from different global consensus.
pub type ForeignFungiblesTransactor = FungiblesAdapter<
// Use this fungibles implementation:
ForeignAssets,
// Use this currency when it is a fungible asset matching the given location or name:
ForeignAssetsConvertedConcreteId,
// Convert an XCM MultiLocation into a local account id:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We dont need to check teleports here.
NoChecking,
// The account to use for tracking teleports.
CheckingAccount,
>;
/// Means for transacting assets on this chain.
pub type AssetTransactors = (CurrencyTransactor, FungiblesTransactor);
pub type AssetTransactors = (CurrencyTransactor, ForeignFungiblesTransactor, FungiblesTransactor);
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
@@ -202,16 +223,22 @@ pub type Barrier = TrailingSetTopicAsId<
pub type AccountIdOf<R> = <R as frame_system::Config>::AccountId;
/// Asset filter that allows all assets from a certain location matching asset id.
pub struct AssetsFrom<T>(PhantomData<T>);
impl<T: Get<MultiLocation>> ContainsPair<MultiAsset, MultiLocation> for AssetsFrom<T> {
pub struct AssetPrefixFrom<Prefix, Origin>(PhantomData<(Prefix, Origin)>);
impl<Prefix, Origin> ContainsPair<MultiAsset, MultiLocation> for AssetPrefixFrom<Prefix, Origin>
where
Prefix: Get<MultiLocation>,
Origin: Get<MultiLocation>,
{
fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool {
let loc = T::get();
let loc = Origin::get();
&loc == origin &&
matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) }
if asset_loc.starts_with(&loc))
if asset_loc.starts_with(&Prefix::get()))
}
}
type AssetsFrom<T> = AssetPrefixFrom<T, T>;
/// Asset filter that allows native/relay asset if coming from a certain location.
pub struct NativeAssetFrom<T>(PhantomData<T>);
impl<T: Get<MultiLocation>> ContainsPair<MultiAsset, MultiLocation> for NativeAssetFrom<T> {
@@ -267,6 +294,7 @@ parameter_types! {
0,
X2(PalletInstance(50), GeneralIndex(TELEPORTABLE_ASSET_ID.into()))
);
pub EthereumLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(EthereumNetwork::get())));
}
/// Accepts asset with ID `AssetLocation` and is coming from `Origin` chain.
@@ -280,8 +308,12 @@ impl<AssetLocation: Get<MultiLocation>, Origin: Get<MultiLocation>>
}
}
pub type Reserves =
(NativeAsset, AssetsFrom<SystemAssetHubLocation>, NativeAssetFrom<SystemAssetHubLocation>);
pub type Reserves = (
NativeAsset,
AssetsFrom<SystemAssetHubLocation>,
NativeAssetFrom<SystemAssetHubLocation>,
AssetPrefixFrom<EthereumLocation, SystemAssetHubLocation>,
);
pub type TrustedTeleporters =
(AssetFromChain<LocalTeleportableToAssetHub, SystemAssetHubLocation>,);
@@ -362,3 +394,12 @@ impl cumulus_pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type XcmExecutor = XcmExecutor<XcmConfig>;
}
/// Simple conversion of `u32` into an `AssetId` for use in benchmarking.
pub struct XcmBenchmarkHelper;
#[cfg(feature = "runtime-benchmarks")]
impl pallet_assets::BenchmarkHelper<MultiLocation> for XcmBenchmarkHelper {
fn create_asset_id_parameter(id: u32) -> MultiLocation {
MultiLocation { parents: 1, interior: X1(Parachain(id)) }
}
}