// SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 Snowfork use crate as snowbridge_system; use frame_support::{ derive_impl, parameter_types, traits::{tokens::fungible::Mutate, ConstU128, ConstU64, ConstU8}, weights::IdentityFee, PalletId, }; use sp_core::H256; use xcm_executor::traits::ConvertLocation; use snowbridge_core::{ gwei, meth, outbound::ConstantGasMeter, sibling_sovereign_account, AgentId, AllowSiblingsOnly, ParaId, PricingParameters, Rewards, }; use sp_runtime::{ traits::{AccountIdConversion, BlakeTwo256, IdentityLookup, Keccak256}, AccountId32, BuildStorage, FixedU128, }; use xcm::prelude::*; #[cfg(feature = "runtime-benchmarks")] use crate::BenchmarkHelper; type Block = frame_system::mocking::MockBlock; type Balance = u128; pub type AccountId = AccountId32; // A stripped-down version of pallet-xcm that only inserts an XCM origin into the runtime #[allow(dead_code)] #[frame_support::pallet] mod pallet_xcm_origin { use frame_support::{ pallet_prelude::*, traits::{Contains, OriginTrait}, }; use xcm::latest::prelude::*; #[pallet::pallet] pub struct Pallet(_); #[pallet::config] pub trait Config: frame_system::Config { type RuntimeOrigin: From + From<::RuntimeOrigin>; } // Insert this custom Origin into the aggregate RuntimeOrigin #[pallet::origin] #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct Origin(pub Location); impl From for Origin { fn from(location: Location) -> Origin { Origin(location) } } /// `EnsureOrigin` implementation succeeding with a `Location` value to recognize and /// filter the contained location pub struct EnsureXcm(PhantomData); impl, F: Contains> EnsureOrigin for EnsureXcm where O::PalletsOrigin: From + TryInto, { type Success = Location; fn try_origin(outer: O) -> Result { outer.try_with_caller(|caller| { caller.try_into().and_then(|o| match o { Origin(location) if F::contains(&location) => Ok(location), o => Err(o.into()), }) }) } #[cfg(feature = "runtime-benchmarks")] fn try_successful_origin() -> Result { Ok(O::from(Origin(Location::new(1, [Parachain(2000)])))) } } } // Configure a mock runtime to test the pallet. frame_support::construct_runtime!( pub enum Test { System: frame_system, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, XcmOrigin: pallet_xcm_origin::{Pallet, Origin}, OutboundQueue: snowbridge_pallet_outbound_queue::{Pallet, Call, Storage, Event}, EthereumSystem: snowbridge_system, MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event} } ); #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeTask = RuntimeTask; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; type RuntimeEvent = RuntimeEvent; type BlockHashCount = ConstU64<250>; type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; type Nonce = u64; type Block = Block; } impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); type ReserveIdentifier = [u8; 8]; type Balance = Balance; type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ConstU128<1>; type AccountStore = System; type WeightInfo = (); type FreezeIdentifier = (); type MaxFreezes = (); type RuntimeHoldReason = (); type RuntimeFreezeReason = (); } impl pallet_xcm_origin::Config for Test { type RuntimeOrigin = RuntimeOrigin; } parameter_types! { pub const HeapSize: u32 = 32 * 1024; pub const MaxStale: u32 = 32; pub static ServiceWeight: Option = Some(Weight::from_parts(100, 100)); } impl pallet_message_queue::Config for Test { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type MessageProcessor = OutboundQueue; type Size = u32; type QueueChangeHandler = (); type HeapSize = HeapSize; type MaxStale = MaxStale; type ServiceWeight = ServiceWeight; type QueuePausedQuery = (); } parameter_types! { pub const MaxMessagePayloadSize: u32 = 1024; pub const MaxMessagesPerBlock: u32 = 20; pub const OwnParaId: ParaId = ParaId::new(1013); } impl snowbridge_pallet_outbound_queue::Config for Test { type RuntimeEvent = RuntimeEvent; type Hashing = Keccak256; type MessageQueue = MessageQueue; type Decimals = ConstU8<10>; type MaxMessagePayloadSize = MaxMessagePayloadSize; type MaxMessagesPerBlock = MaxMessagesPerBlock; type GasMeter = ConstantGasMeter; type Balance = u128; type PricingParameters = EthereumSystem; type Channels = EthereumSystem; type WeightToFee = IdentityFee; type WeightInfo = (); } parameter_types! { pub const SS58Prefix: u8 = 42; pub const AnyNetwork: Option = None; pub const RelayNetwork: Option = Some(NetworkId::Kusama); pub const RelayLocation: Location = Location::parent(); pub UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(1013)].into(); } pub const DOT: u128 = 10_000_000_000; parameter_types! { pub TreasuryAccount: AccountId = PalletId(*b"py/trsry").into_account_truncating(); pub Fee: u64 = 1000; pub const RococoNetwork: NetworkId = NetworkId::Rococo; pub const InitialFunding: u128 = 1_000_000_000_000; pub AssetHubParaId: ParaId = ParaId::new(1000); pub TestParaId: u32 = 2000; pub Parameters: PricingParameters = PricingParameters { exchange_rate: FixedU128::from_rational(1, 400), fee_per_gas: gwei(20), rewards: Rewards { local: DOT, remote: meth(1) } }; pub const InboundDeliveryCost: u128 = 1_000_000_000; } #[cfg(feature = "runtime-benchmarks")] impl BenchmarkHelper for () { fn make_xcm_origin(location: Location) -> RuntimeOrigin { RuntimeOrigin::from(pallet_xcm_origin::Origin(location)) } } impl crate::Config for Test { type RuntimeEvent = RuntimeEvent; type OutboundQueue = OutboundQueue; type SiblingOrigin = pallet_xcm_origin::EnsureXcm; type AgentIdOf = snowbridge_core::AgentIdOf; type TreasuryAccount = TreasuryAccount; type Token = Balances; type DefaultPricingParameters = Parameters; type WeightInfo = (); type InboundDeliveryCost = InboundDeliveryCost; #[cfg(feature = "runtime-benchmarks")] type Helper = (); } // Build genesis storage according to the mock runtime. pub fn new_test_ext(genesis_build: bool) -> sp_io::TestExternalities { let mut storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); if genesis_build { crate::GenesisConfig:: { para_id: OwnParaId::get(), asset_hub_para_id: AssetHubParaId::get(), _config: Default::default(), } .assimilate_storage(&mut storage) .unwrap(); } let mut ext: sp_io::TestExternalities = storage.into(); let initial_amount = InitialFunding::get(); let test_para_id = TestParaId::get(); let sovereign_account = sibling_sovereign_account::(test_para_id.into()); let treasury_account = TreasuryAccount::get(); ext.execute_with(|| { System::set_block_number(1); Balances::mint_into(&AccountId32::from([0; 32]), initial_amount).unwrap(); Balances::mint_into(&sovereign_account, initial_amount).unwrap(); Balances::mint_into(&treasury_account, initial_amount).unwrap(); }); ext } // Test helpers pub fn make_xcm_origin(location: Location) -> RuntimeOrigin { pallet_xcm_origin::Origin(location).into() } pub fn make_agent_id(location: Location) -> AgentId { ::AgentIdOf::convert_location(&location) .expect("convert location") }