diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7543d7019..263d8383b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,7 +73,9 @@ jobs: - name: Check Build run: | - SKIP_WASM_BUILD= cargo check --all-targets --all-features + SKIP_WASM_BUILD= cargo check --bin parallel-dev --features runtime-benchmarks + SKIP_WASM_BUILD= cargo check --bin parallel --features runtime-benchmarks + SKIP_WASM_BUILD= cargo check --bin parallel --no-default-features --features runtime-parallel --features runtime-benchmarks # - name: Check Wasm # run: | diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index f9512ac7c..4629e6b33 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -42,7 +42,7 @@ jobs: - name: Generate code coverage run: | - cargo +nightly-2021-03-24 tarpaulin --verbose --all-features --workspace --exclude parallel --exclude parallel-dev --exclude parallel-runtime --exclude vanilla-runtime --timeout 120 --out Xml + cargo +nightly-2021-03-24 tarpaulin --verbose --workspace --exclude parallel --exclude parallel-dev --exclude parallel-runtime --exclude heiko-runtime --exclude vanilla-runtime --timeout 120 --out Xml - name: Upload To Codecov.io uses: codecov/codecov-action@v1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 006860905..d75d56eb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ - Add RpcDataProviderId & AccountData to types.json (#136) +## 2021.05.22 + +- Add xKSM, heiko-runtime and impl_currency_id macro (#134) + ## 2021.05.21 - Add types.json update bot (#130) diff --git a/Cargo.lock b/Cargo.lock index dc782e777..45f21fb74 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2704,6 +2704,73 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heiko-runtime" +version = "0.0.1" +dependencies = [ + "cumulus-pallet-aura-ext", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-utility", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "hex-literal 0.3.1", + "orml-currencies", + "orml-oracle", + "orml-oracle-rpc-runtime-api", + "orml-tokens", + "orml-traits", + "orml-utilities", + "pallet-aura", + "pallet-balances", + "pallet-collective", + "pallet-democracy", + "pallet-elections-phragmen", + "pallet-liquidate", + "pallet-loans", + "pallet-loans-benchmarking", + "pallet-membership", + "pallet-multisig", + "pallet-prices", + "pallet-scheduler", + "pallet-staking 1.0.0", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-treasury", + "pallet-xcm", + "parachain-info", + "parallel-primitives", + "parity-scale-codec", + "polkadot-parachain", + "serde", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-inherents", + "sp-io", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "static_assertions", + "substrate-wasm-builder 4.0.0", + "xcm", + "xcm-builder", + "xcm-executor", +] + [[package]] name = "hermit-abi" version = "0.1.18" @@ -5559,6 +5626,7 @@ dependencies = [ "derive_more 0.15.0", "frame-benchmarking", "frame-benchmarking-cli", + "heiko-runtime", "hex-literal 0.2.1", "jsonrpc-core", "log", diff --git a/Cargo.toml b/Cargo.toml index cb1de871f..a858ca4ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,4 +2,4 @@ panic = 'unwind' [workspace] -members = ['node/*', 'pallets/*', 'runtime/*'] +members = ['node/*', 'pallets/*'] diff --git a/node/parallel-dev/src/chain_spec.rs b/node/parallel-dev/src/chain_spec.rs index 5a13a6bbd..9ac0e4af9 100644 --- a/node/parallel-dev/src/chain_spec.rs +++ b/node/parallel-dev/src/chain_spec.rs @@ -25,8 +25,8 @@ use sp_runtime::{ }; use vanilla_runtime::currency::DOLLARS; use vanilla_runtime::{ - AuraConfig, CouncilConfig, DemocracyConfig, ElectionsConfig, GrandpaConfig, - TechnicalCommitteeConfig, VanillaOracleConfig, WASM_BINARY, + AuraConfig, CouncilConfig, DemocracyConfig, ElectionsConfig, GrandpaConfig, OracleConfig, + TechnicalCommitteeConfig, WASM_BINARY, }; pub type VanillaChainSpec = sc_service::GenericChainSpec; @@ -177,7 +177,7 @@ fn testnet_genesis( .collect(), }, pallet_sudo: vanilla_runtime::SudoConfig { key: root_key }, - orml_oracle_Instance1: VanillaOracleConfig { + orml_oracle_Instance1: OracleConfig { members: endowed_accounts.clone().into(), phantom: Default::default(), }, @@ -190,6 +190,7 @@ fn testnet_genesis( (x.clone(), CurrencyId::KSM, 1_000 * TOKEN_DECIMAL), (x.clone(), CurrencyId::USDT, 1_000 * TOKEN_DECIMAL), (x.clone(), CurrencyId::xDOT, 1_000 * TOKEN_DECIMAL), + (x.clone(), CurrencyId::xKSM, 1_000 * TOKEN_DECIMAL), ] }) .collect(), @@ -200,6 +201,7 @@ fn testnet_genesis( CurrencyId::KSM, CurrencyId::USDT, CurrencyId::xDOT, + CurrencyId::xKSM, ], borrow_index: Rate::one(), // 1 exchange_rate: Rate::saturating_from_rational(2, 100), // 0.02 @@ -212,12 +214,14 @@ fn testnet_genesis( (CurrencyId::KSM, Ratio::from_percent(50)), (CurrencyId::USDT, Ratio::from_percent(50)), (CurrencyId::xDOT, Ratio::from_percent(50)), + (CurrencyId::xKSM, Ratio::from_percent(50)), ], liquidation_incentive: vec![ (CurrencyId::DOT, Ratio::from_percent(90)), (CurrencyId::KSM, Ratio::from_percent(90)), (CurrencyId::USDT, Ratio::from_percent(90)), (CurrencyId::xDOT, Ratio::from_percent(90)), + (CurrencyId::xKSM, Ratio::from_percent(90)), ], // TODO : please refer to https://github.com/parallel-finance/parallel/issues/46 liquidation_threshold: vec![ @@ -225,18 +229,21 @@ fn testnet_genesis( (CurrencyId::KSM, Ratio::from_percent(90)), (CurrencyId::USDT, Ratio::from_percent(90)), (CurrencyId::xDOT, Ratio::from_percent(90)), + (CurrencyId::xKSM, Ratio::from_percent(90)), ], close_factor: vec![ (CurrencyId::DOT, Ratio::from_percent(50)), (CurrencyId::KSM, Ratio::from_percent(50)), (CurrencyId::USDT, Ratio::from_percent(50)), (CurrencyId::xDOT, Ratio::from_percent(50)), + (CurrencyId::xKSM, Ratio::from_percent(50)), ], reserve_factor: vec![ (CurrencyId::DOT, Ratio::from_percent(15)), (CurrencyId::KSM, Ratio::from_percent(15)), (CurrencyId::USDT, Ratio::from_percent(15)), (CurrencyId::xDOT, Ratio::from_percent(15)), + (CurrencyId::xKSM, Ratio::from_percent(15)), ], }, pallet_staking: vanilla_runtime::StakingConfig { diff --git a/node/parallel/Cargo.toml b/node/parallel/Cargo.toml index 26c3174ac..e540c1b81 100644 --- a/node/parallel/Cargo.toml +++ b/node/parallel/Cargo.toml @@ -23,8 +23,9 @@ log = '0.4.13' primitives = { package = 'parallel-primitives', path = '../../primitives' } +heiko-runtime = { version = '0.0.1', path = '../../runtime/heiko', optional = true } pallet-transaction-payment-rpc = { version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.1' } -parallel-runtime = { version = '0.0.1', path = '../../runtime/parallel' } +parallel-runtime = { version = '0.0.1', path = '../../runtime/parallel', optional = true } sc-basic-authorship = { version = '0.9.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.1' } sc-chain-spec = { version = '3.0.0', git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.1' } @@ -80,8 +81,11 @@ substrate-build-script-utils = { version = '3.0.0', git = 'https://github.com/pa name = 'parallel' [features] -default = [] +default = ['runtime-parallel'] runtime-benchmarks = [ + 'heiko-runtime/runtime-benchmarks', 'parallel-runtime/runtime-benchmarks', 'polkadot-service/runtime-benchmarks', ] +runtime-heiko = ['heiko-runtime'] +runtime-parallel = ['parallel-runtime'] diff --git a/node/parallel/src/chain_spec.rs b/node/parallel/src/chain_spec.rs index b4bd1717a..c263a3bda 100644 --- a/node/parallel/src/chain_spec.rs +++ b/node/parallel/src/chain_spec.rs @@ -13,10 +13,17 @@ // limitations under the License. use cumulus_primitives_core::ParaId; -use parallel_runtime::currency::DOLLARS; +#[cfg(feature = "runtime-heiko")] +use heiko_runtime::{ + currency::DOLLARS, AuraConfig, BalancesConfig, CouncilConfig, DemocracyConfig, ElectionsConfig, + GenesisConfig, LoansConfig, OracleConfig, ParachainInfoConfig, StakingConfig, SudoConfig, + SystemConfig, TechnicalCommitteeConfig, TokensConfig, WASM_BINARY, +}; +#[cfg(feature = "runtime-parallel")] use parallel_runtime::{ - AuraConfig, CouncilConfig, DemocracyConfig, ElectionsConfig, ParallelOracleConfig, - TechnicalCommitteeConfig, + currency::DOLLARS, AuraConfig, BalancesConfig, CouncilConfig, DemocracyConfig, ElectionsConfig, + GenesisConfig, LoansConfig, OracleConfig, ParachainInfoConfig, StakingConfig, SudoConfig, + SystemConfig, TechnicalCommitteeConfig, TokensConfig, WASM_BINARY, }; use primitives::*; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; @@ -30,8 +37,7 @@ use sp_runtime::{ }; /// Specialized `ChainSpec` for the normal parachain runtime. -pub type ParallelChainSpec = - sc_service::GenericChainSpec; +pub type ChainSpec = sc_service::GenericChainSpec; #[allow(dead_code)] /// Helper function to generate a crypto pair from seed @@ -78,8 +84,8 @@ where AccountPublic::from(get_from_seed::(seed)).into_account() } -pub fn development_config(id: ParaId) -> ParallelChainSpec { - ParallelChainSpec::from_genesis( +pub fn development_config(id: ParaId) -> ChainSpec { + ChainSpec::from_genesis( // Name "Development", // ID @@ -127,8 +133,8 @@ pub fn development_config(id: ParaId) -> ParallelChainSpec { ) } -pub fn local_testnet_config(id: ParaId) -> ParallelChainSpec { - ParallelChainSpec::from_genesis( +pub fn local_testnet_config(id: ParaId) -> ChainSpec { + ChainSpec::from_genesis( // Name "Local Testnet", // ID @@ -176,60 +182,55 @@ pub fn local_testnet_config(id: ParaId) -> ParallelChainSpec { ) } +#[cfg(feature = "runtime-parallel")] fn testnet_genesis( root_key: AccountId, initial_authorities: Vec<(AccountId, AuraId)>, endowed_accounts: Vec, id: ParaId, -) -> parallel_runtime::GenesisConfig { +) -> GenesisConfig { let num_endowed_accounts = endowed_accounts.len(); const ENDOWMENT: Balance = 10_000_000 * DOLLARS; const STASH: Balance = ENDOWMENT / 1000; - parallel_runtime::GenesisConfig { - frame_system: parallel_runtime::SystemConfig { - code: parallel_runtime::WASM_BINARY + GenesisConfig { + frame_system: SystemConfig { + code: WASM_BINARY .expect("WASM binary was not build, please build it!") .to_vec(), changes_trie_config: Default::default(), }, - pallet_balances: parallel_runtime::BalancesConfig { + pallet_balances: BalancesConfig { balances: endowed_accounts .iter() .cloned() .map(|k| (k, 1 << 60)) .collect(), }, - // TODO : collateral selection + // TODO : collateral selection using session pallet_aura: AuraConfig { authorities: initial_authorities.iter().map(|x| (x.1.clone())).collect(), }, cumulus_pallet_aura_ext: Default::default(), - pallet_sudo: parallel_runtime::SudoConfig { key: root_key }, - parachain_info: parallel_runtime::ParachainInfoConfig { parachain_id: id }, - orml_oracle_Instance1: ParallelOracleConfig { + pallet_sudo: SudoConfig { key: root_key }, + parachain_info: ParachainInfoConfig { parachain_id: id }, + orml_oracle_Instance1: OracleConfig { members: endowed_accounts.clone().into(), phantom: Default::default(), }, - orml_tokens: parallel_runtime::TokensConfig { + orml_tokens: TokensConfig { endowed_accounts: endowed_accounts .iter() .flat_map(|x| { vec![ (x.clone(), CurrencyId::DOT, 1_000 * TOKEN_DECIMAL), - (x.clone(), CurrencyId::KSM, 1_000 * TOKEN_DECIMAL), (x.clone(), CurrencyId::USDT, 1_000 * TOKEN_DECIMAL), (x.clone(), CurrencyId::xDOT, 1_000 * TOKEN_DECIMAL), ] }) .collect(), }, - pallet_loans: parallel_runtime::LoansConfig { - currencies: vec![ - CurrencyId::DOT, - CurrencyId::KSM, - CurrencyId::USDT, - CurrencyId::xDOT, - ], + pallet_loans: LoansConfig { + currencies: vec![CurrencyId::DOT, CurrencyId::USDT, CurrencyId::xDOT], borrow_index: Rate::one(), // 1 exchange_rate: Rate::saturating_from_rational(2, 100), // 0.02 base_rate: Rate::saturating_from_rational(2, 100), // 2% @@ -238,37 +239,140 @@ fn testnet_genesis( kink_utilization: Ratio::from_percent(80), // 80% collateral_factor: vec![ (CurrencyId::DOT, Ratio::from_percent(50)), - (CurrencyId::KSM, Ratio::from_percent(50)), (CurrencyId::USDT, Ratio::from_percent(50)), (CurrencyId::xDOT, Ratio::from_percent(50)), ], liquidation_incentive: vec![ (CurrencyId::DOT, Ratio::from_percent(90)), - (CurrencyId::KSM, Ratio::from_percent(90)), (CurrencyId::USDT, Ratio::from_percent(90)), (CurrencyId::xDOT, Ratio::from_percent(90)), ], // TODO : please refer to https://github.com/parallel-finance/parallel/issues/46 liquidation_threshold: vec![ (CurrencyId::DOT, Ratio::from_percent(90)), - (CurrencyId::KSM, Ratio::from_percent(90)), (CurrencyId::USDT, Ratio::from_percent(90)), (CurrencyId::xDOT, Ratio::from_percent(90)), ], close_factor: vec![ (CurrencyId::DOT, Ratio::from_percent(50)), - (CurrencyId::KSM, Ratio::from_percent(50)), (CurrencyId::USDT, Ratio::from_percent(50)), (CurrencyId::xDOT, Ratio::from_percent(50)), ], reserve_factor: vec![ (CurrencyId::DOT, Ratio::from_percent(15)), - (CurrencyId::KSM, Ratio::from_percent(15)), (CurrencyId::USDT, Ratio::from_percent(15)), (CurrencyId::xDOT, Ratio::from_percent(15)), ], }, - pallet_staking: parallel_runtime::StakingConfig { + pallet_staking: StakingConfig { + exchange_rate: Rate::saturating_from_rational(2, 100), // 0.02 + }, + pallet_democracy: DemocracyConfig::default(), + pallet_elections_phragmen: ElectionsConfig { + members: endowed_accounts + .iter() + .take((num_endowed_accounts + 1) / 2) + .cloned() + .map(|member| (member, STASH)) + .collect(), + }, + pallet_collective_Instance1: CouncilConfig::default(), + pallet_collective_Instance2: TechnicalCommitteeConfig { + members: endowed_accounts + .iter() + .take((num_endowed_accounts + 1) / 2) + .cloned() + .collect(), + phantom: Default::default(), + }, + pallet_membership_Instance1: Default::default(), + pallet_treasury: Default::default(), + } +} + +#[cfg(feature = "runtime-heiko")] +fn testnet_genesis( + root_key: AccountId, + initial_authorities: Vec<(AccountId, AuraId)>, + endowed_accounts: Vec, + id: ParaId, +) -> GenesisConfig { + let num_endowed_accounts = endowed_accounts.len(); + const ENDOWMENT: Balance = 10_000_000 * DOLLARS; + const STASH: Balance = ENDOWMENT / 1000; + GenesisConfig { + frame_system: SystemConfig { + code: WASM_BINARY + .expect("WASM binary was not build, please build it!") + .to_vec(), + changes_trie_config: Default::default(), + }, + pallet_balances: BalancesConfig { + balances: endowed_accounts + .iter() + .cloned() + .map(|k| (k, 1 << 60)) + .collect(), + }, + // TODO : collateral selection using session + pallet_aura: AuraConfig { + authorities: initial_authorities.iter().map(|x| (x.1.clone())).collect(), + }, + cumulus_pallet_aura_ext: Default::default(), + pallet_sudo: SudoConfig { key: root_key }, + parachain_info: ParachainInfoConfig { parachain_id: id }, + orml_oracle_Instance1: OracleConfig { + members: endowed_accounts.clone().into(), + phantom: Default::default(), + }, + orml_tokens: TokensConfig { + endowed_accounts: endowed_accounts + .iter() + .flat_map(|x| { + vec![ + (x.clone(), CurrencyId::KSM, 1_000 * TOKEN_DECIMAL), + (x.clone(), CurrencyId::USDT, 1_000 * TOKEN_DECIMAL), + (x.clone(), CurrencyId::xKSM, 1_000 * TOKEN_DECIMAL), + ] + }) + .collect(), + }, + pallet_loans: LoansConfig { + currencies: vec![CurrencyId::KSM, CurrencyId::USDT, CurrencyId::xKSM], + borrow_index: Rate::one(), // 1 + exchange_rate: Rate::saturating_from_rational(2, 100), // 0.02 + base_rate: Rate::saturating_from_rational(2, 100), // 2% + kink_rate: Rate::saturating_from_rational(10, 100), // 10% + full_rate: Rate::saturating_from_rational(32, 100), // 32% + kink_utilization: Ratio::from_percent(80), // 80% + collateral_factor: vec![ + (CurrencyId::KSM, Ratio::from_percent(50)), + (CurrencyId::USDT, Ratio::from_percent(50)), + (CurrencyId::xKSM, Ratio::from_percent(50)), + ], + liquidation_incentive: vec![ + (CurrencyId::KSM, Ratio::from_percent(90)), + (CurrencyId::USDT, Ratio::from_percent(90)), + (CurrencyId::xKSM, Ratio::from_percent(90)), + ], + // TODO : please refer to https://github.com/parallel-finance/parallel/issues/46 + liquidation_threshold: vec![ + (CurrencyId::KSM, Ratio::from_percent(90)), + (CurrencyId::USDT, Ratio::from_percent(90)), + (CurrencyId::xKSM, Ratio::from_percent(90)), + ], + close_factor: vec![ + (CurrencyId::KSM, Ratio::from_percent(50)), + (CurrencyId::USDT, Ratio::from_percent(50)), + (CurrencyId::xKSM, Ratio::from_percent(50)), + ], + reserve_factor: vec![ + (CurrencyId::KSM, Ratio::from_percent(15)), + (CurrencyId::USDT, Ratio::from_percent(15)), + (CurrencyId::xKSM, Ratio::from_percent(15)), + ], + }, + pallet_staking: StakingConfig { exchange_rate: Rate::saturating_from_rational(2, 100), // 0.02 }, pallet_democracy: DemocracyConfig::default(), diff --git a/node/parallel/src/command.rs b/node/parallel/src/command.rs index 3bb6a0182..ab8a23457 100644 --- a/node/parallel/src/command.rs +++ b/node/parallel/src/command.rs @@ -19,8 +19,12 @@ use crate::{ use codec::Encode; use cumulus_client_service::genesis::generate_genesis_block; use cumulus_primitives_core::ParaId; +#[cfg(feature = "runtime-heiko")] +use heiko_runtime::{Block, VERSION}; use log::info; -use parallel_runtime::Block; +#[cfg(feature = "runtime-parallel")] +use parallel_runtime::{Block, VERSION}; + use polkadot_parachain::primitives::AccountIdConversion; use sc_cli::{ ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, @@ -43,7 +47,7 @@ fn load_spec( Ok(match id { "dev" => Box::new(chain_spec::development_config(para_id)), "" | "local" => Box::new(chain_spec::local_testnet_config(para_id)), - path => Box::new(chain_spec::ParallelChainSpec::from_json_file( + path => Box::new(chain_spec::ChainSpec::from_json_file( std::path::PathBuf::from(path), )?), }) @@ -79,7 +83,7 @@ impl SubstrateCli for Cli { } fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { - ¶llel_runtime::VERSION + &VERSION } } diff --git a/node/parallel/src/rpc.rs b/node/parallel/src/rpc.rs index ab96c50a0..07f605b0c 100644 --- a/node/parallel/src/rpc.rs +++ b/node/parallel/src/rpc.rs @@ -2,6 +2,9 @@ use std::sync::Arc; +#[cfg(feature = "runtime-heiko")] +use heiko_runtime::opaque::Block; +#[cfg(feature = "runtime-parallel")] use parallel_runtime::opaque::Block; use primitives::{AccountId, Balance, CurrencyId, DataProviderId, Index, TimeStampedPrice}; pub use sc_rpc_api::DenyUnsafe; diff --git a/node/parallel/src/service.rs b/node/parallel/src/service.rs index cd0bf546b..8992a0c5f 100644 --- a/node/parallel/src/service.rs +++ b/node/parallel/src/service.rs @@ -33,6 +33,7 @@ use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use std::sync::Arc; // Native executor instance. +#[cfg(feature = "runtime-parallel")] native_executor_instance!( pub Executor, parallel_runtime::api::dispatch, @@ -40,10 +41,24 @@ native_executor_instance!( frame_benchmarking::benchmarking::HostFunctions, ); -type ParallelBlock = parallel_runtime::opaque::Block; -type ParallelRuntimeApi = parallel_runtime::RuntimeApi; -type ParallelFullClient = sc_service::TFullClient; -type ParallelFullBackend = sc_service::TFullBackend; +#[cfg(feature = "runtime-heiko")] +native_executor_instance!( + pub Executor, + heiko_runtime::api::dispatch, + heiko_runtime::native_version, + frame_benchmarking::benchmarking::HostFunctions, +); + +#[cfg(feature = "runtime-parallel")] +type RuntimeBlock = parallel_runtime::opaque::Block; +#[cfg(feature = "runtime-heiko")] +type RuntimeBlock = heiko_runtime::opaque::Block; +#[cfg(feature = "runtime-parallel")] +type RuntimeApi = parallel_runtime::RuntimeApi; +#[cfg(feature = "runtime-heiko")] +type RuntimeApi = heiko_runtime::RuntimeApi; +type RuntimeFullClient = sc_service::TFullClient; +type RuntimeFullBackend = sc_service::TFullBackend; /// Starts a `ServiceBuilder` for a full service. /// @@ -53,11 +68,11 @@ pub fn new_partial( config: &Configuration, ) -> Result< PartialComponents< - ParallelFullClient, - ParallelFullBackend, + RuntimeFullClient, + RuntimeFullBackend, (), - sp_consensus::DefaultImportQueue, - sc_transaction_pool::FullPool, + sp_consensus::DefaultImportQueue, + sc_transaction_pool::FullPool, (Option, Option), >, sc_service::Error, @@ -74,7 +89,7 @@ pub fn new_partial( .transpose()?; let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( + sc_service::new_full_parts::( &config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), )?; @@ -185,7 +200,7 @@ async fn start_node_impl( collator_key: CollatorPair, polkadot_config: Configuration, id: ParaId, -) -> sc_service::error::Result<(TaskManager, Arc)> { +) -> sc_service::error::Result<(TaskManager, Arc)> { if matches!(parachain_config.role, Role::Light) { return Err("Light client not supported!".into()); } @@ -383,7 +398,7 @@ pub async fn start_node( id: ParaId, ) -> sc_service::error::Result<( TaskManager, - Arc>, + Arc>, )> { start_node_impl(parachain_config, collator_key, polkadot_config, id).await } diff --git a/pallets/loans/benchmarking/Cargo.toml b/pallets/loans/benchmarking/Cargo.toml index 59038e23e..82819b120 100644 --- a/pallets/loans/benchmarking/Cargo.toml +++ b/pallets/loans/benchmarking/Cargo.toml @@ -17,13 +17,13 @@ orml-oracle = { git = 'https://github.com/open-web3-stack/open-runtime-mo orml-tokens = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } orml-traits = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } pallet-balances = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.1', version = '3.0.0', default-features = false } -pallet-loans = { version = "1.0.0", default-features = false, features = ["runtime-benchmarks"], path = "../../loans" } +pallet-loans = { version = '1.0.0', default-features = false, features = ['runtime-benchmarks'], path = '../../loans' } primitives = { package = 'parallel-primitives', path = '../../../primitives', default-features = false } sp-runtime = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.1', version = '3.0.0', default-features = false } sp-std = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.1', version = '3.0.0', default-features = false } [dev-dependencies] -lazy_static = { version = "1.4.0" } +lazy_static = { version = '1.4.0' } sp-core = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.1', version = '3.0.0', default-features = false } sp-io = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.1', version = '3.0.0', default-features = false } diff --git a/pallets/loans/benchmarking/src/mock.rs b/pallets/loans/benchmarking/src/mock.rs index 4de462ec1..1448a27b3 100644 --- a/pallets/loans/benchmarking/src/mock.rs +++ b/pallets/loans/benchmarking/src/mock.rs @@ -205,6 +205,7 @@ impl pallet_loans::Config for Test { type Event = Event; type Currency = Currencies; type PalletId = LoansPalletId; + type BlockPerYear = BlockPerYear; type PriceFeeder = MOCK_PRICE_FEEDER; type ReserveOrigin = EnsureRoot; type UpdateOrigin = EnsureRoot; @@ -215,11 +216,60 @@ impl crate::Config for Test {} parameter_types! { pub const LoansPalletId: PalletId = PalletId(*b"par/loan"); + pub const BlockPerYear: u128 = 5256000; } pub fn new_test_ext() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::default() + let mut t = frame_system::GenesisConfig::default() .build_storage::() .unwrap(); + + pallet_loans::GenesisConfig { + currencies: vec![ + CurrencyId::DOT, + CurrencyId::KSM, + CurrencyId::USDT, + CurrencyId::xDOT, + ], + borrow_index: Rate::one(), // 1 + exchange_rate: Rate::saturating_from_rational(2, 100), // 0.02 + base_rate: Rate::saturating_from_rational(2, 100), // 2% + kink_rate: Rate::saturating_from_rational(10, 100), // 10% + full_rate: Rate::saturating_from_rational(32, 100), // 32% + kink_utilization: Ratio::from_percent(80), // 80% + collateral_factor: vec![ + (CurrencyId::DOT, Ratio::from_percent(50)), + (CurrencyId::KSM, Ratio::from_percent(50)), + (CurrencyId::USDT, Ratio::from_percent(50)), + (CurrencyId::xDOT, Ratio::from_percent(50)), + ], + liquidation_incentive: vec![ + (CurrencyId::DOT, Ratio::from_percent(90)), + (CurrencyId::KSM, Ratio::from_percent(90)), + (CurrencyId::USDT, Ratio::from_percent(90)), + (CurrencyId::xDOT, Ratio::from_percent(90)), + ], + liquidation_threshold: vec![ + (CurrencyId::DOT, Ratio::from_percent(80)), + (CurrencyId::KSM, Ratio::from_percent(80)), + (CurrencyId::USDT, Ratio::from_percent(90)), + (CurrencyId::xDOT, Ratio::from_percent(80)), + ], + close_factor: vec![ + (CurrencyId::DOT, Ratio::from_percent(50)), + (CurrencyId::KSM, Ratio::from_percent(50)), + (CurrencyId::USDT, Ratio::from_percent(50)), + (CurrencyId::xDOT, Ratio::from_percent(50)), + ], + reserve_factor: vec![ + (CurrencyId::DOT, Ratio::from_percent(15)), + (CurrencyId::KSM, Ratio::from_percent(15)), + (CurrencyId::USDT, Ratio::from_percent(15)), + (CurrencyId::xDOT, Ratio::from_percent(15)), + ], + } + .assimilate_storage::(&mut t) + .unwrap(); + sp_io::TestExternalities::new(t) } diff --git a/pallets/loans/src/lib.rs b/pallets/loans/src/lib.rs index 536daf8d3..66a5e5f27 100644 --- a/pallets/loans/src/lib.rs +++ b/pallets/loans/src/lib.rs @@ -83,6 +83,10 @@ pub mod module { #[pallet::constant] type PalletId: Get; + /// The block per year of relay chain + #[pallet::constant] + type BlockPerYear: Get; + /// The origin which can add/reduce reserves. type ReserveOrigin: EnsureOrigin; @@ -150,6 +154,8 @@ pub mod module { InsufficientReserves, /// Invalid rate model params InvalidRateModelParam, + /// Currency Not Enabled + CurrencyNotEnabled, } #[pallet::event] @@ -439,6 +445,8 @@ pub mod module { currency_id: CurrencyId, mint_amount: Balance, ) -> DispatchResultWithPostInfo { + Self::ensure_currency(¤cy_id)?; + let who = ensure_signed(origin)?; Self::update_earned_stored(&who, ¤cy_id)?; Self::mint_internal(&who, ¤cy_id, mint_amount)?; @@ -453,6 +461,8 @@ pub mod module { currency_id: CurrencyId, redeem_amount: Balance, ) -> DispatchResultWithPostInfo { + Self::ensure_currency(¤cy_id)?; + let who = ensure_signed(origin)?; Self::update_earned_stored(&who, ¤cy_id)?; Self::redeem_internal(&who, ¤cy_id, redeem_amount)?; @@ -466,6 +476,8 @@ pub mod module { origin: OriginFor, currency_id: CurrencyId, ) -> DispatchResultWithPostInfo { + Self::ensure_currency(¤cy_id)?; + let who = ensure_signed(origin)?; Self::update_earned_stored(&who, ¤cy_id)?; let collateral = AccountCollateral::::get(¤cy_id, &who); @@ -485,6 +497,8 @@ pub mod module { currency_id: CurrencyId, borrow_amount: Balance, ) -> DispatchResultWithPostInfo { + Self::ensure_currency(¤cy_id)?; + let who = ensure_signed(origin)?; Self::borrow_internal(&who, ¤cy_id, borrow_amount)?; Ok(().into()) @@ -498,6 +512,8 @@ pub mod module { currency_id: CurrencyId, repay_amount: Balance, ) -> DispatchResultWithPostInfo { + Self::ensure_currency(¤cy_id)?; + let who = ensure_signed(origin)?; Self::repay_borrow_internal(&who, ¤cy_id, repay_amount)?; Ok(().into()) @@ -510,6 +526,8 @@ pub mod module { origin: OriginFor, currency_id: CurrencyId, ) -> DispatchResultWithPostInfo { + Self::ensure_currency(¤cy_id)?; + let who = ensure_signed(origin)?; let account_borrows = Self::borrow_balance_stored(&who, ¤cy_id)?; Self::repay_borrow_internal(&who, ¤cy_id, account_borrows)?; @@ -524,6 +542,8 @@ pub mod module { currency_id: CurrencyId, amount: Balance, ) -> DispatchResultWithPostInfo { + Self::ensure_currency(¤cy_id)?; + let who = ensure_signed(origin)?; T::Currency::transfer(currency_id, &who, &to, amount)?; @@ -537,6 +557,8 @@ pub mod module { currency_id: CurrencyId, enable: bool, ) -> DispatchResultWithPostInfo { + Self::ensure_currency(¤cy_id)?; + let who = ensure_signed(origin)?; Self::collateral_asset_internal(who, currency_id, enable)?; @@ -553,6 +575,8 @@ pub mod module { repay_amount: Balance, collateral_token: CurrencyId, ) -> DispatchResultWithPostInfo { + Self::ensure_currency(&liquidate_token)?; + let who = ensure_signed(origin)?; Self::liquidate_borrow_internal( who, @@ -572,6 +596,7 @@ pub mod module { currency_id: CurrencyId, new_model: InterestRateModel, ) -> DispatchResultWithPostInfo { + Self::ensure_currency(&¤cy_id)?; T::UpdateOrigin::ensure_origin(origin)?; new_model @@ -591,6 +616,7 @@ pub mod module { currency_id: CurrencyId, add_amount: Balance, ) -> DispatchResultWithPostInfo { + Self::ensure_currency(&¤cy_id)?; T::ReserveOrigin::ensure_origin(origin)?; let payer = T::Lookup::lookup(payer)?; @@ -618,6 +644,7 @@ pub mod module { currency_id: CurrencyId, reduce_amount: Balance, ) -> DispatchResultWithPostInfo { + Self::ensure_currency(&¤cy_id)?; T::ReserveOrigin::ensure_origin(origin)?; let receiver = T::Lookup::lookup(receiver)?; @@ -650,6 +677,17 @@ impl Pallet { T::PalletId::get().into_account() } + fn ensure_currency(currency_id: &CurrencyId) -> DispatchResult { + if Self::currencies() + .iter() + .any(|currency| currency == currency_id) + { + Ok(()) + } else { + Err(>::CurrencyNotEnabled.into()) + } + } + fn accrue_interest() -> DispatchResult { for currency_id in Self::currencies() { let total_cash = Self::get_total_cash(currency_id); @@ -673,7 +711,7 @@ impl Pallet { SupplyRate::::insert(currency_id, supply_rate.0); let borrow_rate_per_block = APR::from(borrow_rate) - .rate_per_block() + .rate_per_block(T::BlockPerYear::get()) .ok_or(Error::::CalcAccrueInterestFailed)?; Self::update_borrow_index(borrow_rate_per_block, currency_id)?; Self::update_exchange_rate(currency_id)?; diff --git a/pallets/loans/src/loan.rs b/pallets/loans/src/loan.rs index 0bc5d225c..01a7c91be 100644 --- a/pallets/loans/src/loan.rs +++ b/pallets/loans/src/loan.rs @@ -285,26 +285,24 @@ impl Pallet { } else { return Err(Error::::AlreadyEnabledCollateral); } - } else { - if let Some(index) = collateral_assets.iter().position(|c| c == ¤cy_id) { - let total_collateral_asset_value = Self::total_collateral_asset_value(&who)?; - let collateral_asset_value = Self::collateral_asset_value(&who, ¤cy_id)?; - let total_borrowed_value = Self::total_borrowed_value(&who)?; - - if total_collateral_asset_value - > total_borrowed_value - .checked_add(collateral_asset_value) - .ok_or(Error::::CollateralOverflow)? - { - collateral_assets.remove(index); - AccountCollateralAssets::::insert(who.clone(), collateral_assets); - Self::deposit_event(Event::::CollateralAssetRemoved(who, currency_id)); - } else { - return Err(Error::::CollateralDisableActionDenied); - } + } else if let Some(index) = collateral_assets.iter().position(|c| c == ¤cy_id) { + let total_collateral_asset_value = Self::total_collateral_asset_value(&who)?; + let collateral_asset_value = Self::collateral_asset_value(&who, ¤cy_id)?; + let total_borrowed_value = Self::total_borrowed_value(&who)?; + + if total_collateral_asset_value + > total_borrowed_value + .checked_add(collateral_asset_value) + .ok_or(Error::::CollateralOverflow)? + { + collateral_assets.remove(index); + AccountCollateralAssets::::insert(who.clone(), collateral_assets); + Self::deposit_event(Event::::CollateralAssetRemoved(who, currency_id)); } else { - return Err(Error::::AlreadyDisabledCollateral); + return Err(Error::::CollateralDisableActionDenied); } + } else { + return Err(Error::::AlreadyDisabledCollateral); } Ok(()) diff --git a/pallets/loans/src/mock.rs b/pallets/loans/src/mock.rs index 777b99fc8..eb63ea62e 100644 --- a/pallets/loans/src/mock.rs +++ b/pallets/loans/src/mock.rs @@ -171,6 +171,7 @@ impl Config for Runtime { type Event = Event; type Currency = Currencies; type PalletId = LoansPalletId; + type BlockPerYear = BlockPerYear; type PriceFeeder = MOCK_PRICE_FEEDER; type ReserveOrigin = EnsureRoot; type UpdateOrigin = EnsureRoot; @@ -179,6 +180,7 @@ impl Config for Runtime { parameter_types! { pub const LoansPalletId: PalletId = PalletId(*b"par/loan"); + pub const BlockPerYear: u128 = 5256000; } pub struct ExtBuilder { diff --git a/pallets/loans/src/rate.rs b/pallets/loans/src/rate.rs index febf1840c..c83572b1a 100644 --- a/pallets/loans/src/rate.rs +++ b/pallets/loans/src/rate.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use primitives::{Rate, Ratio, BLOCK_PER_YEAR}; +use primitives::{Rate, Ratio}; use sp_runtime::traits::{CheckedAdd, CheckedDiv, CheckedSub, Saturating}; use crate::*; @@ -40,9 +40,9 @@ impl From for APR { impl APR { pub const MAX: Rate = Rate::from_inner(350_000_000_000_000_000); // 35% - pub fn rate_per_block(&self) -> Option { + pub fn rate_per_block(&self, block_per_year: u128) -> Option { self.0 - .checked_div(&Rate::saturating_from_integer(BLOCK_PER_YEAR)) + .checked_div(&Rate::saturating_from_integer(block_per_year)) } } @@ -227,7 +227,9 @@ mod tests { #[test] fn get_supply_rate_works() { - let borrow_rate = APR::from(Rate::saturating_from_rational(2, 100 * BLOCK_PER_YEAR)); + // DOT's block per year + let block_per_year: u128 = 5256000; + let borrow_rate = APR::from(Rate::saturating_from_rational(2, 100 * block_per_year)); let util = Ratio::from_percent(50); let reserve_factor = Ratio::zero(); let supply_rate = diff --git a/pallets/loans/src/tests.rs b/pallets/loans/src/tests.rs index a2b4c7448..6537dc2c8 100644 --- a/pallets/loans/src/tests.rs +++ b/pallets/loans/src/tests.rs @@ -15,7 +15,7 @@ //! Unit tests for the loans module. use frame_support::{assert_noop, assert_ok}; -use primitives::{BLOCK_PER_YEAR, RATE_DECIMAL}; +use primitives::RATE_DECIMAL; use sp_runtime::traits::{CheckedDiv, One, Saturating}; use sp_runtime::{FixedU128, Permill}; @@ -292,7 +292,9 @@ fn interest_rate_model_works() { let multiplier_per_year = Multiplier::saturating_from_rational(1, 10); let multiplier_per_block = multiplier_per_year - .checked_div(&Rate::saturating_from_integer(BLOCK_PER_YEAR)) + .checked_div(&Rate::saturating_from_integer( + ::BlockPerYear::get(), + )) .unwrap(); assert_eq!(multiplier_per_block, Rate::from_inner(19025875190)); @@ -302,7 +304,9 @@ fn interest_rate_model_works() { let base_rate_per_year = Rate::saturating_from_rational(2, 100); let base_rate_per_block = base_rate_per_year - .checked_div(&Rate::saturating_from_integer(BLOCK_PER_YEAR)) + .checked_div(&Rate::saturating_from_integer( + ::BlockPerYear::get(), + )) .unwrap(); assert_eq!(base_rate_per_block, Rate::from_inner(3805175038)); diff --git a/pallets/prices/src/lib.rs b/pallets/prices/src/lib.rs index d473195a4..c0c78dfca 100644 --- a/pallets/prices/src/lib.rs +++ b/pallets/prices/src/lib.rs @@ -21,7 +21,9 @@ pub use module::*; use orml_traits::{arithmetic::CheckedDiv, DataProvider}; use primitives::*; +#[cfg(test)] mod mock; +#[cfg(test)] mod tests; #[frame_support::pallet] @@ -97,7 +99,7 @@ pub mod module { impl Pallet { // get emergency price, the timestamp is zero fn get_emergency_price(currency_id: &CurrencyId) -> Option { - Self::emergency_price(currency_id).and_then(|price| Some((price, 0))) + Self::emergency_price(currency_id).map(|price| (price, 0)) } } @@ -106,13 +108,12 @@ impl PriceFeeder for Pallet { /// Timestamp is zero means the price is emergency price fn get_price(currency_id: &CurrencyId) -> Option { // if emergency price exists, return it, otherwise return latest price from oracle. - let origin_price = Self::get_emergency_price(currency_id).or_else(|| { - T::Source::get(¤cy_id).and_then(|price| Some((price.value, price.timestamp))) - }); + let origin_price = Self::get_emergency_price(currency_id) + .or_else(|| T::Source::get(¤cy_id).map(|price| (price.value, price.timestamp))); if let Some((price, timestamp)) = origin_price { price .checked_div(&Price::saturating_from_integer(CURRENCY_DECIMAL)) - .and_then(|p| Some((p, timestamp))) + .map(|p| (p, timestamp)) } else { None } @@ -123,7 +124,7 @@ impl EmergencyPriceFeeder for Pallet { /// Set emergency price fn set_emergency_price(currency_id: CurrencyId, price: Price) { // set price direct - EmergencyPrice::::insert(currency_id, price.clone()); + EmergencyPrice::::insert(currency_id, price); >::deposit_event(Event::SetPrice(currency_id, price)); } diff --git a/pallets/prices/src/mock.rs b/pallets/prices/src/mock.rs index 1494257fc..bd8bbb69c 100644 --- a/pallets/prices/src/mock.rs +++ b/pallets/prices/src/mock.rs @@ -14,8 +14,6 @@ //! Mocks for the prices module. -#![cfg(test)] - use super::*; use frame_support::{construct_runtime, ord_parameter_types, parameter_types}; use frame_system::EnsureSignedBy; diff --git a/pallets/prices/src/tests.rs b/pallets/prices/src/tests.rs index ed84a07b5..2abdcfe26 100644 --- a/pallets/prices/src/tests.rs +++ b/pallets/prices/src/tests.rs @@ -14,8 +14,6 @@ //! Unit tests for the prices pallet. -#![cfg(test)] - use super::*; use frame_support::{assert_noop, assert_ok}; use mock::{Event, *}; diff --git a/primitives/src/currency.rs b/primitives/src/currency.rs new file mode 100644 index 000000000..667a30547 --- /dev/null +++ b/primitives/src/currency.rs @@ -0,0 +1,60 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode}; +use sp_runtime::RuntimeDebug; +use sp_std::{convert::Into, prelude::*}; + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +pub trait CurrencyInfo { + fn name(&self) -> &str; + fn symbol(&self) -> &str; + fn decimals(&self) -> u32; +} + +macro_rules! impl_currency_id { + ($(#[$meta:meta])* + $vis:vis enum CurrencyId { + $($(#[$vmeta:meta])* $symbol:ident($name:expr, $deci:literal),)* + }) => { + $(#[$meta])* + $vis enum CurrencyId { + $($(#[$vmeta])* $symbol,)* + } + + impl CurrencyInfo for CurrencyId { + fn name(&self) -> &str { + match self { + $(CurrencyId::$symbol => $name),* + } + } + fn symbol(&self) -> &str { + match self { + $(CurrencyId::$symbol => stringify!($symbol),)* + } + } + fn decimals(&self) -> u32 { + match self { + $(CurrencyId::$symbol => $deci,)* + } + } + } + } +} + +// TODO: use decimals +impl_currency_id! { + #[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, RuntimeDebug, PartialOrd, Ord)] + #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash))] + pub enum CurrencyId { + DOT("Polkadot", 10), + KSM("Kusama", 12), + USDT("Tether", 6), + #[allow(non_camel_case_types)] + xDOT("Liquid DOT", 10), + #[allow(non_camel_case_types)] + xKSM("Liquid KSM", 12), + Native("Native", 18), + } +} diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 775674a59..8ad39a594 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -16,6 +16,8 @@ #![allow(clippy::unnecessary_cast)] #![allow(clippy::upper_case_acronyms)] +mod currency; + use codec::{Decode, Encode}; use sp_runtime::{ generic, @@ -86,16 +88,7 @@ pub type BlockId = generic::BlockId; /// Opaque, encoded, unchecked extrinsic. pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; -#[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, RuntimeDebug, PartialOrd, Ord)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash))] -pub enum CurrencyId { - DOT, - KSM, - USDT, - #[allow(non_camel_case_types)] - xDOT, - Native, -} +pub type AuraId = sp_consensus_aura::sr25519::AuthorityId; pub const TOKEN_DECIMAL: u128 = 1_000_000_000_000_000_000; @@ -103,8 +96,6 @@ pub const RATE_DECIMAL: u128 = 1_000_000_000_000_000_000; pub const CURRENCY_DECIMAL: u128 = 1_000_000_000_000; -pub const BLOCK_PER_YEAR: u128 = 5256000; - pub const MIN_PRICE: FixedU128 = FixedU128::from_inner(u128::MIN); pub type Price = FixedU128; @@ -113,27 +104,27 @@ pub type Timestamp = u64; pub type PriceDetail = (Price, Timestamp); -pub trait PriceFeeder { - fn get_price(currency_id: &CurrencyId) -> Option; -} - pub type Rate = FixedU128; pub type Ratio = Permill; pub type Multiplier = FixedU128; -pub trait EmergencyPriceFeeder { - fn set_emergency_price(currency_id: CurrencyId, price: Price); - fn reset_emergency_price(currency_id: CurrencyId); -} - pub type TimeStampedPrice = orml_oracle::TimestampedValue; +pub use currency::{CurrencyId, CurrencyInfo}; + #[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, RuntimeDebug, PartialOrd, Ord)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum DataProviderId { Aggregated = 0, } -pub type AuraId = sp_consensus_aura::sr25519::AuthorityId; +pub trait PriceFeeder { + fn get_price(currency_id: &CurrencyId) -> Option; +} + +pub trait EmergencyPriceFeeder { + fn set_emergency_price(currency_id: CurrencyId, price: Price); + fn reset_emergency_price(currency_id: CurrencyId); +} diff --git a/resources/types.json b/resources/types.json index 91eb71fe0..93f7fb31c 100644 --- a/resources/types.json +++ b/resources/types.json @@ -2,7 +2,7 @@ "Address": "MultiAddress", "LookupSource": "MultiAddress", "CurrencyId": { - "_enum": ["DOT", "KSM", "USDT", "xDOT", "Native"] + "_enum": ["DOT", "KSM", "USDT", "xDOT", "xKSM", "Native"] }, "CurrencyIdOf": "CurrencyId", "Amount": "i128", diff --git a/runtime/heiko/Cargo.toml b/runtime/heiko/Cargo.toml new file mode 100644 index 000000000..ff3fd0860 --- /dev/null +++ b/runtime/heiko/Cargo.toml @@ -0,0 +1,164 @@ +[package] +authors = ['Parallel Team'] +build = 'build.rs' +description = 'A decentralized lending protocol which allow users to earn "double interests" from staking and lending' +edition = '2018' +homepage = 'https://parallel.fi' +license = 'Apache' +name = 'heiko-runtime' +repository = 'https://github.com/parallel-finance/parallel' +version = '0.0.1' + +[package.metadata.docs.rs] +targets = ['x86_64-unknown-linux-gnu'] + +[dependencies] +codec = { package = 'parity-scale-codec', version = '2.0.0', default-features = false, features = ['derive'] } +cumulus-pallet-aura-ext = { git = 'https://github.com/paritytech/cumulus.git', branch = 'polkadot-v0.9.1', default-features = false } +cumulus-pallet-dmp-queue = { git = 'https://github.com/paritytech/cumulus.git', branch = 'polkadot-v0.9.1', default-features = false } +cumulus-pallet-parachain-system = { git = 'https://github.com/paritytech/cumulus.git', branch = 'polkadot-v0.9.1', default-features = false } +cumulus-pallet-xcm = { git = 'https://github.com/paritytech/cumulus.git', branch = 'polkadot-v0.9.1', default-features = false } +cumulus-pallet-xcmp-queue = { git = 'https://github.com/paritytech/cumulus.git', branch = 'polkadot-v0.9.1', default-features = false } +cumulus-primitives-core = { git = 'https://github.com/paritytech/cumulus.git', branch = 'polkadot-v0.9.1', default-features = false } +cumulus-primitives-utility = { git = 'https://github.com/paritytech/cumulus.git', branch = 'polkadot-v0.9.1', default-features = false } +frame-benchmarking = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false, optional = true } +frame-executive = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +frame-support = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +frame-system = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +frame-system-benchmarking = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false, optional = true } +frame-system-rpc-runtime-api = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +hex-literal = { version = '0.3.1', optional = true } +orml-currencies = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } +orml-oracle = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } +orml-oracle-rpc-runtime-api = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } +orml-tokens = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } +orml-traits = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } +# orml-unknown-tokens = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } +orml-utilities = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } +# orml-xcm-support = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } +# orml-xtokens = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } +pallet-aura = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-balances = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-collective = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-democracy = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-elections-phragmen = { git = 'https://github.com/paritytech/substrate.git', version = '4.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-liquidate = { path = '../../pallets/liquidate', default-features = false } +pallet-loans = { path = '../../pallets/loans', default-features = false } +pallet-loans-benchmarking = { path = '../../pallets/loans/benchmarking', default-features = false, optional = true } +pallet-membership = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-multisig = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +# pallet-ocw-oracle = { path = '../../pallets/ocw-oracle', default-features = false } +pallet-prices = { path = '../../pallets/prices', default-features = false } +pallet-scheduler = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-staking = { path = '../../pallets/staking', default-features = false } +pallet-sudo = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-timestamp = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-transaction-payment = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-treasury = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-xcm = { git = 'https://github.com/paritytech/polkadot.git', branch = 'release-v0.9.1', default-features = false } +parachain-info = { git = 'https://github.com/paritytech/cumulus.git', version = '0.1.0', branch = 'polkadot-v0.9.1', default-features = false } +polkadot-parachain = { git = 'https://github.com/paritytech/polkadot.git', branch = 'release-v0.9.1', default-features = false } +primitives = { package = 'parallel-primitives', path = '../../primitives', default-features = false } +serde = { version = '1', features = ['derive'], optional = true } +sp-api = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +sp-block-builder = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +sp-consensus-aura = { git = 'https://github.com/paritytech/substrate.git', version = '0.9.0', branch = 'polkadot-v0.9.1', default-features = false } +sp-core = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +sp-inherents = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +sp-offchain = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +sp-runtime = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +sp-session = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +sp-std = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +sp-transaction-pool = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +sp-version = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +static_assertions = '1.1.0' +xcm = { git = 'https://github.com/paritytech/polkadot.git', branch = 'release-v0.9.1', default-features = false } +xcm-builder = { git = 'https://github.com/paritytech/polkadot.git', branch = 'release-v0.9.1', default-features = false } +xcm-executor = { git = 'https://github.com/paritytech/polkadot.git', branch = 'release-v0.9.1', default-features = false } + +[build-dependencies.substrate-wasm-builder] +branch = 'polkadot-v0.9.1' +git = 'https://github.com/paritytech/substrate.git' +version = '4.0.0' + +[dev-dependencies] +sp-io = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } + +[features] +default = ['std'] +runtime-benchmarks = [ + 'sp-runtime/runtime-benchmarks', + 'frame-benchmarking', + 'frame-support/runtime-benchmarks', + 'frame-system-benchmarking', + 'hex-literal', + 'frame-system/runtime-benchmarks', + 'pallet-balances/runtime-benchmarks', + 'pallet-timestamp/runtime-benchmarks', + 'pallet-loans-benchmarking', + 'pallet-xcm/runtime-benchmarks', + 'xcm-builder/runtime-benchmarks', + 'pallet-collective/runtime-benchmarks', +] +std = [ + 'codec/std', + 'serde', + 'sp-api/std', + 'sp-std/std', + 'sp-core/std', + 'sp-runtime/std', + 'sp-version/std', + 'sp-offchain/std', + 'sp-session/std', + 'sp-block-builder/std', + 'sp-transaction-pool/std', + 'sp-inherents/std', + 'sp-consensus-aura/std', + 'frame-support/std', + 'frame-executive/std', + 'frame-system/std', + 'frame-benchmarking/std', + 'frame-system-rpc-runtime-api/std', + 'pallet-balances/std', + 'pallet-xcm/std', + 'pallet-timestamp/std', + 'pallet-sudo/std', + 'pallet-transaction-payment/std', + 'pallet-transaction-payment-rpc-runtime-api/std', + 'parachain-info/std', + 'polkadot-parachain/std', + 'cumulus-pallet-parachain-system/std', + 'cumulus-primitives-core/std', + 'cumulus-primitives-utility/std', + 'cumulus-pallet-xcmp-queue/std', + 'cumulus-pallet-dmp-queue/std', + 'cumulus-pallet-aura-ext/std', + 'cumulus-pallet-xcm/std', + 'xcm/std', + 'xcm-builder/std', + 'xcm-executor/std', + 'primitives/std', + 'pallet-loans/std', + 'pallet-staking/std', + 'pallet-liquidate/std', + 'pallet-prices/std', + 'pallet-multisig/std', + 'pallet-aura/std', + 'orml-oracle/std', + 'orml-oracle-rpc-runtime-api/std', + 'orml-currencies/std', + 'orml-tokens/std', + 'orml-traits/std', + 'orml-utilities/std', + 'pallet-treasury/std', + 'pallet-collective/std', + 'pallet-elections-phragmen/std', + 'pallet-membership/std', + 'pallet-democracy/std', + 'pallet-scheduler/std', +] +# 'pallet-ocw-oracle/std', +# 'orml-xtokens/std', +# 'orml-xcm-support/std', +# 'orml-unknown-tokens/std', diff --git a/runtime/heiko/build.rs b/runtime/heiko/build.rs new file mode 100644 index 000000000..9421a4f0e --- /dev/null +++ b/runtime/heiko/build.rs @@ -0,0 +1,23 @@ +// Copyright 2021 Parallel Finance Developer. +// This file is part of Parallel Finance. + +// 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 substrate_wasm_builder::WasmBuilder; + +fn main() { + WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() +} diff --git a/runtime/heiko/src/lib.rs b/runtime/heiko/src/lib.rs new file mode 100644 index 000000000..c359b3f2e --- /dev/null +++ b/runtime/heiko/src/lib.rs @@ -0,0 +1,1086 @@ +// Copyright 2021 Parallel Finance Developer. +// This file is part of Parallel Finance. + +// 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)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +use codec::Encode; +use frame_support::{ + traits::{All, IsInVec, LockIdentifier, U128CurrencyToVote}, + PalletId, +}; +use orml_currencies::BasicCurrencyAdapter; +use orml_traits::{parameter_type_with_key, DataProvider}; +use sp_api::impl_runtime_apis; +use sp_core::{ + u32_trait::{_1, _2, _3, _4, _5}, + OpaqueMetadata, +}; +use sp_runtime::traits::{AccountIdLookup, BlakeTwo256, Block as BlockT}; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, traits, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, KeyTypeId, Percent, SaturatedConversion, +}; +use sp_std::prelude::*; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; + +// XCM imports +use frame_support::log; +use frame_system::{ + limits::{BlockLength, BlockWeights}, + EnsureOneOf, EnsureRoot, +}; +use polkadot_parachain::primitives::Sibling; +use primitives::*; +use static_assertions::const_assert; +use xcm::v0::{Junction, Junction::*, MultiAsset, MultiLocation, MultiLocation::*, NetworkId, Xcm}; +use xcm_builder::{ + AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, + EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, + ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SovereignSignedViaLocation, + TakeWeightCredit, UsingComponents, +}; +use xcm_executor::{Config, XcmExecutor}; + +// re-exports +pub use pallet_liquidate; +pub use pallet_loans; +pub use pallet_multisig; +// pub use pallet_ocw_oracle; +pub use pallet_prices; +pub use pallet_staking; + +// A few exports that help ease life for downstream crates. +use currency::*; +pub use frame_support::{ + construct_runtime, parameter_types, + traits::{KeyOwnerProofSystem, Randomness}, + weights::{ + constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, + DispatchClass, IdentityFee, Weight, + }, + StorageValue, +}; +pub use pallet_balances::Call as BalancesCall; +pub use pallet_timestamp::Call as TimestampCall; +use pallet_xcm::XcmPassthrough; +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +pub use sp_runtime::{Perbill, Permill}; + +/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know +/// the specifics of the runtime. They can then be made to be agnostic over specific formats +/// of data like extrinsics, allowing for them to continue syncing the network through upgrades +/// to even the core data structures. +pub mod opaque { + use super::*; + + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + + /// Opaque block type. + pub type Block = generic::Block; + + pub type SessionHandlers = (); + + impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + } + } +} + +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("parallel"), + impl_name: create_runtime_str!("parallel"), + authoring_version: 1, + spec_version: 100, + impl_version: 1, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, +}; + +/// This determines the average expected block time that we are targetting. +/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. +/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked +/// up by `pallet_aura` to implement `fn slot_duration()`. +/// +/// Change this to adjust the block time. +pub const MILLISECS_PER_BLOCK: u64 = 6000; + +pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + +// Time is measured by number of blocks. +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; + +// 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks. +pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4); + +#[derive(codec::Encode, codec::Decode)] +pub enum XCMPMessage { + /// Transfer tokens to the given account from the Parachain account. + TransferToken(XAccountId, XBalance), +} + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +/// We assume that ~10% of the block weight is consumed by `on_initalize` handlers. +/// This is used to limit the maximal weight of a single extrinsic. +const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); +/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used +/// by Operational extrinsics. +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); +/// We allow for 2 seconds of compute with a 6 second average block time. +const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND; + +parameter_types! { + pub const BlockHashCount: BlockNumber = 250; + pub const Version: RuntimeVersion = VERSION; + pub RuntimeBlockLength: BlockLength = + BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Operational transactions have some extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); + // TODO: register parallel's SS58Prefix + pub const SS58Prefix: u8 = 42; +} + +// Configure FRAME pallets to include in runtime. + +impl frame_system::Config for Runtime { + /// The basic call filter to use in dispatchable. + type BaseCallFilter = (); + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type Call = Call; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The index type for blocks. + type BlockNumber = BlockNumber; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The header type. + type Header = generic::Header; + /// The ubiquitous event type. + type Event = Event; + /// The ubiquitous origin type. + type Origin = Origin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// Version of the runtime. + type Version = Version; + /// Converts a module to the index of the module in `construct_runtime!`. + /// + /// This type is being generated by `construct_runtime!`. + type PalletInfo = PalletInfo; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// The set code logic. + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; +} + +parameter_type_with_key! { + pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance { + Default::default() + }; +} + +impl orml_tokens::Config for Runtime { + type Event = Event; + type Balance = Balance; + type Amount = Amount; + type CurrencyId = CurrencyId; + type OnDust = (); + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; +} + +parameter_types! { + pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native; + + pub const LoansPalletId: PalletId = PalletId(*b"par/loan"); + pub const BlockPerYear: u128 = 5256000; +} + +impl orml_currencies::Config for Runtime { + type Event = Event; + type MultiCurrency = Tokens; + type NativeCurrency = BasicCurrencyAdapter; + type GetNativeCurrencyId = GetNativeCurrencyId; + type WeightInfo = (); +} + +impl frame_system::offchain::CreateSignedTransaction for Runtime +where + Call: From, +{ + fn create_transaction>( + call: Call, + public: ::Signer, + account: AccountId, + index: Index, + ) -> Option<( + Call, + ::SignaturePayload, + )> { + let period = BlockHashCount::get() as u64; + let current_block = System::block_number() + .saturated_into::() + .saturating_sub(1); + let tip = 0; + let extra: SignedExtra = ( + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(generic::Era::mortal(period, current_block)), + frame_system::CheckNonce::::from(index), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + ); + + let raw_payload = SignedPayload::new(call, extra) + .map_err(|e| { + log::error!("SignedPayload error: {:?}", e); + }) + .ok()?; + let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; + let address = account; + let (call, extra, _) = raw_payload.deconstruct(); + Some(( + call, + (sp_runtime::MultiAddress::Id(address), signature, extra), + )) + } +} + +impl frame_system::offchain::SigningTypes for Runtime { + type Public = ::Signer; + type Signature = Signature; +} + +impl frame_system::offchain::SendTransactionTypes for Runtime +where + Call: From, +{ + type OverarchingCall = Call; + type Extrinsic = UncheckedExtrinsic; +} + +// parameter_types! { +// pub const PricePrecision: u8 = 18; +// } + +// impl pallet_ocw_oracle::Config for Runtime { +// type AuthorityId = pallet_ocw_oracle::crypto::TestAuthId; +// type Call = Call; +// type Event = Event; +// type PricePrecision = PricePrecision; +// } + +impl pallet_loans::Config for Runtime { + type Event = Event; + type Currency = Currencies; + type PalletId = LoansPalletId; + type BlockPerYear = BlockPerYear; + type PriceFeeder = Prices; + type ReserveOrigin = EnsureRoot; + type UpdateOrigin = EnsureRoot; + type WeightInfo = pallet_loans::weights::SubstrateWeight; +} + +parameter_types! { + pub const StakingPalletId: PalletId = PalletId(*b"par/stak"); + pub const StakingCurrency: CurrencyId = CurrencyId::KSM; + pub const LiquidCurrency: CurrencyId = CurrencyId::xKSM; + pub const MaxWithdrawAmount: Balance = 1000; + pub const MaxAccountProcessingUnstake: u32 = 5; +} + +impl pallet_staking::Config for Runtime { + type Event = Event; + type Currency = Currencies; + type PalletId = StakingPalletId; + type StakingCurrency = StakingCurrency; + type LiquidCurrency = LiquidCurrency; + type WithdrawOrigin = EnsureRoot; + type MaxWithdrawAmount = MaxWithdrawAmount; + type MaxAccountProcessingUnstake = MaxAccountProcessingUnstake; +} + +impl pallet_liquidate::Config for Runtime { + type AuthorityId = pallet_liquidate::crypto::TestAuthId; + type Call = Call; + type Event = Event; + type PriceFeeder = Prices; +} + +parameter_types! { + pub const MinimumPeriod: u64 = SLOT_DURATION / 2; +} + +impl pallet_timestamp::Config for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +impl pallet_aura::Config for Runtime { + type AuthorityId = AuraId; +} + +impl cumulus_pallet_aura_ext::Config for Runtime {} + +parameter_types! { + pub const ExistentialDeposit: u128 = 500; + pub const MaxLocks: u32 = 50; +} + +impl pallet_balances::Config for Runtime { + type MaxLocks = MaxLocks; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = pallet_balances::weights::SubstrateWeight; +} + +parameter_types! { + pub const TransactionByteFee: Balance = 1; +} + +impl pallet_transaction_payment::Config for Runtime { + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; + type TransactionByteFee = TransactionByteFee; + type WeightToFee = IdentityFee; + type FeeMultiplierUpdate = (); +} + +impl pallet_sudo::Config for Runtime { + type Event = Event; + type Call = Call; +} + +/// No local origins on this chain are allowed to dispatch XCM sends/executions. +/// TODO: LocalOrigins +/// https://github.com/paritytech/statemint/blob/master/runtime/statemine/src/lib.rs +pub type LocalOriginToLocation = (); + +/// The means for routing XCM messages which are not for local execution into the right message +/// queues. +pub type XcmRouter = ( + // Two routers - use UMP to communicate with the relay chain: + cumulus_primitives_utility::ParentAsUmp, + // ..and XCMP to communicate with the sibling chains. + XcmpQueue, +); + +impl pallet_xcm::Config for Runtime { + type Event = Event; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = All<(MultiLocation, Xcm)>; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = All<(MultiLocation, Vec)>; + type Weigher = FixedWeightBounds; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type Event = Event; + type XcmExecutor = XcmExecutor; +} + +impl cumulus_pallet_xcmp_queue::Config for Runtime { + type Event = Event; + type XcmExecutor = XcmExecutor; + type ChannelInfo = ParachainSystem; +} + +impl cumulus_pallet_dmp_queue::Config for Runtime { + type Event = Event; + type XcmExecutor = XcmExecutor; + type ExecuteOverweightOrigin = frame_system::EnsureRoot; +} + +parameter_types! { + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4; + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4; +} + +impl cumulus_pallet_parachain_system::Config for Runtime { + type Event = Event; + type OnValidationData = (); + type SelfParaId = ParachainInfo; + type DmpMessageHandler = DmpQueue; + type OutboundXcmpMessageSource = XcmpQueue; + type XcmpMessageHandler = XcmpQueue; + type ReservedXcmpWeight = ReservedXcmpWeight; + type ReservedDmpWeight = ReservedDmpWeight; +} + +impl parachain_info::Config for Runtime {} + +parameter_types! { + pub const RelayLocation: MultiLocation = MultiLocation::X1(Junction::Parent); + pub const RelayNetwork: NetworkId = NetworkId::Kusama; + pub RelayChainOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); + pub Ancestry: MultiLocation = X1(Parachain(ParachainInfo::parachain_id().into())); +} + +/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the default `AccountId`. + ParentIsDefault, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // Straight up local `AccountId32` origins just alias directly to `AccountId`. + AccountId32Aliases, +); + +/// Means for transacting assets on this chain. +pub type LocalAssetTransactor = CurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching the given location or name: + IsConcrete, + // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We don't track any teleports. + (), +>; + +/// 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 +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToTransactDispatchOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // recognised. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognised. + SiblingParachainAsNative, + // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a + // transaction from the Root origin. + ParentAsSuperuser, + // Native signed account converter; this just converts an `AccountId32` origin into a normal + // `Origin::Signed` origin of the same 32-byte value. + SignedAccountId32AsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + XcmPassthrough, +); + +parameter_types! { + pub UnitWeightCost: Weight = 1_000; +} + +parameter_types! { + // 1_000_000_000_000 => 1 unit of asset for 1 unit of Weight. + // TODO: Should take the actual weight price. This is just 1_000 ROC per second of weight. + pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::X1(Junction::Parent), 1_000); + pub AllowUnpaidFrom: Vec = vec![ MultiLocation::X1(Junction::Parent) ]; +} + +pub type Barrier = ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom>, + AllowUnpaidExecutionFrom>, // <- Parent gets free execution +); + +pub struct XcmConfig; +impl Config for XcmConfig { + type Call = Call; + type XcmSender = XcmRouter; + // How to withdraw and deposit an asset. + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = NativeAsset; + type IsTeleporter = NativeAsset; // <- should be enough to allow teleportation of ROC + type LocationInverter = LocationInverter; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = UsingComponents, RelayLocation, AccountId, Balances, ()>; + type ResponseHandler = (); // Don't handle responses for now. +} + +parameter_types! { + pub const MinimumCount: u32 = 1; + pub const ExpiresIn: Moment = 1000 * 60 * 60; // 60 mins + pub ZeroAccountId: AccountId = AccountId::from([0u8; 32]); +} + +type ParallelDataProvider = orml_oracle::Instance1; +impl orml_oracle::Config for Runtime { + type Event = Event; + type OnNewData = (); + type CombineData = + orml_oracle::DefaultCombineData; + type Time = Timestamp; + type OracleKey = CurrencyId; + type OracleValue = Price; + type RootOperatorAccountId = ZeroAccountId; + type WeightInfo = (); +} + +pub type TimeStampedPrice = orml_oracle::TimestampedValue; +pub struct AggregatedDataProvider; +impl DataProvider for AggregatedDataProvider { + fn get(key: &CurrencyId) -> Option { + Oracle::get(key) + } +} + +impl pallet_prices::Config for Runtime { + type Event = Event; + type Source = AggregatedDataProvider; + type FeederOrigin = EnsureRoot; +} + +pub mod currency { + type Balance = u128; + pub const MILLICENTS: Balance = 1_000_000_000; + pub const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent. + pub const DOLLARS: Balance = 100 * CENTS; + + pub const fn deposit(items: u32, bytes: u32) -> Balance { + items as Balance * 15 * CENTS + (bytes as Balance) * 6 * CENTS + } +} + +parameter_types! { + // One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes. + pub const DepositBase: Balance = currency::deposit(1, 88); + // Additional storage item size of 32 bytes. + pub const DepositFactor: Balance = currency::deposit(0, 32); + pub const MaxSignatories: u16 = 100; +} + +impl pallet_multisig::Config for Runtime { + type Event = Event; + type Call = Call; + type Currency = Balances; + type DepositBase = DepositBase; + type DepositFactor = DepositFactor; + type MaxSignatories = MaxSignatories; + type WeightInfo = (); +} + +parameter_types! { + pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; + pub const VotingPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; + pub const FastTrackVotingPeriod: BlockNumber = 3 * 24 * 60 * MINUTES; + pub const InstantAllowed: bool = true; + pub const MinimumDeposit: Balance = 100 * DOLLARS; + pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES; + pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; + // One cent: $10,000 / MB + pub const PreimageByteDeposit: Balance = 1 * CENTS; + pub const MaxVotes: u32 = 100; + pub const MaxProposals: u32 = 100; +} + +impl pallet_democracy::Config for Runtime { + type Proposal = Call; + type Event = Event; + type Currency = Balances; + type EnactmentPeriod = EnactmentPeriod; + type LaunchPeriod = LaunchPeriod; + type VotingPeriod = VotingPeriod; + type MinimumDeposit = MinimumDeposit; + /// A straight majority of the council can decide what their next motion is. + type ExternalOrigin = + pallet_collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>; + /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. + type ExternalMajorityOrigin = + pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>; + /// A unanimous council can have the next scheduled referendum be a straight default-carries + /// (NTB) vote. + type ExternalDefaultOrigin = + pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, CouncilCollective>; + /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote + /// be tabled immediately and with a shorter voting/enactment period. + type FastTrackOrigin = + pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, TechnicalCollective>; + type InstantOrigin = + pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, TechnicalCollective>; + type InstantAllowed = InstantAllowed; + type FastTrackVotingPeriod = FastTrackVotingPeriod; + // To cancel a proposal which has been passed, 2/3 of the council must agree to it. + type CancellationOrigin = + pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilCollective>; + // To cancel a proposal before it has been passed, the technical committee must be unanimous or + // Root must agree. + type CancelProposalOrigin = EnsureOneOf< + AccountId, + EnsureRoot, + pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, TechnicalCollective>, + >; + type BlacklistOrigin = EnsureRoot; + // Any single technical committee member may veto a coming council proposal, however they can + // only do it once and it lasts only for the cool-off period. + type VetoOrigin = pallet_collective::EnsureMember; + type CooloffPeriod = CooloffPeriod; + type PreimageByteDeposit = PreimageByteDeposit; + type OperationalPreimageOrigin = pallet_collective::EnsureMember; + type Slash = Treasury; + type Scheduler = Scheduler; + type PalletsOrigin = OriginCaller; + type MaxVotes = MaxVotes; + type WeightInfo = pallet_democracy::weights::SubstrateWeight; + type MaxProposals = MaxProposals; +} + +parameter_types! { + pub const CouncilMotionDuration: BlockNumber = 5 * DAYS; + pub const CouncilMaxProposals: u32 = 100; + pub const CouncilMaxMembers: u32 = 100; +} + +type CouncilCollective = pallet_collective::Instance1; +impl pallet_collective::Config for Runtime { + type Origin = Origin; + type Proposal = Call; + type Event = Event; + type MotionDuration = CouncilMotionDuration; + type MaxProposals = CouncilMaxProposals; + type MaxMembers = CouncilMaxMembers; + type DefaultVote = pallet_collective::PrimeDefaultVote; + type WeightInfo = pallet_collective::weights::SubstrateWeight; +} + +parameter_types! { + pub const CandidacyBond: Balance = 10 * DOLLARS; + // 1 storage item created, key size is 32 bytes, value size is 16+16. + pub const VotingBondBase: Balance = deposit(1, 64); + // additional data per vote is 32 bytes (account id). + pub const VotingBondFactor: Balance = deposit(0, 32); + pub const TermDuration: BlockNumber = 7 * DAYS; + pub const DesiredMembers: u32 = 13; + pub const DesiredRunnersUp: u32 = 7; + pub const ElectionsPhragmenPalletId: LockIdentifier = *b"phrelect"; +} + +// Make sure that there are no more than `MaxMembers` members elected via elections-phragmen. +const_assert!(DesiredMembers::get() <= CouncilMaxMembers::get()); + +impl pallet_elections_phragmen::Config for Runtime { + type Event = Event; + type PalletId = ElectionsPhragmenPalletId; + type Currency = Balances; + type ChangeMembers = Council; + // NOTE: this implies that council's genesis members cannot be set directly and must come from + // this module. + type InitializeMembers = Council; + type CurrencyToVote = U128CurrencyToVote; + type CandidacyBond = CandidacyBond; + type VotingBondBase = VotingBondBase; + type VotingBondFactor = VotingBondFactor; + type LoserCandidate = (); + type KickedMember = (); + type DesiredMembers = DesiredMembers; + type DesiredRunnersUp = DesiredRunnersUp; + type TermDuration = TermDuration; + type WeightInfo = pallet_elections_phragmen::weights::SubstrateWeight; +} + +parameter_types! { + pub const TechnicalMotionDuration: BlockNumber = 5 * DAYS; + pub const TechnicalMaxProposals: u32 = 100; + pub const TechnicalMaxMembers: u32 = 100; +} + +type TechnicalCollective = pallet_collective::Instance2; +impl pallet_collective::Config for Runtime { + type Origin = Origin; + type Proposal = Call; + type Event = Event; + type MotionDuration = TechnicalMotionDuration; + type MaxProposals = TechnicalMaxProposals; + type MaxMembers = TechnicalMaxMembers; + type DefaultVote = pallet_collective::PrimeDefaultVote; + type WeightInfo = pallet_collective::weights::SubstrateWeight; +} + +type EnsureRootOrHalfCouncil = EnsureOneOf< + AccountId, + EnsureRoot, + pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>, +>; +impl pallet_membership::Config for Runtime { + type Event = Event; + type AddOrigin = EnsureRootOrHalfCouncil; + type RemoveOrigin = EnsureRootOrHalfCouncil; + type SwapOrigin = EnsureRootOrHalfCouncil; + type ResetOrigin = EnsureRootOrHalfCouncil; + type PrimeOrigin = EnsureRootOrHalfCouncil; + type MembershipInitialized = TechnicalCommittee; + type MembershipChanged = TechnicalCommittee; + type MaxMembers = TechnicalMaxMembers; + type WeightInfo = pallet_membership::weights::SubstrateWeight; +} + +parameter_types! { + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * + RuntimeBlockWeights::get().max_block; + pub const MaxScheduledPerBlock: u32 = 50; +} + +impl pallet_scheduler::Config for Runtime { + type Event = Event; + type Origin = Origin; + type PalletsOrigin = OriginCaller; + type Call = Call; + type MaximumWeight = MaximumSchedulerWeight; + type ScheduleOrigin = EnsureRoot; + type MaxScheduledPerBlock = MaxScheduledPerBlock; + type WeightInfo = pallet_scheduler::weights::SubstrateWeight; +} + +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const ProposalBondMinimum: Balance = 1 * DOLLARS; + pub const SpendPeriod: BlockNumber = 1 * DAYS; + pub const Burn: Permill = Permill::from_percent(50); + pub const TipCountdown: BlockNumber = 1 * DAYS; + pub const TipFindersFee: Percent = Percent::from_percent(20); + pub const TipReportDepositBase: Balance = 1 * DOLLARS; + pub const TreasuryPalletId: PalletId = PalletId(*b"py/trsry"); + pub const MaxApprovals: u32 = 100; +} + +impl pallet_treasury::Config for Runtime { + type PalletId = TreasuryPalletId; + type Currency = Balances; + type ApproveOrigin = EnsureOneOf< + AccountId, + EnsureRoot, + pallet_collective::EnsureProportionAtLeast<_3, _5, AccountId, CouncilCollective>, + >; + type RejectOrigin = EnsureOneOf< + AccountId, + EnsureRoot, + pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>, + >; + type Event = Event; + type OnSlash = (); + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ProposalBondMinimum; + type SpendPeriod = SpendPeriod; + type Burn = Burn; + type BurnDestination = (); + type SpendFunds = (); + type WeightInfo = pallet_treasury::weights::SubstrateWeight; + type MaxApprovals = MaxApprovals; +} + +// Create the runtime by composing the FRAME pallets that were previously configured. +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = opaque::Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Storage, Config, Event}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + Sudo: pallet_sudo::{Pallet, Call, Storage, Config, Event}, + ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event, ValidateUnsigned}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, + ParachainInfo: parachain_info::{Pallet, Storage, Config}, + XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event}, + DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event}, + PolkadotXcm: pallet_xcm::{Pallet, Call, Event, Origin}, + CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event, Origin}, + Currencies: orml_currencies::{Pallet, Call, Event}, + Tokens: orml_tokens::{Pallet, Storage, Event, Config}, + Aura: pallet_aura::{Pallet, Config}, + AuraExt: cumulus_pallet_aura_ext::{Pallet, Config}, + // OcwOracle: pallet_ocw_oracle::{Pallet, Call, Storage, Event, ValidateUnsigned}, + Oracle: orml_oracle::::{Pallet, Storage, Call, Config, Event}, + Loans: pallet_loans::{Pallet, Call, Storage, Event, Config}, + Staking: pallet_staking::{Pallet, Call, Storage, Event, Config}, + Liquidate: pallet_liquidate::{Pallet, Call, Event}, + Prices: pallet_prices::{Pallet, Storage, Call, Event}, + Multisig: pallet_multisig::{Pallet, Call, Storage, Event}, + Democracy: pallet_democracy::{Pallet, Call, Storage, Config, Event}, + Council: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config}, + TechnicalCommittee: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config}, + Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event}, + Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event}, + Elections: pallet_elections_phragmen::{Pallet, Call, Storage, Event, Config}, + TechnicalMembership: pallet_membership::::{Pallet, Call, Storage, Event, Config}, + } +); + +/// The address format for describing accounts. +pub type Address = sp_runtime::MultiAddress; +/// Block header type as expected by this runtime. +pub type Header = generic::Header; +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +/// The payload being signed in transactions. +pub type SignedPayload = generic::SignedPayload; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = generic::CheckedExtrinsic; +/// Executive: handles dispatch to the various modules. +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPallets, +>; + +impl_runtime_apis! { + impl sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> sp_consensus_aura::SlotDuration { + sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) + } + + fn authorities() -> Vec { + Aura::authorities() + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(seed: Option>) -> Vec { + opaque::SessionKeys::generate(seed) + } + + fn decode_session_keys( + encoded: Vec, + ) -> Option, KeyTypeId)>> { + opaque::SessionKeys::decode_into_raw_public_keys(&encoded) + } + } + + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + Runtime::metadata().into() + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_block() + } + + fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::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 for Runtime { + fn validate_transaction( + source: TransactionSource, + tx: ::Extrinsic, + ) -> TransactionValidity { + Executive::validate_transaction(source, tx) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Index { + System::account_nonce(account) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { + fn query_info( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + fn query_fee_details( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment::FeeDetails { + TransactionPayment::query_fee_details(uxt, len) + } + } + + impl orml_oracle_rpc_runtime_api::OracleApi< + Block, + DataProviderId, + CurrencyId, + TimeStampedPrice, + > for Runtime { + fn get_value(provider_id: DataProviderId, key: CurrencyId) -> Option { + match provider_id { + DataProviderId::Aggregated => Oracle::get_no_op(&key) + } + } + + fn get_all_values(provider_id: DataProviderId) -> Vec<(CurrencyId, Option)> { + match provider_id { + DataProviderId::Aggregated => Oracle::get_all_values() + } + } + } + + #[cfg(feature = "runtime-benchmarks")] + impl frame_benchmarking::Benchmark for Runtime { + fn dispatch_benchmark( + config: frame_benchmarking::BenchmarkConfig + ) -> Result, sp_runtime::RuntimeString> { + use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; + + use pallet_loans_benchmarking::Pallet as LoansBench; + use frame_system_benchmarking::Pallet as SystemBench; + + impl pallet_loans_benchmarking::Config for Runtime {} + impl frame_system_benchmarking::Config for Runtime {} + + let whitelist: Vec = 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(), + ]; + + let mut batches = Vec::::new(); + let params = (&config, &whitelist); + + add_benchmark!(params, batches, frame_system, SystemBench::); + add_benchmark!(params, batches, pallet_balances, Balances); + add_benchmark!(params, batches, pallet_timestamp, Timestamp); + add_benchmark!(params, batches, pallet_loans, LoansBench::); + + if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } + Ok(batches) + } + } +} + +cumulus_pallet_parachain_system::register_validate_block!( + Runtime, + cumulus_pallet_aura_ext::BlockExecutor::, +); diff --git a/runtime/parallel/Cargo.toml b/runtime/parallel/Cargo.toml index 872a5b3d9..3e1b1a5b3 100644 --- a/runtime/parallel/Cargo.toml +++ b/runtime/parallel/Cargo.toml @@ -37,20 +37,20 @@ orml-traits = { git = 'https://github.com/open-web3-stack/op orml-utilities = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } # orml-xcm-support = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } # orml-xtokens = { git = 'https://github.com/open-web3-stack/open-runtime-module-library.git', default-features = false } -pallet-aura = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } -pallet-balances = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } -pallet-collective = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } -pallet-democracy = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } -pallet-elections-phragmen = { git = 'https://github.com/paritytech/substrate.git', version = '4.0.0', branch = 'polkadot-v0.9.1', default-features = false } -pallet-liquidate = { path = '../../pallets/liquidate', default-features = false } -pallet-loans = { path = '../../pallets/loans', default-features = false } -pallet-loans-benchmarking = { path = '../../pallets/loans/benchmarking', default-features = false, optional = true } -pallet-membership = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } -pallet-multisig = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-aura = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-balances = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-collective = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-democracy = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-elections-phragmen = { git = 'https://github.com/paritytech/substrate.git', version = '4.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-liquidate = { path = '../../pallets/liquidate', default-features = false } +pallet-loans = { path = '../../pallets/loans', default-features = false } +pallet-loans-benchmarking = { path = '../../pallets/loans/benchmarking', default-features = false, optional = true } +pallet-membership = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +pallet-multisig = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } # pallet-ocw-oracle = { path = '../../pallets/ocw-oracle', default-features = false } pallet-prices = { path = '../../pallets/prices', default-features = false } +pallet-scheduler = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } pallet-staking = { path = '../../pallets/staking', default-features = false } -pallet-scheduler = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } pallet-sudo = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } pallet-timestamp = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } pallet-transaction-payment = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } @@ -83,7 +83,7 @@ git = 'https://github.com/paritytech/substrate.git' version = '4.0.0' [dev-dependencies] -sp-io = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } +sp-io = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } [features] default = ['std'] @@ -99,6 +99,7 @@ runtime-benchmarks = [ 'pallet-loans-benchmarking', 'pallet-xcm/runtime-benchmarks', 'xcm-builder/runtime-benchmarks', + 'pallet-collective/runtime-benchmarks', ] std = [ 'codec/std', @@ -156,7 +157,8 @@ std = [ 'pallet-membership/std', 'pallet-democracy/std', 'pallet-scheduler/std', - # 'orml-unknown-tokens/std', - # 'orml-xtokens/std', - # 'orml-xcm-support/std', -] # 'pallet-ocw-oracle/std', +] +# 'pallet-ocw-oracle/std', +# 'orml-unknown-tokens/std', +# 'orml-xtokens/std', +# 'orml-xcm-support/std', diff --git a/runtime/parallel/src/lib.rs b/runtime/parallel/src/lib.rs index e3b6ff4a7..072d2bf44 100644 --- a/runtime/parallel/src/lib.rs +++ b/runtime/parallel/src/lib.rs @@ -261,6 +261,7 @@ parameter_types! { pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native; pub const LoansPalletId: PalletId = PalletId(*b"par/loan"); + pub const BlockPerYear: u128 = 5256000; } impl orml_currencies::Config for Runtime { @@ -342,6 +343,7 @@ impl pallet_loans::Config for Runtime { type Event = Event; type Currency = Currencies; type PalletId = LoansPalletId; + type BlockPerYear = BlockPerYear; type PriceFeeder = Prices; type ReserveOrigin = EnsureRoot; type UpdateOrigin = EnsureRoot; @@ -598,7 +600,7 @@ pub type TimeStampedPrice = orml_oracle::TimestampedValue; pub struct AggregatedDataProvider; impl DataProvider for AggregatedDataProvider { fn get(key: &CurrencyId) -> Option { - ParallelOracle::get(key) + Oracle::get(key) } } @@ -868,7 +870,7 @@ construct_runtime!( Aura: pallet_aura::{Pallet, Config}, AuraExt: cumulus_pallet_aura_ext::{Pallet, Config}, // OcwOracle: pallet_ocw_oracle::{Pallet, Call, Storage, Event, ValidateUnsigned}, - ParallelOracle: orml_oracle::::{Pallet, Storage, Call, Config, Event}, + Oracle: orml_oracle::::{Pallet, Storage, Call, Config, Event}, Loans: pallet_loans::{Pallet, Call, Storage, Event, Config}, Staking: pallet_staking::{Pallet, Call, Storage, Event, Config}, Liquidate: pallet_liquidate::{Pallet, Call, Event}, @@ -1027,13 +1029,13 @@ impl_runtime_apis! { > for Runtime { fn get_value(provider_id: DataProviderId, key: CurrencyId) -> Option { match provider_id { - DataProviderId::Aggregated => ParallelOracle::get_no_op(&key) + DataProviderId::Aggregated => Oracle::get_no_op(&key) } } fn get_all_values(provider_id: DataProviderId) -> Vec<(CurrencyId, Option)> { match provider_id { - DataProviderId::Aggregated => ParallelOracle::get_all_values() + DataProviderId::Aggregated => Oracle::get_all_values() } } } diff --git a/runtime/vanilla/Cargo.toml b/runtime/vanilla/Cargo.toml index c0a00cc7c..05761fc80 100644 --- a/runtime/vanilla/Cargo.toml +++ b/runtime/vanilla/Cargo.toml @@ -18,10 +18,10 @@ git = 'https://github.com/paritytech/substrate.git' version = '4.0.0' [dependencies] -codec = { package = 'parity-scale-codec', version = '2.0.0', default-features = false, features = ['derive'] } -hex-literal = { version = '0.3.1', optional = true } -serde = { version = '1', features = ['derive'], optional = true } -static_assertions = '1.1.0' +codec = { package = 'parity-scale-codec', version = '2.0.0', default-features = false, features = ['derive'] } +hex-literal = { version = '0.3.1', optional = true } +serde = { version = '1', features = ['derive'], optional = true } +static_assertions = '1.1.0' # local dependencies pallet-liquidate = { path = '../../pallets/liquidate', default-features = false } @@ -73,7 +73,6 @@ sp-transaction-pool = { git = 'https://github.com/parityt sp-version = { git = 'https://github.com/paritytech/substrate.git', version = '3.0.0', branch = 'polkadot-v0.9.1', default-features = false } [features] -default = ['std'] runtime-benchmarks = [ 'hex-literal', 'frame-benchmarking', @@ -84,6 +83,7 @@ runtime-benchmarks = [ 'pallet-timestamp/runtime-benchmarks', 'sp-runtime/runtime-benchmarks', 'pallet-loans-benchmarking', + 'pallet-collective/runtime-benchmarks', ] std = [ 'codec/std', @@ -128,4 +128,6 @@ std = [ 'pallet-membership/std', 'pallet-democracy/std', 'pallet-scheduler/std', -] # 'pallet-ocw-oracle/std', +] +# 'pallet-ocw-oracle/std', +default = ['std'] diff --git a/runtime/vanilla/src/lib.rs b/runtime/vanilla/src/lib.rs index 2ca60f603..f8b4cabf1 100644 --- a/runtime/vanilla/src/lib.rs +++ b/runtime/vanilla/src/lib.rs @@ -275,7 +275,9 @@ impl orml_tokens::Config for Runtime { parameter_types! { pub const GetNativeCurrencyId: CurrencyId = CurrencyId::Native; + pub const LoansPalletId: PalletId = PalletId(*b"par/loan"); + pub const BlockPerYear: u128 = 5256000; } impl orml_currencies::Config for Runtime { @@ -290,6 +292,7 @@ impl pallet_loans::Config for Runtime { type Event = Event; type Currency = Currencies; type PalletId = LoansPalletId; + type BlockPerYear = BlockPerYear; type PriceFeeder = Prices; type ReserveOrigin = EnsureRoot; type UpdateOrigin = EnsureRoot; @@ -416,7 +419,7 @@ pub type TimeStampedPrice = orml_oracle::TimestampedValue; pub struct AggregatedDataProvider; impl DataProvider for AggregatedDataProvider { fn get(key: &CurrencyId) -> Option { - VanillaOracle::get(key) + Oracle::get(key) } } @@ -685,7 +688,7 @@ construct_runtime!( Loans: pallet_loans::{Pallet, Call, Storage, Event, Config}, Staking: pallet_staking::{Pallet, Call, Storage, Event, Config}, // OcwOracle: pallet_ocw_oracle::{Pallet, Call, Storage, Event, ValidateUnsigned}, - VanillaOracle: orml_oracle::::{Pallet, Storage, Call, Config, Event}, + Oracle: orml_oracle::::{Pallet, Storage, Call, Config, Event}, Liquidate: pallet_liquidate::{Pallet, Call, Event}, Prices: pallet_prices::{Pallet, Storage, Call, Event}, Democracy: pallet_democracy::{Pallet, Call, Storage, Config, Event}, @@ -869,13 +872,13 @@ impl_runtime_apis! { > for Runtime { fn get_value(provider_id: DataProviderId, key: CurrencyId) -> Option { match provider_id { - DataProviderId::Aggregated => VanillaOracle::get_no_op(&key) + DataProviderId::Aggregated => Oracle::get_no_op(&key) } } fn get_all_values(provider_id: DataProviderId) -> Vec<(CurrencyId, Option)> { match provider_id { - DataProviderId::Aggregated => VanillaOracle::get_all_values() + DataProviderId::Aggregated => Oracle::get_all_values() } } }