1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
#![cfg_attr(not(feature = "std"), no_std)]
18
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
19
#![recursion_limit = "256"]
20

            
21
extern crate alloc;
22

            
23
// Make the WASM binary available.
24
#[cfg(feature = "std")]
25
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
26

            
27
use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
28
#[cfg(feature = "std")]
29
use sp_version::NativeVersion;
30

            
31
#[cfg(any(feature = "std", test))]
32
pub use sp_runtime::BuildStorage;
33

            
34
pub mod genesis_config_presets;
35
pub mod migrations;
36
pub mod weights;
37

            
38
pub use sp_runtime::{traits::ExtrinsicLike, MultiAddress, Perbill, Permill};
39
use {
40
    alloc::vec,
41
    alloc::vec::Vec,
42
    cumulus_primitives_core::AggregateMessageOrigin,
43
    cumulus_primitives_core::ParaId,
44
    dp_impl_tanssi_pallets_config::impl_tanssi_pallets_config,
45
    frame_support::{
46
        construct_runtime,
47
        dispatch::DispatchClass,
48
        dynamic_params::{dynamic_pallet_params, dynamic_params},
49
        genesis_builder_helper::{build_state, get_preset},
50
        pallet_prelude::DispatchResult,
51
        parameter_types,
52
        traits::{
53
            tokens::ConversionToAssetBalance, ConstBool, ConstU128, ConstU32, ConstU64, ConstU8,
54
            Contains, InsideBoth, InstanceFilter,
55
        },
56
        weights::{
57
            constants::{
58
                BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight,
59
                WEIGHT_REF_TIME_PER_SECOND,
60
            },
61
            ConstantMultiplier, FeePolynomial, Weight, WeightToFee as _, WeightToFeeCoefficient,
62
            WeightToFeeCoefficients, WeightToFeePolynomial,
63
        },
64
    },
65
    frame_system::{
66
        limits::{BlockLength, BlockWeights},
67
        EnsureRoot,
68
    },
69
    nimbus_primitives::{NimbusId, SlotBeacon},
70
    pallet_parameters,
71
    pallet_transaction_payment::FungibleAdapter,
72
    parity_scale_codec::{Decode, DecodeWithMemTracking, Encode},
73
    polkadot_runtime_common::SlowAdjustingFeeUpdate,
74
    scale_info::TypeInfo,
75
    serde::{Deserialize, Serialize},
76
    smallvec::smallvec,
77
    sp_api::impl_runtime_apis,
78
    sp_consensus_slots::{Slot, SlotDuration},
79
    sp_core::{Get, MaxEncodedLen, OpaqueMetadata},
80
    sp_keyring::Sr25519Keyring,
81
    sp_runtime::{
82
        generic,
83
        generic::SignedPayload,
84
        impl_opaque_keys,
85
        traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify},
86
        transaction_validity::{TransactionSource, TransactionValidity},
87
        ApplyExtrinsicResult, Cow, MultiSignature, SaturatedConversion,
88
    },
89
    sp_version::RuntimeVersion,
90
    xcm::prelude::Location,
91
    xcm::Version as XcmVersion,
92
    xcm::{
93
        v5::NetworkId, IntoVersion, VersionedAssetId, VersionedAssets, VersionedLocation,
94
        VersionedXcm,
95
    },
96
    xcm_runtime_apis::{
97
        dry_run::{CallDryRunEffects, Error as XcmDryRunApiError, XcmDryRunEffects},
98
        fees::Error as XcmPaymentApiError,
99
    },
100
};
101

            
102
pub mod xcm_config;
103

            
104
// Polkadot imports
105
use polkadot_runtime_common::BlockHashCount;
106

            
107
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
108
pub type Signature = MultiSignature;
109

            
110
/// Some way of identifying an account on the chain. We intentionally make it equivalent
111
/// to the public key of our transaction signing scheme.
112
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
113

            
114
/// Balance of an account.
115
pub type Balance = u128;
116

            
117
/// Index of a transaction in the chain.
118
pub type Index = u32;
119

            
120
/// A hash of some data used by the chain.
121
pub type Hash = sp_core::H256;
122

            
123
/// An index to a block.
124
pub type BlockNumber = u32;
125

            
126
/// The address format for describing accounts.
127
pub type Address = MultiAddress<AccountId, ()>;
128

            
129
/// Block header type as expected by this runtime.
130
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
131

            
132
/// Block type as expected by this runtime.
133
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
134

            
135
/// A Block signed with a Justification
136
pub type SignedBlock = generic::SignedBlock<Block>;
137

            
138
/// BlockId type as expected by this runtime.
139
pub type BlockId = generic::BlockId<Block>;
140

            
141
/// The SignedExtension to the basic transaction logic.
142
pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim<
143
    Runtime,
144
    (
145
        frame_system::CheckNonZeroSender<Runtime>,
146
        frame_system::CheckSpecVersion<Runtime>,
147
        frame_system::CheckTxVersion<Runtime>,
148
        frame_system::CheckGenesis<Runtime>,
149
        frame_system::CheckEra<Runtime>,
150
        frame_system::CheckNonce<Runtime>,
151
        frame_system::CheckWeight<Runtime>,
152
        pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
153
    ),
154
>;
155

            
156
/// Unchecked extrinsic type as expected by this runtime.
157
pub type UncheckedExtrinsic =
158
    generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, TxExtension>;
159

            
160
/// Extrinsic type that has already been checked.
161
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, RuntimeCall, TxExtension>;
162

            
163
/// Executive: handles dispatch to the various modules.
164
pub type Executive = frame_executive::Executive<
165
    Runtime,
166
    Block,
167
    frame_system::ChainContext<Runtime>,
168
    Runtime,
169
    AllPalletsWithSystem,
170
>;
171

            
172
pub mod currency {
173
    use super::Balance;
174

            
175
    pub const MICROUNIT: Balance = 1_000_000;
176
    pub const MILLIUNIT: Balance = 1_000_000_000;
177
    pub const UNIT: Balance = 1_000_000_000_000;
178
    pub const KILOUNIT: Balance = 1_000_000_000_000_000;
179

            
180
    pub const STORAGE_BYTE_FEE: Balance = 100 * MICROUNIT;
181

            
182
    pub const fn deposit(items: u32, bytes: u32) -> Balance {
183
        items as Balance * 100 * MILLIUNIT + (bytes as Balance) * STORAGE_BYTE_FEE
184
    }
185
}
186

            
187
/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the
188
/// node's balance type.
189
///
190
/// This should typically create a mapping between the following ranges:
191
///   - `[0, MAXIMUM_BLOCK_WEIGHT]`
192
///   - `[Balance::min, Balance::max]`
193
///
194
/// Yet, it can be used for any other sort of change to weight-fee. Some examples being:
195
///   - Setting it to `0` will essentially disable the weight fee.
196
///   - Setting it to `1` will cause the literal `#[weight = x]` values to be charged.
197
pub struct WeightToFee;
198
impl frame_support::weights::WeightToFee for WeightToFee {
199
    type Balance = Balance;
200

            
201
264
    fn weight_to_fee(weight: &Weight) -> Self::Balance {
202
264
        let time_poly: FeePolynomial<Balance> = RefTimeToFee::polynomial().into();
203
264
        let proof_poly: FeePolynomial<Balance> = ProofSizeToFee::polynomial().into();
204

            
205
        // Take the maximum instead of the sum to charge by the more scarce resource.
206
264
        time_poly
207
264
            .eval(weight.ref_time())
208
264
            .max(proof_poly.eval(weight.proof_size()))
209
264
    }
210
}
211
pub struct RefTimeToFee;
212
impl WeightToFeePolynomial for RefTimeToFee {
213
    type Balance = Balance;
214
264
    fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
215
        // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT:
216
        // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT
217
264
        let p = MILLIUNIT / 10;
218
264
        let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time());
219
264
        smallvec![WeightToFeeCoefficient {
220
            degree: 1,
221
            negative: false,
222
            coeff_frac: Perbill::from_rational(p % q, q),
223
            coeff_integer: p / q,
224
        }]
225
264
    }
226
}
227

            
228
/// Maps the proof size component of `Weight` to a fee.
229
pub struct ProofSizeToFee;
230
impl WeightToFeePolynomial for ProofSizeToFee {
231
    type Balance = Balance;
232
264
    fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
233
        // Map 10kb proof to 1 CENT.
234
264
        let p = MILLIUNIT / 10;
235
264
        let q = 10_000;
236

            
237
264
        smallvec![WeightToFeeCoefficient {
238
            degree: 1,
239
            negative: false,
240
            coeff_frac: Perbill::from_rational(p % q, q),
241
            coeff_integer: p / q,
242
        }]
243
264
    }
244
}
245

            
246
parameter_types! {
247
        /// Network and location for the Ethereum chain. On Starlight, the Ethereum chain bridged
248
        /// to is the Ethereum mainnet, with chain ID 1.
249
        /// <https://chainlist.org/chain/1>
250
        /// <https://ethereum.org/en/developers/docs/apis/json-rpc/#net_version>
251
        pub EthereumNetwork: NetworkId = {
252
            use crate::dynamic_params::xcm_config::RelayNetwork;
253
            use crate::dynamic_params::EthereumNetworkChainId;
254

            
255
            // derive chain_id from RelayNetwork
256
            let chain_id = EthereumNetworkChainId::from_relay_network(&RelayNetwork::get())
257
                .unwrap_or(EthereumNetworkChainId::EthereumMainnet)
258
                .as_u64();
259

            
260
            NetworkId::Ethereum { chain_id }
261
        };
262
        pub EthereumLocation: Location = Location::new(2, EthereumNetwork::get());
263
}
264

            
265
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
266
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
267
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
268
/// to even the core data structures.
269
pub mod opaque {
270
    use {
271
        super::*,
272
        sp_runtime::{generic, traits::BlakeTwo256},
273
    };
274

            
275
    pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
276
    /// Opaque block header type.
277
    pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
278
    /// Opaque block type.
279
    pub type Block = generic::Block<Header, UncheckedExtrinsic>;
280
    /// Opaque block identifier type.
281
    pub type BlockId = generic::BlockId<Block>;
282
}
283

            
284
impl_opaque_keys! {
285
    pub struct SessionKeys { }
286
}
287

            
288
#[sp_version::runtime_version]
289
pub const VERSION: RuntimeVersion = RuntimeVersion {
290
    spec_name: Cow::Borrowed("container-chain-template"),
291
    impl_name: Cow::Borrowed("container-chain-template"),
292
    authoring_version: 1,
293
    spec_version: 1700,
294
    impl_version: 0,
295
    apis: RUNTIME_API_VERSIONS,
296
    transaction_version: 1,
297
    system_version: 1,
298
};
299

            
300
/// This determines the average expected block time that we are targeting.
301
/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`.
302
/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked
303
/// up by `pallet_aura` to implement `fn slot_duration()`.
304
///
305
/// Change this to adjust the block time.
306
pub const MILLISECS_PER_BLOCK: u64 = 6000;
307

            
308
// NOTE: Currently it is not possible to change the slot duration after the chain has started.
309
//       Attempting to do so will brick block production.
310
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
311

            
312
// Time is measured by number of blocks.
313
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
314
pub const HOURS: BlockNumber = MINUTES * 60;
315
pub const DAYS: BlockNumber = HOURS * 24;
316

            
317
pub const SUPPLY_FACTOR: Balance = 100;
318

            
319
// Unit = the base number of indivisible units for balances
320
pub const UNIT: Balance = 1_000_000_000_000;
321
pub const MILLIUNIT: Balance = 1_000_000_000;
322
pub const MICROUNIT: Balance = 1_000_000;
323

            
324
pub const STORAGE_BYTE_FEE: Balance = 100 * MICROUNIT * SUPPLY_FACTOR;
325

            
326
pub const fn deposit(items: u32, bytes: u32) -> Balance {
327
    items as Balance * 100 * MILLIUNIT * SUPPLY_FACTOR + (bytes as Balance) * STORAGE_BYTE_FEE
328
}
329

            
330
/// The existential deposit. Set to 1/10 of the Connected Relay Chain.
331
pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT;
332

            
333
/// We assume that ~5% of the block weight is consumed by `on_initialize` handlers. This is
334
/// used to limit the maximal weight of a single extrinsic.
335
const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5);
336

            
337
/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used by
338
/// `Operational` extrinsics.
339
const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
340

            
341
/// We allow for 2 seconds of compute with a 6 second average block time
342
const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(
343
    WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2),
344
    cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64,
345
);
346

            
347
/// The version information used to identify this runtime when compiled natively.
348
#[cfg(feature = "std")]
349
pub fn native_version() -> NativeVersion {
350
    NativeVersion {
351
        runtime_version: VERSION,
352
        can_author_with: Default::default(),
353
    }
354
}
355

            
356
parameter_types! {
357
    pub const Version: RuntimeVersion = VERSION;
358

            
359
    // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`.
360
    //  The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the
361
    // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize
362
    // the lazy contract deletion.
363
    pub RuntimeBlockLength: BlockLength =
364
        BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
365
    pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
366
        .base_block(BlockExecutionWeight::get())
367
29637
        .for_class(DispatchClass::all(), |weights| {
368
29637
            weights.base_extrinsic = ExtrinsicBaseWeight::get();
369
29637
        })
370
9879
        .for_class(DispatchClass::Normal, |weights| {
371
9879
            weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
372
9879
        })
373
9879
        .for_class(DispatchClass::Operational, |weights| {
374
9879
            weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
375
            // Operational transactions have some extra reserved space, so that they
376
            // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
377
9879
            weights.reserved = Some(
378
9879
                MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
379
9879
            );
380
9879
        })
381
        .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
382
        .build_or_panic();
383
    pub const SS58Prefix: u16 = 42;
384
}
385

            
386
// Configure FRAME pallets to include in runtime.
387

            
388
impl frame_system::Config for Runtime {
389
    /// The identifier used to distinguish between accounts.
390
    type AccountId = AccountId;
391
    /// The aggregated dispatch type that is available for extrinsics.
392
    type RuntimeCall = RuntimeCall;
393
    /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
394
    type Lookup = AccountIdLookup<AccountId, ()>;
395
    /// The index type for storing how many extrinsics an account has signed.
396
    type Nonce = Index;
397
    /// The index type for blocks.
398
    type Block = Block;
399
    /// The type for hashing blocks and tries.
400
    type Hash = Hash;
401
    /// The hashing algorithm used.
402
    type Hashing = BlakeTwo256;
403
    /// The ubiquitous event type.
404
    type RuntimeEvent = RuntimeEvent;
405
    /// The ubiquitous origin type.
406
    type RuntimeOrigin = RuntimeOrigin;
407
    /// Maximum number of block number to block hash mappings to keep (oldest pruned first).
408
    type BlockHashCount = BlockHashCount;
409
    /// Runtime version.
410
    type Version = Version;
411
    /// Converts a module to an index of this module in the runtime.
412
    type PalletInfo = PalletInfo;
413
    /// The data to be stored in an account.
414
    type AccountData = pallet_balances::AccountData<Balance>;
415
    /// What to do if a new account is created.
416
    type OnNewAccount = ();
417
    /// What to do if an account is fully reaped from the system.
418
    type OnKilledAccount = ();
419
    /// The weight of database operations that the runtime can invoke.
420
    type DbWeight = RocksDbWeight;
421
    /// The basic call filter to use in dispatchable.
422
    type BaseCallFilter = InsideBoth<MaintenanceMode, TxPause>;
423
    /// Weight information for the extrinsics of this pallet.
424
    type SystemWeightInfo = weights::frame_system::SubstrateWeight<Runtime>;
425
    /// Block & extrinsics weights: base values and limits.
426
    type BlockWeights = RuntimeBlockWeights;
427
    /// The maximum length of a block (in bytes).
428
    type BlockLength = RuntimeBlockLength;
429
    /// This is used as an identifier of the chain. 42 is the generic substrate prefix.
430
    type SS58Prefix = SS58Prefix;
431
    /// The action to take on a Runtime Upgrade
432
    type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
433
    type MaxConsumers = frame_support::traits::ConstU32<16>;
434
    type RuntimeTask = RuntimeTask;
435
    type SingleBlockMigrations = ();
436
    type MultiBlockMigrator = MultiBlockMigrations;
437
    type PreInherents = ();
438
    type PostInherents = ();
439
    type PostTransactions = ();
440
    type ExtensionsWeightInfo = weights::frame_system_extensions::SubstrateWeight<Runtime>;
441
}
442

            
443
parameter_types! {
444
    pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT;
445
}
446

            
447
impl pallet_balances::Config for Runtime {
448
    type MaxLocks = ConstU32<50>;
449
    /// The type for recording an account's balance.
450
    type Balance = Balance;
451
    /// The ubiquitous event type.
452
    type RuntimeEvent = RuntimeEvent;
453
    type DustRemoval = ();
454
    type ExistentialDeposit = ExistentialDeposit;
455
    type AccountStore = System;
456
    type MaxReserves = ConstU32<50>;
457
    type ReserveIdentifier = [u8; 8];
458
    type FreezeIdentifier = RuntimeFreezeReason;
459
    type MaxFreezes = ConstU32<0>;
460
    type RuntimeHoldReason = RuntimeHoldReason;
461
    type RuntimeFreezeReason = RuntimeFreezeReason;
462
    type DoneSlashHandler = ();
463
    type WeightInfo = weights::pallet_balances::SubstrateWeight<Runtime>;
464
}
465

            
466
parameter_types! {
467
    pub const TransactionByteFee: Balance = 1;
468
}
469

            
470
impl pallet_transaction_payment::Config for Runtime {
471
    type RuntimeEvent = RuntimeEvent;
472
    // This will burn the fees
473
    type OnChargeTransaction = FungibleAdapter<Balances, ()>;
474
    type OperationalFeeMultiplier = ConstU8<5>;
475
    type WeightToFee = WeightToFee;
476
    type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
477
    type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
478
    type WeightInfo = weights::pallet_transaction_payment::SubstrateWeight<Runtime>;
479
}
480

            
481
/// Dynamic params that can be adjusted at runtime.
482
#[dynamic_params(RuntimeParameters, pallet_parameters::Parameters::<Runtime>)]
483
pub mod dynamic_params {
484
    use super::*;
485

            
486
    /// The Dancelight genesis hash used as the default relay network identifier.
487
    pub const DANCELIGHT_GENESIS_HASH: [u8; 32] =
488
        hex_literal::hex!["983a1a72503d6cc3636776747ec627172b51272bf45e50a355348facb67a820a"];
489

            
490
    /// The Starlight genesis hash.
491
    pub const TANSSI_GENESIS_HASH: [u8; 32] =
492
        hex_literal::hex!["dd6d086f75ec041b66e20c4186d327b23c8af244c534a2418de6574e8c041a60"];
493

            
494
    pub enum EthereumNetworkChainId {
495
        EthereumTestnet,
496
        EthereumMainnet,
497
    }
498

            
499
    pub const SEPOLIA_ETH_TESTNET_CHAIN_ID: u64 = 11155111;
500
    pub const ETH_MAINNET_CHAIN_ID: u64 = 1;
501

            
502
    impl EthereumNetworkChainId {
503
386
        pub fn as_u64(&self) -> u64 {
504
386
            match self {
505
169
                EthereumNetworkChainId::EthereumTestnet => SEPOLIA_ETH_TESTNET_CHAIN_ID,
506
217
                EthereumNetworkChainId::EthereumMainnet => ETH_MAINNET_CHAIN_ID,
507
            }
508
386
        }
509

            
510
        /// Derive chain_id from relay network
511
386
        pub fn from_relay_network(network: &NetworkId) -> Option<Self> {
512
217
            match network {
513
386
                NetworkId::ByGenesis(hash) if hash == &DANCELIGHT_GENESIS_HASH => {
514
169
                    Some(Self::EthereumTestnet)
515
                }
516
217
                NetworkId::ByGenesis(hash) if hash == &TANSSI_GENESIS_HASH => {
517
217
                    Some(Self::EthereumMainnet)
518
                }
519
                _ => None,
520
            }
521
386
        }
522
    }
523

            
524
    #[dynamic_pallet_params]
525
    #[codec(index = 0)]
526
    pub mod xcm_config {
527
        use super::*;
528

            
529
        /// The relay network identifier for this container chain.
530
        /// Using Dancelight genesis hash as default.
531
        #[codec(index = 0)]
532
        pub static RelayNetwork: xcm::latest::NetworkId =
533
            xcm::latest::NetworkId::ByGenesis(DANCELIGHT_GENESIS_HASH);
534
    }
535
}
536

            
537
#[cfg(feature = "runtime-benchmarks")]
538
impl Default for RuntimeParameters {
539
    fn default() -> Self {
540
        RuntimeParameters::XcmConfig(dynamic_params::xcm_config::Parameters::RelayNetwork(
541
            dynamic_params::xcm_config::RelayNetwork,
542
            Some(xcm::latest::NetworkId::ByGenesis(
543
                dynamic_params::DANCELIGHT_GENESIS_HASH,
544
            )),
545
        ))
546
    }
547
}
548

            
549
impl pallet_parameters::Config for Runtime {
550
    type AdminOrigin = EnsureRoot<AccountId>;
551
    type RuntimeEvent = RuntimeEvent;
552
    type RuntimeParameters = RuntimeParameters;
553
    type WeightInfo = weights::pallet_parameters::SubstrateWeight<Runtime>;
554
}
555

            
556
parameter_types! {
557
    pub ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
558
    pub ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
559
    pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent;
560
}
561

            
562
pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000;
563
pub const UNINCLUDED_SEGMENT_CAPACITY: u32 = 3;
564
pub const BLOCK_PROCESSING_VELOCITY: u32 = 1;
565

            
566
type ConsensusHook = pallet_async_backing::consensus_hook::FixedVelocityConsensusHook<
567
    Runtime,
568
    BLOCK_PROCESSING_VELOCITY,
569
    UNINCLUDED_SEGMENT_CAPACITY,
570
>;
571

            
572
impl cumulus_pallet_parachain_system::Config for Runtime {
573
    type WeightInfo = weights::cumulus_pallet_parachain_system::SubstrateWeight<Runtime>;
574
    type RuntimeEvent = RuntimeEvent;
575
    type OnSystemEvent = ();
576
    type OutboundXcmpMessageSource = XcmpQueue;
577
    type SelfParaId = parachain_info::Pallet<Runtime>;
578
    type DmpQueue = frame_support::traits::EnqueueWithOrigin<MessageQueue, RelayOrigin>;
579
    type ReservedDmpWeight = ReservedDmpWeight;
580
    type XcmpMessageHandler = XcmpQueue;
581
    type ReservedXcmpWeight = ReservedXcmpWeight;
582
    type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases;
583
    type ConsensusHook = ConsensusHook;
584
    type SelectCore = cumulus_pallet_parachain_system::DefaultCoreSelector<Runtime>;
585
    type RelayParentOffset = ConstU32<0>;
586
}
587

            
588
pub struct ParaSlotProvider;
589
impl sp_core::Get<(Slot, SlotDuration)> for ParaSlotProvider {
590
1208
    fn get() -> (Slot, SlotDuration) {
591
1208
        let slot = u64::from(<Runtime as pallet_author_inherent::Config>::SlotBeacon::slot());
592
1208
        (Slot::from(slot), SlotDuration::from_millis(SLOT_DURATION))
593
1208
    }
594
}
595

            
596
parameter_types! {
597
    pub const ExpectedBlockTime: u64 = MILLISECS_PER_BLOCK;
598
}
599

            
600
impl pallet_async_backing::Config for Runtime {
601
    type AllowMultipleBlocksPerSlot = ConstBool<true>;
602
    type GetAndVerifySlot =
603
        pallet_async_backing::ParaSlot<RELAY_CHAIN_SLOT_DURATION_MILLIS, ParaSlotProvider>;
604
    type ExpectedBlockTime = ExpectedBlockTime;
605
}
606

            
607
impl parachain_info::Config for Runtime {}
608

            
609
parameter_types! {
610
    pub const Period: u32 = 6 * HOURS;
611
    pub const Offset: u32 = 0;
612
}
613

            
614
impl pallet_sudo::Config for Runtime {
615
    type RuntimeCall = RuntimeCall;
616
    type RuntimeEvent = RuntimeEvent;
617
    type WeightInfo = weights::pallet_sudo::SubstrateWeight<Runtime>;
618
}
619

            
620
impl pallet_utility::Config for Runtime {
621
    type RuntimeEvent = RuntimeEvent;
622
    type RuntimeCall = RuntimeCall;
623
    type PalletsOrigin = OriginCaller;
624
    type WeightInfo = weights::pallet_utility::SubstrateWeight<Runtime>;
625
}
626

            
627
/// The type used to represent the kinds of proxying allowed.
628
#[derive(
629
    Copy,
630
    Clone,
631
    Eq,
632
    PartialEq,
633
    Ord,
634
    PartialOrd,
635
    Encode,
636
    Decode,
637
    Debug,
638
    MaxEncodedLen,
639
    DecodeWithMemTracking,
640
    TypeInfo,
641
    Serialize,
642
    Deserialize,
643
)]
644
#[allow(clippy::unnecessary_cast)]
645
pub enum ProxyType {
646
    /// All calls can be proxied. This is the trivial/most permissive filter.
647
    Any = 0,
648
    /// Only extrinsics that do not transfer funds.
649
    NonTransfer = 1,
650
    /// Only extrinsics related to governance (democracy and collectives).
651
    Governance = 2,
652
    /// Allow to veto an announced proxy call.
653
    CancelProxy = 3,
654
    /// Allow extrinsic related to Balances.
655
    Balances = 4,
656
}
657

            
658
impl Default for ProxyType {
659
    fn default() -> Self {
660
        Self::Any
661
    }
662
}
663

            
664
impl InstanceFilter<RuntimeCall> for ProxyType {
665
    fn filter(&self, c: &RuntimeCall) -> bool {
666
        // Since proxy filters are respected in all dispatches of the Utility
667
        // pallet, it should never need to be filtered by any proxy.
668
        if let RuntimeCall::Utility(..) = c {
669
            return true;
670
        }
671

            
672
        match self {
673
            ProxyType::Any => true,
674
            ProxyType::NonTransfer => {
675
                matches!(
676
                    c,
677
                    RuntimeCall::System(..)
678
                        | RuntimeCall::ParachainSystem(..)
679
                        | RuntimeCall::Timestamp(..)
680
                        | RuntimeCall::Proxy(..)
681
                )
682
            }
683
            // We don't have governance yet
684
            ProxyType::Governance => false,
685
            ProxyType::CancelProxy => matches!(
686
                c,
687
                RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. })
688
            ),
689
            ProxyType::Balances => {
690
                matches!(c, RuntimeCall::Balances(..))
691
            }
692
        }
693
    }
694

            
695
    fn is_superset(&self, o: &Self) -> bool {
696
        match (self, o) {
697
            (x, y) if x == y => true,
698
            (ProxyType::Any, _) => true,
699
            (_, ProxyType::Any) => false,
700
            _ => false,
701
        }
702
    }
703
}
704

            
705
impl pallet_proxy::Config for Runtime {
706
    type RuntimeEvent = RuntimeEvent;
707
    type RuntimeCall = RuntimeCall;
708
    type Currency = Balances;
709
    type ProxyType = ProxyType;
710
    // One storage item; key size 32, value size 8
711
    type ProxyDepositBase = ConstU128<{ deposit(1, 8) }>;
712
    // Additional storage item size of 33 bytes (32 bytes AccountId + 1 byte sizeof(ProxyType)).
713
    type ProxyDepositFactor = ConstU128<{ deposit(0, 33) }>;
714
    type MaxProxies = ConstU32<32>;
715
    type MaxPending = ConstU32<32>;
716
    type CallHasher = BlakeTwo256;
717
    type AnnouncementDepositBase = ConstU128<{ deposit(1, 8) }>;
718
    // Additional storage item size of 68 bytes:
719
    // - 32 bytes AccountId
720
    // - 32 bytes Hasher (Blake2256)
721
    // - 4 bytes BlockNumber (u32)
722
    type AnnouncementDepositFactor = ConstU128<{ deposit(0, 68) }>;
723
    type WeightInfo = weights::pallet_proxy::SubstrateWeight<Runtime>;
724
    type BlockNumberProvider = System;
725
}
726

            
727
pub struct XcmExecutionManager;
728
impl xcm_primitives::PauseXcmExecution for XcmExecutionManager {
729
    fn suspend_xcm_execution() -> DispatchResult {
730
        XcmpQueue::suspend_xcm_execution(RuntimeOrigin::root())
731
    }
732
    fn resume_xcm_execution() -> DispatchResult {
733
        XcmpQueue::resume_xcm_execution(RuntimeOrigin::root())
734
    }
735
}
736

            
737
impl pallet_migrations::Config for Runtime {
738
    type MigrationsList = (migrations::TemplateMigrations<Runtime, XcmpQueue, PolkadotXcm>,);
739
    type XcmExecutionManager = XcmExecutionManager;
740
}
741

            
742
parameter_types! {
743
    pub MbmServiceWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block;
744
}
745

            
746
impl pallet_multiblock_migrations::Config for Runtime {
747
    type RuntimeEvent = RuntimeEvent;
748
    #[cfg(not(feature = "runtime-benchmarks"))]
749
    type Migrations = ();
750
    // Benchmarks need mocked migrations to guarantee that they succeed.
751
    #[cfg(feature = "runtime-benchmarks")]
752
    type Migrations = pallet_multiblock_migrations::mock_helpers::MockedMigrations;
753
    type CursorMaxLen = ConstU32<65_536>;
754
    type IdentifierMaxLen = ConstU32<256>;
755
    type MigrationStatusHandler = ();
756
    type FailedMigrationHandler = MaintenanceMode;
757
    type MaxServiceWeight = MbmServiceWeight;
758
    type WeightInfo = weights::pallet_multiblock_migrations::SubstrateWeight<Runtime>;
759
}
760

            
761
/// Maintenance mode Call filter
762
pub struct MaintenanceFilter;
763
impl Contains<RuntimeCall> for MaintenanceFilter {
764
    fn contains(c: &RuntimeCall) -> bool {
765
        !matches!(c, RuntimeCall::Balances(_) | RuntimeCall::PolkadotXcm(_))
766
    }
767
}
768

            
769
/// Normal Call Filter
770
/// We dont allow to create nor mint assets, this for now is disabled
771
/// We only allow transfers. For now creation of assets will go through
772
/// asset-manager, while minting/burning only happens through xcm messages
773
/// This can change in the future
774
pub struct NormalFilter;
775
impl Contains<RuntimeCall> for NormalFilter {
776
2416
    fn contains(_c: &RuntimeCall) -> bool {
777
2416
        true
778
2416
    }
779
}
780

            
781
impl pallet_maintenance_mode::Config for Runtime {
782
    type NormalCallFilter = NormalFilter;
783
    type MaintenanceCallFilter = InsideBoth<MaintenanceFilter, NormalFilter>;
784
    type MaintenanceOrigin = EnsureRoot<AccountId>;
785
    type XcmExecutionManager = XcmExecutionManager;
786
}
787

            
788
impl pallet_root_testing::Config for Runtime {
789
    type RuntimeEvent = RuntimeEvent;
790
}
791

            
792
impl pallet_tx_pause::Config for Runtime {
793
    type RuntimeEvent = RuntimeEvent;
794
    type RuntimeCall = RuntimeCall;
795
    type PauseOrigin = EnsureRoot<AccountId>;
796
    type UnpauseOrigin = EnsureRoot<AccountId>;
797
    type WhitelistedCalls = ();
798
    type MaxNameLen = ConstU32<256>;
799
    type WeightInfo = weights::pallet_tx_pause::SubstrateWeight<Runtime>;
800
}
801

            
802
impl dp_impl_tanssi_pallets_config::Config for Runtime {
803
    const SLOT_DURATION: u64 = SLOT_DURATION;
804
    type TimestampWeights = weights::pallet_timestamp::SubstrateWeight<Runtime>;
805
    type AuthorInherentWeights = weights::pallet_author_inherent::SubstrateWeight<Runtime>;
806
    type AuthoritiesNotingWeights = weights::pallet_cc_authorities_noting::SubstrateWeight<Runtime>;
807
}
808

            
809
parameter_types! {
810
    // One storage item; key size 32; value is size 4+4+16+32. Total = 1 * (32 + 56)
811
    pub const DepositBase: Balance = currency::deposit(1, 88);
812
    // Additional storage item size of 32 bytes.
813
    pub const DepositFactor: Balance = currency::deposit(0, 32);
814
    pub const MaxSignatories: u32 = 100;
815
}
816

            
817
impl pallet_multisig::Config for Runtime {
818
    type RuntimeEvent = RuntimeEvent;
819
    type RuntimeCall = RuntimeCall;
820
    type Currency = Balances;
821
    type DepositBase = DepositBase;
822
    type DepositFactor = DepositFactor;
823
    type MaxSignatories = MaxSignatories;
824
    type WeightInfo = weights::pallet_multisig::SubstrateWeight<Runtime>;
825
    type BlockNumberProvider = System;
826
}
827

            
828
impl frame_system::offchain::SigningTypes for Runtime {
829
    type Public = <Signature as sp_runtime::traits::Verify>::Signer;
830
    type Signature = Signature;
831
}
832

            
833
/// Submits a transaction with the node's public and signature type. Adheres to the signed extension
834
/// format of the chain.
835
impl<LocalCall> frame_system::offchain::CreateSignedTransaction<LocalCall> for Runtime
836
where
837
    RuntimeCall: From<LocalCall>,
838
{
839
    fn create_signed_transaction<
840
        C: frame_system::offchain::AppCrypto<Self::Public, Self::Signature>,
841
    >(
842
        call: RuntimeCall,
843
        public: <Signature as Verify>::Signer,
844
        account: AccountId,
845
        nonce: <Runtime as frame_system::Config>::Nonce,
846
    ) -> Option<UncheckedExtrinsic> {
847
        use sp_runtime::traits::StaticLookup;
848
        // take the biggest period possible.
849
        let period = u64::from(
850
            BlockHashCount::get()
851
                .checked_next_power_of_two()
852
                .map(|c| c / 2)
853
                .unwrap_or(2),
854
        );
855

            
856
        let current_block = System::block_number()
857
            .saturated_into::<u64>()
858
            // The `System::block_number` is initialized with `n+1`,
859
            // so the actual block number is `n`.
860
            .saturating_sub(1);
861
        let tip = 0;
862
        let tx_ext = TxExtension::new((
863
            frame_system::CheckNonZeroSender::<Runtime>::new(),
864
            frame_system::CheckSpecVersion::<Runtime>::new(),
865
            frame_system::CheckTxVersion::<Runtime>::new(),
866
            frame_system::CheckGenesis::<Runtime>::new(),
867
            frame_system::CheckMortality::<Runtime>::from(generic::Era::mortal(
868
                period,
869
                current_block,
870
            )),
871
            frame_system::CheckNonce::<Runtime>::from(nonce),
872
            frame_system::CheckWeight::<Runtime>::new(),
873
            pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
874
            //frame_metadata_hash_extension::CheckMetadataHash::new(true),
875
        ));
876
        let raw_payload = SignedPayload::new(call, tx_ext)
877
            .map_err(|e| {
878
                log::warn!("Unable to create signed payload: {:?}", e);
879
            })
880
            .ok()?;
881
        let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?;
882
        let (call, tx_ext, _) = raw_payload.deconstruct();
883
        let address = <Runtime as frame_system::Config>::Lookup::unlookup(account);
884
        let transaction = UncheckedExtrinsic::new_signed(call, address, signature, tx_ext);
885
        Some(transaction)
886
    }
887
}
888

            
889
impl<C> frame_system::offchain::CreateTransactionBase<C> for Runtime
890
where
891
    RuntimeCall: From<C>,
892
{
893
    type Extrinsic = UncheckedExtrinsic;
894
    type RuntimeCall = RuntimeCall;
895
}
896

            
897
impl<LocalCall> frame_system::offchain::CreateBare<LocalCall> for Runtime
898
where
899
    RuntimeCall: From<LocalCall>,
900
{
901
    fn create_bare(call: RuntimeCall) -> UncheckedExtrinsic {
902
        UncheckedExtrinsic::new_bare(call)
903
    }
904
}
905

            
906
impl pallet_ocw_testing::Config for Runtime {
907
    type UnsignedInterval = ConstU32<6>;
908
}
909

            
910
impl cumulus_pallet_weight_reclaim::Config for Runtime {
911
    type WeightInfo = weights::cumulus_pallet_weight_reclaim::SubstrateWeight<Runtime>;
912
}
913

            
914
impl_tanssi_pallets_config!(Runtime);
915

            
916
// Create the runtime by composing the FRAME pallets that were previously configured.
917
construct_runtime!(
918
    pub enum Runtime
919
    {
920
        // System support stuff.
921
        System: frame_system = 0,
922
        ParachainSystem: cumulus_pallet_parachain_system = 1,
923
        Timestamp: pallet_timestamp = 2,
924
        ParachainInfo: parachain_info = 3,
925
        Sudo: pallet_sudo = 4,
926
        Utility: pallet_utility = 5,
927
        Proxy: pallet_proxy = 6,
928
        Migrations: pallet_migrations = 7,
929
        MultiBlockMigrations: pallet_multiblock_migrations = 121,
930
        MaintenanceMode: pallet_maintenance_mode = 8,
931
        TxPause: pallet_tx_pause = 9,
932

            
933
        // Monetary stuff.
934
        Balances: pallet_balances = 10,
935
        TransactionPayment: pallet_transaction_payment = 11,
936

            
937
        // Other utilities
938
        Multisig: pallet_multisig = 16,
939
        Parameters: pallet_parameters = 17,
940

            
941
        // ContainerChain Author Verification
942
        AuthoritiesNoting: pallet_cc_authorities_noting = 50,
943
        AuthorInherent: pallet_author_inherent = 51,
944

            
945
        // XCM
946
        XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Storage, Event<T>} = 70,
947
        CumulusXcm: cumulus_pallet_xcm::{Pallet, Event<T>, Origin} = 71,
948
        PolkadotXcm: pallet_xcm::{Pallet, Call, Storage, Event<T>, Origin, Config<T>} = 73,
949
        MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event<T>} = 74,
950
        ForeignAssets: pallet_assets::<Instance1>::{Pallet, Call, Storage, Event<T>} = 75,
951
        ForeignAssetsCreator: pallet_foreign_asset_creator::{Pallet, Call, Storage, Event<T>} = 76,
952
        AssetRate: pallet_asset_rate::{Pallet, Call, Storage, Event<T>} = 77,
953
        XcmExecutorUtils: pallet_xcm_executor_utils::{Pallet, Call, Storage, Event<T>} = 78,
954

            
955
        WeightReclaim: cumulus_pallet_weight_reclaim = 80,
956

            
957
        RootTesting: pallet_root_testing = 100,
958
        AsyncBacking: pallet_async_backing::{Pallet, Storage} = 110,
959

            
960
        OffchainWorker: pallet_ocw_testing::{Pallet, Call, Storage, Event<T>, ValidateUnsigned} = 120,
961
    }
962
);
963

            
964
#[cfg(feature = "runtime-benchmarks")]
965
mod benches {
966
    frame_benchmarking::define_benchmarks!(
967
        [frame_system, frame_system_benchmarking::Pallet::<Runtime>]
968
        [frame_system_extensions, frame_system_benchmarking::extensions::Pallet::<Runtime>]
969
        [cumulus_pallet_parachain_system, ParachainSystem]
970
        [pallet_timestamp, Timestamp]
971
        [pallet_sudo, Sudo]
972
        [pallet_utility, Utility]
973
        [pallet_proxy, Proxy]
974
        [pallet_tx_pause, TxPause]
975
        [pallet_transaction_payment, TransactionPayment]
976
        [pallet_balances, Balances]
977
        [pallet_multiblock_migrations, MultiBlockMigrations]
978
        [pallet_multisig, Multisig]
979
        [pallet_cc_authorities_noting, AuthoritiesNoting]
980
        [pallet_author_inherent, AuthorInherent]
981
        [cumulus_pallet_xcmp_queue, XcmpQueue]
982
        [pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>]
983
        [pallet_xcm_benchmarks::generic, pallet_xcm_benchmarks::generic::Pallet::<Runtime>]
984
        [pallet_message_queue, MessageQueue]
985
        [pallet_assets, ForeignAssets]
986
        [pallet_foreign_asset_creator, ForeignAssetsCreator]
987
        [pallet_asset_rate, AssetRate]
988
        [pallet_xcm_executor_utils, XcmExecutorUtils]
989
        [cumulus_pallet_weight_reclaim, WeightReclaim]
990
    );
991
}
992

            
993
impl_runtime_apis! {
994
    impl sp_api::Core<Block> for Runtime {
995
        fn version() -> RuntimeVersion {
996
            VERSION
997
        }
998

            
999
        fn execute_block(block: Block) {
            Executive::execute_block(block)
        }
        fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
            Executive::initialize_block(header)
        }
    }
    impl sp_api::Metadata<Block> for Runtime {
        fn metadata() -> OpaqueMetadata {
            OpaqueMetadata::new(Runtime::metadata().into())
        }
        fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
            Runtime::metadata_at_version(version)
        }
        fn metadata_versions() -> Vec<u32> {
            Runtime::metadata_versions()
        }
    }
    impl sp_block_builder::BlockBuilder<Block> for Runtime {
        fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
            Executive::apply_extrinsic(extrinsic)
        }
        fn finalize_block() -> <Block as BlockT>::Header {
            Executive::finalize_block()
        }
        fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
            data.create_extrinsics()
        }
        fn check_inherents(
            block: Block,
            data: sp_inherents::InherentData,
        ) -> sp_inherents::CheckInherentsResult {
            data.check_extrinsics(&block)
        }
    }
    impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
        fn validate_transaction(
            source: TransactionSource,
            tx: <Block as BlockT>::Extrinsic,
            block_hash: <Block as BlockT>::Hash,
        ) -> TransactionValidity {
            Executive::validate_transaction(source, tx, block_hash)
        }
    }
    impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
        fn offchain_worker(header: &<Block as BlockT>::Header) {
            Executive::offchain_worker(header)
        }
    }
    impl sp_session::SessionKeys<Block> for Runtime {
        fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
            SessionKeys::generate(seed)
        }
        fn decode_session_keys(
            encoded: Vec<u8>,
        ) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
            SessionKeys::decode_into_raw_public_keys(&encoded)
        }
    }
    impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
        fn account_nonce(account: AccountId) -> Index {
            System::account_nonce(account)
        }
    }
    impl cumulus_primitives_core::CollectCollationInfo<Block> for Runtime {
        fn collect_collation_info(header: &<Block as BlockT>::Header) -> cumulus_primitives_core::CollationInfo {
            ParachainSystem::collect_collation_info(header)
        }
    }
    impl async_backing_primitives::UnincludedSegmentApi<Block> for Runtime {
        fn can_build_upon(
            included_hash: <Block as BlockT>::Hash,
            slot: async_backing_primitives::Slot,
        ) -> bool {
            ConsensusHook::can_build_upon(included_hash, slot)
        }
    }
    impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
        fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
            build_state::<RuntimeGenesisConfig>(config)
        }
       fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
            get_preset::<RuntimeGenesisConfig>(id, |id: &sp_genesis_builder::PresetId| {
                let mut default_funded_accounts = genesis_config_presets::pre_funded_accounts();
                default_funded_accounts.sort();
                default_funded_accounts.dedup();
                let para_id: ParaId = 2000.into();
                let patch = match id.as_ref() {
                    "development" => genesis_config_presets::development(
                        default_funded_accounts.clone(),
                        para_id,
                        Sr25519Keyring::Alice.to_account_id(),
                    ),
                    _ => return None,
                };
                Some(
                    serde_json::to_string(&patch)
                        .expect("serialization to json is expected to work. qed.")
                        .into_bytes(),
                )
            })
        }
        fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
            vec!["development".into()]
        }
    }
    #[cfg(feature = "runtime-benchmarks")]
    impl frame_benchmarking::Benchmark<Block> for Runtime {
        fn benchmark_metadata(
            extra: bool,
        ) -> (
            Vec<frame_benchmarking::BenchmarkList>,
            Vec<frame_support::traits::StorageInfo>,
        ) {
            use frame_benchmarking::{BenchmarkList};
            use frame_support::traits::StorageInfoTrait;
            use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
            let mut list = Vec::<BenchmarkList>::new();
            list_benchmarks!(list, extra);
            let storage_info = AllPalletsWithSystem::storage_info();
            (list, storage_info)
        }
        #[allow(non_local_definitions)]
        fn dispatch_benchmark(
            config: frame_benchmarking::BenchmarkConfig,
        ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> {
            use frame_benchmarking::{BenchmarkBatch, BenchmarkError};
            use sp_core::storage::TrackedStorageKey;
            use xcm::latest::prelude::*;
            use alloc::boxed::Box;
            impl frame_system_benchmarking::Config for Runtime {
                fn setup_set_code_requirements(code: &alloc::vec::Vec<u8>) -> Result<(), BenchmarkError> {
                    ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32);
                    Ok(())
                }
                fn verify_set_code() {
                    System::assert_last_event(cumulus_pallet_parachain_system::Event::<Runtime>::ValidationFunctionStored.into());
                }
            }
            use crate::xcm_config::SelfReserve;
            parameter_types! {
                pub ExistentialDepositAsset: Option<Asset> = Some((
                    SelfReserve::get(),
                    ExistentialDeposit::get()
                ).into());
            }
            impl pallet_xcm_benchmarks::Config for Runtime {
                type XcmConfig = xcm_config::XcmConfig;
                type AccountIdConverter = xcm_config::LocationToAccountId;
                type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
                xcm_config::XcmConfig,
                ExistentialDepositAsset,
                xcm_config::PriceForParentDelivery,
                >;
                fn valid_destination() -> Result<Location, BenchmarkError> {
                    Ok(Location::parent())
                }
                fn worst_case_holding(_depositable_count: u32) -> Assets {
                    // We only care for native asset until we support others
                    // TODO: refactor this case once other assets are supported
                    vec![Asset{
                        id: AssetId(SelfReserve::get()),
                        fun: Fungible(u128::MAX),
                    }].into()
                }
            }
            impl pallet_xcm_benchmarks::generic::Config for Runtime {
                type TransactAsset = Balances;
                type RuntimeCall = RuntimeCall;
                fn worst_case_response() -> (u64, Response) {
                    (0u64, Response::Version(Default::default()))
                }
                fn worst_case_asset_exchange() -> Result<(Assets, Assets), BenchmarkError> {
                    Err(BenchmarkError::Skip)
                }
                fn universal_alias() -> Result<(Location, Junction), BenchmarkError> {
                    tanssi_runtime_common::universal_aliases::AliasingBenchmarksHelper::prepare_universal_alias()
                    .ok_or(BenchmarkError::Skip)
                }
                fn transact_origin_and_runtime_call() -> Result<(Location, RuntimeCall), BenchmarkError> {
                    Ok((Location::parent(), frame_system::Call::remark_with_event { remark: vec![] }.into()))
                }
                fn subscribe_origin() -> Result<Location, BenchmarkError> {
                    Ok(Location::parent())
                }
                fn worst_case_for_trader() -> Result<(Asset, WeightLimit), BenchmarkError> {
                    Ok((Asset {
                        id: AssetId(SelfReserve::get()),
                        fun: Fungible(ExistentialDeposit::get()*100),
                    }, WeightLimit::Unlimited))
                }
                fn claimable_asset() -> Result<(Location, Location, Assets), BenchmarkError> {
                    let origin = Location::parent();
                    let assets: Assets = (Location::parent(), 1_000u128).into();
                    let ticket = Location { parents: 0, interior: Here };
                    Ok((origin, ticket, assets))
                }
                fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> {
                    Err(BenchmarkError::Skip)
                }
                fn export_message_origin_and_destination(
                ) -> Result<(Location, NetworkId, InteriorLocation), BenchmarkError> {
                    Err(BenchmarkError::Skip)
                }
                fn alias_origin() -> Result<(Location, Location), BenchmarkError> {
                    Err(BenchmarkError::Skip)
                }
            }
            use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark;
            impl pallet_xcm::benchmarking::Config for Runtime {
                type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper<
                xcm_config::XcmConfig,
                ExistentialDepositAsset,
                xcm_config::PriceForParentDelivery,
                >;
                fn get_asset() -> Asset {
                    Asset {
                        id: AssetId(SelfReserve::get()),
                        fun: Fungible(ExistentialDeposit::get()),
                    }
                }
                fn reachable_dest() -> Option<Location> {
                    Some(Parent.into())
                }
                fn teleportable_asset_and_dest() -> Option<(Asset, Location)> {
                    // Relay/native token can be teleported between AH and Relay.
                    Some((
                        Asset {
                            fun: Fungible(EXISTENTIAL_DEPOSIT),
                            id: Parent.into()
                        },
                        Parent.into(),
                    ))
                }
                fn reserve_transferable_asset_and_dest() -> Option<(Asset, Location)> {
                    use xcm_config::SelfReserve;
                    // AH can reserve transfer native token to some random parachain.
                    let random_para_id = 43211234;
                    ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(
                        random_para_id.into()
                    );
                    let who = frame_benchmarking::whitelisted_caller();
                    // Give some multiple of the existential deposit
                    let balance = EXISTENTIAL_DEPOSIT * 1000;
                    let _ = <Balances as frame_support::traits::Currency<_>>::make_free_balance_be(
                        &who, balance,
                    );
                    Some((
                        Asset {
                            fun: Fungible(EXISTENTIAL_DEPOSIT*10),
                            id: SelfReserve::get().into()
                        },
                        ParentThen(Parachain(random_para_id).into()).into(),
                    ))
                }
                fn set_up_complex_asset_transfer(
                ) -> Option<(Assets, u32, Location, Box<dyn FnOnce()>)> {
                    use xcm_config::SelfReserve;
                    // Transfer to Relay some local AH asset (local-reserve-transfer) while paying
                    // fees using teleported native token.
                    // (We don't care that Relay doesn't accept incoming unknown AH local asset)
                    let dest = Parent.into();
                    let fee_amount = EXISTENTIAL_DEPOSIT;
                    let fee_asset: Asset = (SelfReserve::get(), fee_amount).into();
                    let who = frame_benchmarking::whitelisted_caller();
                    // Give some multiple of the existential deposit
                    let balance = fee_amount + EXISTENTIAL_DEPOSIT * 1000;
                    let _ = <Balances as frame_support::traits::Currency<_>>::make_free_balance_be(
                        &who, balance,
                    );
                    // verify initial balance
                    assert_eq!(Balances::free_balance(&who), balance);
                    // set up local asset
                    let asset_amount = 10u128;
                    let initial_asset_amount = asset_amount * 10;
                    let (asset_id, asset_location) = pallet_foreign_asset_creator::benchmarks::create_minted_asset::<Runtime>(
                        initial_asset_amount,
                        who.clone(),
                        None,
                    );
                    let transfer_asset: Asset = (asset_location, asset_amount).into();
                    let assets: Assets = vec![fee_asset.clone(), transfer_asset].into();
                    let fee_index = if assets.get(0).unwrap().eq(&fee_asset) { 0 } else { 1 };
                    // verify transferred successfully
                    let verify = Box::new(move || {
                        // verify native balance after transfer, decreased by transferred fee amount
                        // (plus transport fees)
                        assert!(Balances::free_balance(&who) <= balance - fee_amount);
                        // verify asset balance decreased by exactly transferred amount
                        assert_eq!(
                            ForeignAssets::balance(asset_id, &who),
                            initial_asset_amount - asset_amount,
                        );
                    });
                    Some((assets, fee_index, dest, verify))
                }
            }
            let whitelist: Vec<TrackedStorageKey> = vec![
                // Block Number
                hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac")
                    .to_vec()
                    .into(),
                // Total Issuance
                hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80")
                    .to_vec()
                    .into(),
                // Execution Phase
                hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a")
                    .to_vec()
                    .into(),
                // Event Count
                hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850")
                    .to_vec()
                    .into(),
                // System Events
                hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7")
                    .to_vec()
                    .into(),
                // The transactional storage limit.
                hex_literal::hex!("3a7472616e73616374696f6e5f6c6576656c3a")
                    .to_vec()
                    .into(),
                // ParachainInfo ParachainId
                hex_literal::hex!(  "0d715f2646c8f85767b5d2764bb2782604a74d81251e398fd8a0a4d55023bb3f")
                    .to_vec()
                    .into(),
            ];
            let mut batches = Vec::<BenchmarkBatch>::new();
            let params = (&config, &whitelist);
            add_benchmarks!(params, batches);
            Ok(batches)
        }
    }
    #[cfg(feature = "try-runtime")]
    impl frame_try_runtime::TryRuntime<Block> for Runtime {
        fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
            let weight = Executive::try_runtime_upgrade(checks).unwrap();
            (weight, RuntimeBlockWeights::get().max_block)
        }
        fn execute_block(
            block: Block,
            state_root_check: bool,
            signature_check: bool,
            select: frame_try_runtime::TryStateSelect,
        ) -> Weight {
            // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
            // have a backtrace here.
            Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap()
        }
    }
    impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
    for Runtime {
        fn query_info(
            uxt: <Block as BlockT>::Extrinsic,
            len: u32,
        ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
            TransactionPayment::query_info(uxt, len)
        }
        fn query_fee_details(
            uxt: <Block as BlockT>::Extrinsic,
            len: u32,
        ) -> pallet_transaction_payment::FeeDetails<Balance> {
            TransactionPayment::query_fee_details(uxt, len)
        }
        fn query_weight_to_fee(weight: Weight) -> Balance {
            TransactionPayment::weight_to_fee(weight)
        }
        fn query_length_to_fee(length: u32) -> Balance {
            TransactionPayment::length_to_fee(length)
        }
    }
    impl dp_slot_duration_runtime_api::TanssiSlotDurationApi<Block> for Runtime {
        fn slot_duration() -> u64 {
            SLOT_DURATION
        }
    }
    impl xcm_runtime_apis::fees::XcmPaymentApi<Block> for Runtime {
        fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result<Vec<VersionedAssetId>, XcmPaymentApiError> {
            if !matches!(xcm_version, 3..=5) {
                return Err(XcmPaymentApiError::UnhandledXcmVersion);
            }
            Ok([VersionedAssetId::V5(xcm_config::SelfReserve::get().into())]
                .into_iter()
                .chain(
                    pallet_asset_rate::ConversionRateToNative::<Runtime>::iter_keys().filter_map(|asset_id_u16| {
                        pallet_foreign_asset_creator::AssetIdToForeignAsset::<Runtime>::get(asset_id_u16).map(|location| {
                            VersionedAssetId::V5(location.into())
                        }).or_else(|| {
                            log::warn!("Asset `{}` is present in pallet_asset_rate but not in pallet_foreign_asset_creator", asset_id_u16);
                            None
                        })
                    })
                )
                .filter_map(|asset| asset.into_version(xcm_version).map_err(|e| {
                    log::warn!("Failed to convert asset to version {}: {:?}", xcm_version, e);
                }).ok())
                .collect())
        }
        fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result<u128, XcmPaymentApiError> {
            let local_asset = VersionedAssetId::V5(xcm_config::SelfReserve::get().into());
            let asset = asset
                .into_version(5)
                .map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
            if asset == local_asset {
                Ok(WeightToFee::weight_to_fee(&weight))
            } else {
                let native_fee = WeightToFee::weight_to_fee(&weight);
                let asset_v5: xcm::latest::AssetId = asset.try_into().map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?;
                let location: xcm::latest::Location = asset_v5.0;
                let asset_id = pallet_foreign_asset_creator::ForeignAssetToAssetId::<Runtime>::get(location).ok_or(XcmPaymentApiError::AssetNotFound)?;
                let asset_rate = AssetRate::to_asset_balance(native_fee, asset_id);
                match asset_rate {
                    Ok(x) => Ok(x),
                    Err(pallet_asset_rate::Error::UnknownAssetKind) => Err(XcmPaymentApiError::AssetNotFound),
                    // Error when converting native balance to asset balance, probably overflow
                    Err(_e) => Err(XcmPaymentApiError::WeightNotComputable),
                }
            }
        }
        fn query_xcm_weight(message: VersionedXcm<()>) -> Result<Weight, XcmPaymentApiError> {
            PolkadotXcm::query_xcm_weight(message)
        }
        fn query_delivery_fees(destination: VersionedLocation, message: VersionedXcm<()>) -> Result<VersionedAssets, XcmPaymentApiError> {
            PolkadotXcm::query_delivery_fees(destination, message)
        }
    }
    impl xcm_runtime_apis::dry_run::DryRunApi<Block, RuntimeCall, RuntimeEvent, OriginCaller> for Runtime {
        fn dry_run_call(origin: OriginCaller, call: RuntimeCall, result_xcms_version: XcmVersion) -> Result<CallDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
            PolkadotXcm::dry_run_call::<Runtime, xcm_config::XcmRouter, OriginCaller, RuntimeCall>(origin, call, result_xcms_version)
        }
        fn dry_run_xcm(origin_location: VersionedLocation, xcm: VersionedXcm<RuntimeCall>) -> Result<XcmDryRunEffects<RuntimeEvent>, XcmDryRunApiError> {
            PolkadotXcm::dry_run_xcm::<Runtime, xcm_config::XcmRouter, RuntimeCall, xcm_config::XcmConfig>(origin_location, xcm)
        }
    }
    impl xcm_runtime_apis::conversions::LocationToAccountApi<Block, AccountId> for Runtime {
        fn convert_location(location: VersionedLocation) -> Result<
            AccountId,
            xcm_runtime_apis::conversions::Error
        > {
            xcm_runtime_apis::conversions::LocationToAccountHelper::<
                AccountId,
                xcm_config::LocationToAccountId,
            >::convert_location(location)
        }
    }
13536
}
#[allow(dead_code)]
struct CheckInherents;
#[allow(deprecated)]
impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
    fn check_inherents(
        block: &Block,
        relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
    ) -> sp_inherents::CheckInherentsResult {
        let relay_chain_slot = relay_state_proof
            .read_slot()
            .expect("Could not read the relay chain slot from the proof");
        let inherent_data =
            cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(
                relay_chain_slot,
                core::time::Duration::from_secs(6),
            )
            .create_inherent_data()
            .expect("Could not create the timestamp inherent data");
        inherent_data.check_extrinsics(block)
    }
}
cumulus_pallet_parachain_system::register_validate_block! {
    Runtime = Runtime,
    CheckInherents = CheckInherents,
    BlockExecutor = pallet_author_inherent::BlockExecutor::<Runtime, Executive>,
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
1
    fn test_chain_id_derivation_dancelight() {
1
        let chain_id = dynamic_params::EthereumNetworkChainId::from_relay_network(
1
            &NetworkId::ByGenesis(dynamic_params::DANCELIGHT_GENESIS_HASH),
1
        )
1
        .unwrap()
1
        .as_u64();
1
        assert_eq!(chain_id, dynamic_params::SEPOLIA_ETH_TESTNET_CHAIN_ID);
1
    }
    #[test]
1
    fn test_chain_id_derivation_starlight() {
1
        let chain_id = dynamic_params::EthereumNetworkChainId::from_relay_network(
1
            &NetworkId::ByGenesis(dynamic_params::TANSSI_GENESIS_HASH),
1
        )
1
        .unwrap()
1
        .as_u64();
1
        assert_eq!(chain_id, dynamic_params::ETH_MAINNET_CHAIN_ID);
1
    }
}