Skip to content

Commit

Permalink
adds snowbridge
Browse files Browse the repository at this point in the history
  • Loading branch information
claravanstaden authored and claravanstaden committed Jan 26, 2024
1 parent 18a45cc commit 4fcef54
Show file tree
Hide file tree
Showing 27 changed files with 2,219 additions and 41 deletions.
2 changes: 1 addition & 1 deletion relay/kusama/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ parameter_types! {
pub const MaxAssetsIntoHolding: u32 = 64;
}

/// Kusama Relay recognizes/respects AssetHub, Encointer, and BridgeHub chains as teleporters.
/// Kusama Relay recognizes/respects AssetHub, Encointer and BridgeHub chains as teleporters.
pub type TrustedTeleporters = (
xcm_builder::Case<KsmForAssetHub>,
xcm_builder::Case<KsmForEncointer>,
Expand Down
6 changes: 6 additions & 0 deletions system-parachains/asset-hubs/asset-hub-kusama/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ assets-common = { default-features = false , version = "0.4.0" }

# Bridges
pallet-xcm-bridge-hub-router = { default-features = false , version = "0.2.0" }
snowbridge-router-primitives = { default-features = false , version = "1.0.0" } #todo publish
snowbridge-kusama-common = { default-features = false , version = "1.0.0" } #todo publish

[dev-dependencies]
asset-test-utils = { version = "4.0.0" }
Expand Down Expand Up @@ -138,6 +140,8 @@ runtime-benchmarks = [
"pallet-xcm/runtime-benchmarks",
"polkadot-parachain-primitives/runtime-benchmarks",
"polkadot-runtime-common/runtime-benchmarks",
"snowbridge-kusama-common/runtime-benchmarks",
"snowbridge-router-primitives/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"xcm-executor/runtime-benchmarks",
Expand Down Expand Up @@ -228,6 +232,8 @@ std = [
"polkadot-runtime-common/std",
"polkadot-runtime-constants/std",
"scale-info/std",
"snowbridge-kusama-common/std",
"snowbridge-router-primitives/std",
"sp-api/std",
"sp-block-builder/std",
"sp-consensus-aura/std",
Expand Down
8 changes: 6 additions & 2 deletions system-parachains/asset-hubs/asset-hub-kusama/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ pub mod xcm_config;
use assets_common::{
foreign_creators::ForeignCreators,
local_and_foreign_assets::{LocalAndForeignAssets, MultiLocationConverter},
matching::FromSiblingParachain,
matching::{FromNetwork, FromSiblingParachain},
AssetIdForTrustBackedAssetsConvert, MultiLocationForAssetId,
};
use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases;
use snowbridge_kusama_common::EthereumNetwork;
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
Expand Down Expand Up @@ -381,7 +382,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,
>;
Expand Down
115 changes: 109 additions & 6 deletions system-parachains/asset-hubs/asset-hub-kusama/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use super::{
use crate::{ForeignAssets, ForeignAssetsInstance};
use assets_common::{
local_and_foreign_assets::MatchesLocalAndForeignAssetsMultiLocation,
matching::{FromSiblingParachain, IsForeignConcreteAsset},
matching::{FromNetwork, FromSiblingParachain, IsForeignConcreteAsset},
};
use frame_support::{
match_types, parameter_types,
Expand All @@ -39,6 +39,8 @@ use parachains_common::{
},
};
use polkadot_parachain_primitives::primitives::Sibling;
use snowbridge_kusama_common::EthereumNetwork;
use snowbridge_router_primitives::inbound::GlobalConsensusEthereumConvertsFor;
use sp_runtime::traits::{AccountIdConversion, ConvertInto};
use system_parachains_constants::TREASURY_PALLET_ID;
use xcm::latest::prelude::*;
Expand All @@ -49,7 +51,7 @@ use xcm_builder::{
EnsureXcmOrigin, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription,
IsConcrete, LocalMint, NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative,
SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative,
SignedToAccountId32, SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus,
SignedToAccountId32, SovereignPaidRemoteExporter, SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus,
TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin,
WithUniqueTopic, XcmFeesToAccount,
};
Expand Down Expand Up @@ -266,8 +268,9 @@ impl Contains<RuntimeCall> for SafeCallFilter {
match call {
RuntimeCall::System(frame_system::Call::set_storage { items })
if items.iter().all(|(k, _)| {
k.eq(&bridging::XcmBridgeHubRouterBaseFee::key()) ||
k.eq(&bridging::XcmBridgeHubRouterByteFee::key())
k.eq(&bridging::XcmBridgeHubRouterByteFee::key()) |
k.eq(&bridging::XcmBridgeHubRouterBaseFee::key()) |
k.eq(&bridging::to_ethereum::BridgeHubEthereumBaseFee::key())
}) =>
return true,
_ => (),
Expand Down Expand Up @@ -549,7 +552,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 KSM and assets created
// under `pallet-assets`. Users must use teleport where allowed (e.g. KSM with the Relay Chain).
type IsReserve = (bridging::to_polkadot::IsTrustedBridgedReserveLocationForConcreteAsset,);
type IsReserve = (
bridging::to_polkadot::IsTrustedBridgedReserveLocationForConcreteAsset,
bridging::to_ethereum::IsTrustedBridgedReserveLocationForForeignAsset,
);
type IsTeleporter = TrustedTeleporters;
type UniversalLocation = UniversalLocation;
type Barrier = Barrier;
Expand Down Expand Up @@ -586,6 +592,19 @@ impl xcm_executor::Config for XcmConfig {
XcmAssetFeesReceiver,
>,
>,
// This trader allows to pay with `is_sufficient=true` "Foreign" assets from dedicated
// `pallet_assets` instance - `ForeignAssets`.
cumulus_primitives_utility::TakeFirstAssetTrader<
AccountId,
ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger,
ForeignAssetsConvertedConcreteId,
ForeignAssets,
cumulus_primitives_utility::XcmFeesTo32ByteAccount<
ForeignFungiblesTransactor,
AccountId,
XcmAssetFeesReceiver,
>,
>,
);
type ResponseHandler = PolkadotXcm;
type AssetTrap = PolkadotXcm;
Expand All @@ -597,7 +616,8 @@ impl xcm_executor::Config for XcmConfig {
type AssetExchanger = ();
type FeeManager = XcmFeesToAccount<Self, WaivedLocations, AccountId, TreasuryAccount>;
type MessageExporter = ();
type UniversalAliases = bridging::to_polkadot::UniversalAliases;
type UniversalAliases =
(bridging::to_polkadot::UniversalAliases, bridging::to_ethereum::UniversalAliases);
type CallDispatcher = WithOriginFilter<SafeCallFilter>;
type SafeCallFilter = SafeCallFilter;
type Aliasers = Nothing;
Expand All @@ -624,6 +644,9 @@ pub type XcmRouter = WithUniqueTopic<(
// Router which wraps and sends xcm to BridgeHub to be delivered to the Polkadot
// GlobalConsensus
ToPolkadotXcmRouter,
// Router which wraps and sends xcm to BridgeHub to be delivered to the Ethereum
// GlobalConsensus
SovereignPaidRemoteExporter<bridging::EthereumNetworkExportTable, XcmpQueue, UniversalLocation>,
)>;

#[cfg(feature = "runtime-benchmarks")]
Expand Down Expand Up @@ -676,6 +699,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.
Expand Down Expand Up @@ -741,10 +765,17 @@ pub mod bridging {
sp_std::vec::Vec::new().into_iter()
.chain(to_polkadot::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_polkadot {
use super::*;

Expand Down Expand Up @@ -836,4 +867,76 @@ pub mod bridging {
Some(alias.expect("we expect here BridgeHubKusama to Polkadot mapping at least"))
}
}

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_kusama_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;

#[cfg(feature = "runtime-benchmarks")]
impl BridgingBenchmarksHelper {
pub fn prepare_universal_alias() -> Option<(MultiLocation, Junction)> {
let alias = to_polkadot::UniversalAliases::get().into_iter().find_map(
|(location, junction)| {
match to_polkadot::SiblingBridgeHubWithBridgeHubPolkadotInstance::get()
.eq(&location)
{
true => Some((location, junction)),
false => None,
}
},
);
assert!(alias.is_some(), "we expect here BridgeHubKusama to Polkadot mapping at least");
Some(alias.unwrap())
}
}
}
52 changes: 52 additions & 0 deletions system-parachains/asset-hubs/asset-hub-kusama/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,58 @@ 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()
}
},
)
}

// missing stuff from asset_test_utils::test_cases_over_bridge
// TODO: replace me with direct usages of `asset_test_utils` after deps are bumped to (at least) 1.4
mod missing_asset_test_utils_test_cases_over_bridge {
Expand Down
2 changes: 2 additions & 0 deletions system-parachains/asset-hubs/asset-hub-polkadot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ assets-common = { default-features = false , version = "0.4.0" }

# Bridges
pallet-xcm-bridge-hub-router = { default-features = false , version = "0.2.0" }
snowbridge-router-primitives = { default-features = false, version = "1.0.0" } #todo publish
snowbridge-polkadot-common = { default-features = false, version = "1.0.0" } #todo publish

[dev-dependencies]
hex-literal = "0.4.1"
Expand Down
9 changes: 7 additions & 2 deletions system-parachains/asset-hubs/asset-hub-polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,11 @@ mod weights;
pub mod xcm_config;

use assets_common::{
foreign_creators::ForeignCreators, matching::FromSiblingParachain, MultiLocationForAssetId,
foreign_creators::ForeignCreators, matching::{FromNetwork, FromSiblingParachain},
MultiLocationForAssetId,
};
use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases;
use snowbridge_polkadot_common::EthereumNetwork;
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
Expand Down Expand Up @@ -321,7 +323,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,
>;
Expand Down
Loading

0 comments on commit 4fcef54

Please sign in to comment.