From b6eb261c75eb7bd34ea93d1bef2a75b965b994b0 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Tue, 10 Oct 2023 17:13:32 +0200 Subject: [PATCH 01/27] Add handle and base env structure --- Cargo.lock | 2 + runtime/integration-tests/Cargo.toml | 2 + .../src/generic/cases/example.rs | 29 +- .../src/generic/envs/fudge_env.rs | 52 +++- .../src/generic/envs/fudge_env/handle.rs | 266 ++++++++++++++++++ .../src/generic/envs/runtime_env.rs | 2 + runtime/integration-tests/src/generic/mod.rs | 91 +++++- 7 files changed, 432 insertions(+), 12 deletions(-) create mode 100644 runtime/integration-tests/src/generic/envs/fudge_env/handle.rs diff --git a/Cargo.lock b/Cargo.lock index de36be2b53..e4c5166fbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11133,6 +11133,7 @@ dependencies = [ "polkadot-runtime-parachains", "rococo-runtime", "runtime-common", + "sc-block-builder", "sc-client-api", "sc-executor", "sc-service", @@ -11149,6 +11150,7 @@ dependencies = [ "sp-std", "sp-timestamp", "sp-tracing", + "sp-transaction-pool", "tokio", "tracing-subscriber", "xcm", diff --git a/runtime/integration-tests/Cargo.toml b/runtime/integration-tests/Cargo.toml index 6db66868ee..cbe7df6145 100644 --- a/runtime/integration-tests/Cargo.toml +++ b/runtime/integration-tests/Cargo.toml @@ -36,6 +36,7 @@ pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } #sp-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } sp-consensus-slots = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } @@ -50,6 +51,7 @@ fp-self-contained = { git = "https://github.com/PureStake/frontier", branch = "m ## Substrate-Client node-primitives = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } +sc-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } #sc-consensus-uncles = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } sc-service = { git = "https://github.com/paritytech/substrate", features = ["rocksdb", "test-helpers"], branch = "polkadot-v0.9.38" } diff --git a/runtime/integration-tests/src/generic/cases/example.rs b/runtime/integration-tests/src/generic/cases/example.rs index 28ccf9d1bc..484c15422d 100644 --- a/runtime/integration-tests/src/generic/cases/example.rs +++ b/runtime/integration-tests/src/generic/cases/example.rs @@ -4,7 +4,10 @@ use frame_support::traits::Get; use crate::{ generic::{ environment::{Blocks, Env}, - envs::runtime_env::RuntimeEnv, + envs::{ + fudge_env::{FudgeEnv, FudgeSupport}, + runtime_env::RuntimeEnv, + }, runtime::Runtime, utils::genesis::Genesis, }, @@ -16,6 +19,8 @@ fn transfer_balance() { const FOR_FEES: Balance = 1 * CFG; // Set up all GenesisConfig for your initial state + // You can choose `RuntimeEnv` by `FudgeEnv` to make it working with fudge + // environment. let mut env = RuntimeEnv::::from_storage( Genesis::default() .add(pallet_aura::GenesisConfig:: { @@ -106,10 +111,26 @@ fn check_fee() { }); } +fn using_fudge() { + let _env = FudgeEnv::::from_storage( + Genesis::default() + .add(pallet_aura::GenesisConfig:: { + authorities: vec![AuraId::from(Keyring::Charlie.public())], + }) + .add(pallet_balances::GenesisConfig:: { + balances: vec![(Keyring::Alice.to_account_id(), 1 * CFG)], + }) + .storage(), + ); + + //TODO +} + // Generate tests for all runtimes -crate::test_for_runtimes!((development, altair, centrifuge), transfer_balance); -crate::test_for_all_runtimes!(call_api); -crate::test_for_all_runtimes!(check_fee); +crate::test_for_runtimes!([development, altair, centrifuge], transfer_balance); +crate::test_for_runtimes!(all, call_api); +crate::test_for_runtimes!(all, check_fee); +crate::test_for_runtimes!([development], using_fudge); // Output: for `cargo test -p runtime-integration-tests transfer_balance` // running 6 tests diff --git a/runtime/integration-tests/src/generic/envs/fudge_env.rs b/runtime/integration-tests/src/generic/envs/fudge_env.rs index 882aa285f2..cb441820b5 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env.rs @@ -1 +1,51 @@ -// TODO: implement generic::env::Env for an environment using fudge +pub mod handle; + +use handle::FudgeHandle; +use sp_runtime::{DispatchResult, Storage}; + +use crate::{ + generic::{ + environment::{Blocks, Env}, + runtime::Runtime, + }, + utils::accounts::Keyring, +}; + +/// Trait that represent the entity has Fudge support +pub trait FudgeSupport { + /// Type to interact with fudge chains + type FudgeHandle: FudgeHandle; +} + +/// Evironment that uses fudge to interact with the runtime +pub struct FudgeEnv { + handle: T::FudgeHandle, +} + +impl Env for FudgeEnv { + fn from_storage(storage: Storage) -> Self { + Self { + handle: T::FudgeHandle::build(Storage::default(), storage), + } + } + + fn submit(&mut self, _who: Keyring, _call: impl Into) -> DispatchResult { + // Access to the handle to do everything + todo!() + } + + fn pass(&mut self, _blocks: Blocks) { + // Access to the handle to do everything + todo!() + } + + fn state_mut(&mut self, _f: impl FnOnce() -> R) -> R { + // Access to the handle to do everything + todo!() + } + + fn state(&self, _f: impl FnOnce() -> R) -> R { + // Access to the handle to do everything + todo!() + } +} diff --git a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs new file mode 100644 index 0000000000..3e57d2ccb7 --- /dev/null +++ b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs @@ -0,0 +1,266 @@ +use std::sync::Arc; + +use cfg_primitives::{AuraId, BlockNumber}; +use frame_support::traits::GenesisBuild; +use fudge::{ + digest::{DigestCreator as DigestCreatorT, DigestProvider, FudgeAuraDigest, FudgeBabeDigest}, + inherent::{ + CreateInherentDataProviders, FudgeDummyInherentRelayParachain, FudgeInherentParaParachain, + FudgeInherentTimestamp, + }, + state::StateProvider, + TWasmExecutor, +}; +use polkadot_core_primitives::{Block as RelayBlock, Header as RelayHeader}; +use polkadot_parachain::primitives::Id as ParaId; +use polkadot_primitives::runtime_api::ParachainHost; +use sc_block_builder::BlockBuilderApi; +use sc_client_api::Backend; +use sc_service::{TFullBackend, TFullClient}; +use sp_api::{ApiExt, BlockT, ConstructRuntimeApi}; +use sp_consensus_aura::{sr25519::AuthorityId, AuraApi}; +use sp_consensus_babe::BabeApi; +use sp_consensus_slots::SlotDuration; +use sp_core::H256; +use sp_runtime::Storage; +use sp_transaction_pool::runtime_api::TaggedTransactionQueue; +use tokio::runtime::Handle; + +use crate::{generic::runtime::Runtime, utils::time::START_DATE}; + +type InherentCreator = Box< + dyn CreateInherentDataProviders< + Block, + (), + InherentDataProviders = ( + FudgeInherentTimestamp, + InherentDataProvider, + InherentParachain, + ), + >, +>; + +pub type RelayInherentCreator = InherentCreator< + RelayBlock, + FudgeDummyInherentRelayParachain, + sp_consensus_babe::inherents::InherentDataProvider, +>; + +pub type ParachainInherentCreator = InherentCreator< + Block, + FudgeInherentParaParachain, + sp_consensus_aura::inherents::InherentDataProvider, +>; + +pub type DigestCreator = Box + Send + Sync>; + +pub type RelaychainBuilder = fudge::RelaychainBuilder< + RelayBlock, + RuntimeApi, + Runtime, + RelayInherentCreator, + DigestCreator, +>; + +pub type ParachainBuilder = fudge::ParachainBuilder< + Block, + RuntimeApi, + ParachainInherentCreator, + DigestCreator, +>; + +pub type RelayClient = TFullClient; +pub type ParachainClient = TFullClient; + +pub trait FudgeHandle { + type RelayRuntime: frame_system::Config + + polkadot_runtime_parachains::paras::Config + + polkadot_runtime_parachains::session_info::Config + + polkadot_runtime_parachains::initializer::Config; + + type RelayConstructApi: ConstructRuntimeApi< + RelayBlock, + RelayClient, + RuntimeApi = Self::RelayApi, + > + Send + + Sync + + 'static; + + type RelayApi: BlockBuilderApi + + BabeApi + + ParachainHost + + ApiExt as Backend>::State> + + TaggedTransactionQueue; + + type ParachainRuntime: Runtime; + + type ParachainBlock: BlockT; + + type ParachainConstructApi: ConstructRuntimeApi< + Self::ParachainBlock, + ParachainClient, + RuntimeApi = Self::ParachainApi, + > + Send + + Sync + + 'static; + + type ParachainApi: BlockBuilderApi + + ApiExt< + Self::ParachainBlock, + StateBackend = as Backend>::State, + > + AuraApi + + TaggedTransactionQueue; + + const RELAY_CODE: Option<&'static [u8]>; + const PARACHAIN_CODE: Option<&'static [u8]>; + const PARA_ID: u32; + + fn relay(&self) -> &RelaychainBuilder; + fn relay_mut(&mut self) -> &mut RelaychainBuilder; + + fn parachain(&self) -> &ParachainBuilder; + fn parachain_mut( + &mut self, + ) -> &mut ParachainBuilder; + + fn build(relay_storage: Storage, parachain_storage: Storage) -> Self; + + fn build_relay( + storage: Storage, + ) -> RelaychainBuilder { + sp_tracing::enter_span!(sp_tracing::Level::INFO, "Relay - StartUp"); + + let code = Self::RELAY_CODE.unwrap(); + let mut state = StateProvider::new(code); + + state.insert_storage( + polkadot_runtime_parachains::configuration::GenesisConfig::::default() + .build_storage() + .unwrap() + ); + + state.insert_storage( + frame_system::GenesisConfig { + code: code.to_vec(), + } + .build_storage::() + .unwrap(), + ); + + state.insert_storage(storage); + + let mut init = fudge::initiator::default(Handle::current()); + init.with_genesis(Box::new(state)); + + let cidp = |client: Arc>| -> RelayInherentCreator { + let instance_id = FudgeInherentTimestamp::create_instance( + std::time::Duration::from_secs(6), + Some(std::time::Duration::from_millis(START_DATE)), + ); + + Box::new(move |parent: H256, ()| { + let client = client.clone(); + let parent_header = client + .header(parent.clone()) + .expect("ESSENTIAL: Relay CIDP must not fail.") + .expect("ESSENTIAL: Relay CIDP must not fail."); + + async move { + let timestamp = FudgeInherentTimestamp::get_instance(instance_id) + .expect("Instances is initialized"); + + let slot = + sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + timestamp.current_time(), + SlotDuration::from_millis(std::time::Duration::from_secs(6).as_millis() as u64), + ); + + let relay_para_inherent = FudgeDummyInherentRelayParachain::new(parent_header); + Ok((timestamp, slot, relay_para_inherent)) + } + }) + }; + + let dp: DigestCreator = Box::new(move |parent, inherents| async move { + let babe = FudgeBabeDigest::::new(); + let digest = babe.build_digest(&parent, &inherents).await?; + Ok(digest) + }); + + RelaychainBuilder::new(init, |client| (cidp(client), dp)) + } + + fn build_parachain( + relay: &RelaychainBuilder, + storage: Storage, + ) -> ParachainBuilder { + sp_tracing::enter_span!(sp_tracing::Level::INFO, "Centrifuge - StartUp"); + + let code = Self::PARACHAIN_CODE.unwrap(); + let mut state = StateProvider::new(code); + + state.insert_storage( + frame_system::GenesisConfig { + code: code.to_vec(), + } + .build_storage::() + .unwrap(), + ); + state.insert_storage( + pallet_aura::GenesisConfig:: { + authorities: vec![AuraId::from(sp_core::sr25519::Public([0u8; 32]))], + } + .build_storage() + .unwrap(), + ); + + state.insert_storage(storage); + + let mut init = fudge::initiator::default(Handle::current()); + init.with_genesis(Box::new(state)); + + let para_id = ParaId::from(Self::PARA_ID); + let inherent_builder = relay.inherent_builder(para_id.clone()); + let instance_id = FudgeInherentTimestamp::create_instance( + std::time::Duration::from_secs(12), + Some(std::time::Duration::from_millis(START_DATE)), + ); + + let cidp = Box::new(move |_parent, ()| { + let inherent_builder_clone = inherent_builder.clone(); + async move { + let timestamp = FudgeInherentTimestamp::get_instance(instance_id) + .expect("Instances is initialized"); + + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + timestamp.current_time(), + SlotDuration::from_millis(std::time::Duration::from_secs(12).as_millis() as u64), + ); + let inherent = inherent_builder_clone.parachain_inherent().await.unwrap(); + let relay_para_inherent = FudgeInherentParaParachain::new(inherent); + Ok((timestamp, slot, relay_para_inherent)) + } + }); + + let dp = |clone_client: Arc< + ParachainClient, + >| { + Box::new(move |parent, inherents| { + let client = clone_client.clone(); + + async move { + let aura = FudgeAuraDigest::< + Self::ParachainBlock, + ParachainClient, + >::new(&*client); + + let digest = aura.build_digest(&parent, &inherents).await?; + Ok(digest) + } + }) + }; + + ParachainBuilder::new(init, |client| (cidp, dp(client))) + } +} diff --git a/runtime/integration-tests/src/generic/envs/runtime_env.rs b/runtime/integration-tests/src/generic/envs/runtime_env.rs index 9f6b6c0c02..b4c2814112 100644 --- a/runtime/integration-tests/src/generic/envs/runtime_env.rs +++ b/runtime/integration-tests/src/generic/envs/runtime_env.rs @@ -26,6 +26,8 @@ use crate::{ utils::accounts::Keyring, }; +/// Evironment that interact directly with the runtime, +/// without the usage of a client. pub struct RuntimeEnv { nonce: Index, ext: Rc>, diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index f87b09a241..43ca85f579 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -38,26 +38,103 @@ impl_config!(centrifuge_runtime, Centrifuge); #[macro_export] macro_rules! test_for_runtimes { - ( ( $($runtime:ident),* ), $name:ident ) => { + ( [ $($runtime:ident),* ], $name:ident ) => { mod $name { use super::*; + + #[allow(unused)] use development_runtime as development; + + #[allow(unused)] use altair_runtime as altair; + + #[allow(unused)] use centrifuge_runtime as centrifuge; $( - #[test] - fn $runtime() { + #[tokio::test] + async fn $runtime() { $name::<$runtime::Runtime>() } )* } }; + ( all , $name:ident ) => { + $crate::test_for_runtimes!([development, altair, centrifuge], $name); + }; } -#[macro_export] -macro_rules! test_for_all_runtimes { - ( $name:ident ) => { - $crate::test_for_runtimes!((development, altair, centrifuge), $name); +/// TODO generate this for all runtimes with a macro +mod fudge_handles { + use polkadot_core_primitives::Block as RelayBlock; + use sp_api::ConstructRuntimeApi; + use sp_runtime::Storage; + + use crate::generic::envs::fudge_env::{ + handle::{FudgeHandle, ParachainBuilder, ParachainClient, RelayClient, RelaychainBuilder}, + FudgeSupport, }; + + const DEVELOPMENT_PARA_ID: u32 = 2000; + + type Relaychain = RelaychainBuilder; + type Parachain = ParachainBuilder; + + #[fudge::companion] + pub struct DevelopmentFudge { + #[fudge::relaychain] + pub relay: Relaychain, + + #[fudge::parachain(DEVELOPMENT_PARA_ID)] + pub parachain: Parachain, + } + + // TODO: Implement for T only once when fudge::companion + // supports generic in the struct signature. + impl FudgeHandle for DevelopmentFudge { + type ParachainApi = , + >>::RuntimeApi; + type ParachainBlock = development_runtime::Block; + type ParachainConstructApi = development_runtime::RuntimeApi; + type ParachainRuntime = development_runtime::Runtime; + type RelayApi = , + >>::RuntimeApi; + type RelayConstructApi = rococo_runtime::RuntimeApi; + type RelayRuntime = rococo_runtime::Runtime; + + const PARACHAIN_CODE: Option<&'static [u8]> = development_runtime::WASM_BINARY; + const PARA_ID: u32 = DEVELOPMENT_PARA_ID; + const RELAY_CODE: Option<&'static [u8]> = rococo_runtime::WASM_BINARY; + + fn build(relay_storage: Storage, parachain_storage: Storage) -> Self { + let relay = Self::build_relay(relay_storage); + let parachain = Self::build_parachain(&relay, parachain_storage); + + Self { relay, parachain } + } + + fn relay(&self) -> &Relaychain { + &self.relay + } + + fn relay_mut(&mut self) -> &mut Relaychain { + &mut self.relay + } + + fn parachain(&self) -> &Parachain { + &self.parachain + } + + fn parachain_mut(&mut self) -> &mut Parachain { + &mut self.parachain + } + } + + impl FudgeSupport for development_runtime::Runtime { + type FudgeHandle = DevelopmentFudge; + } } From ad491e2d1ea5fb472ea8cb72e72b575662e6568c Mon Sep 17 00:00:00 2001 From: lemunozm Date: Tue, 10 Oct 2023 18:44:30 +0200 Subject: [PATCH 02/27] evolving and state support for fudge env --- .../src/generic/environment.rs | 41 +++++++++++++++- .../src/generic/envs/fudge_env.rs | 24 +++++----- .../src/generic/envs/fudge_env/handle.rs | 5 ++ .../src/generic/envs/runtime_env.rs | 47 ++++--------------- runtime/integration-tests/src/generic/mod.rs | 11 +++++ 5 files changed, 75 insertions(+), 53 deletions(-) diff --git a/runtime/integration-tests/src/generic/environment.rs b/runtime/integration-tests/src/generic/environment.rs index bee4f05635..bb0e9d2a7b 100644 --- a/runtime/integration-tests/src/generic/environment.rs +++ b/runtime/integration-tests/src/generic/environment.rs @@ -30,7 +30,44 @@ pub trait Env { fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult; /// Pass any number of blocks - fn pass(&mut self, blocks: Blocks); + fn pass(&mut self, blocks: Blocks) { + let (next, end_block) = self.state(|| { + let next = frame_system::Pallet::::block_number() + 1; + + let end_block = match blocks { + Blocks::ByNumber(n) => next + n, + Blocks::BySeconds(secs) => { + let blocks = secs / pallet_aura::Pallet::::slot_duration(); + if blocks % pallet_aura::Pallet::::slot_duration() != 0 { + blocks as BlockNumber + 1 + } else { + blocks as BlockNumber + } + } + Blocks::UntilEvent { limit, .. } => limit, + }; + + (next, end_block) + }); + + for i in next..end_block { + self.__priv_build_block(i); + + if let Blocks::UntilEvent { event, .. } = blocks.clone() { + let found = self.state(|| { + let event: T::RuntimeEventExt = event.into(); + frame_system::Pallet::::events() + .into_iter() + .find(|record| record.event == event) + .is_some() + }); + + if found { + break; + } + } + } + } /// Allows to mutate the storage state through the closure fn state_mut(&mut self, f: impl FnOnce() -> R) -> R; @@ -82,4 +119,6 @@ pub trait Env { }) .expect("Expected transaction") } + + fn __priv_build_block(&mut self, i: BlockNumber); } diff --git a/runtime/integration-tests/src/generic/envs/fudge_env.rs b/runtime/integration-tests/src/generic/envs/fudge_env.rs index cb441820b5..95de2912a1 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env.rs @@ -1,13 +1,12 @@ pub mod handle; +use cfg_primitives::BlockNumber; +use fudge::primitives::Chain; use handle::FudgeHandle; use sp_runtime::{DispatchResult, Storage}; use crate::{ - generic::{ - environment::{Blocks, Env}, - runtime::Runtime, - }, + generic::{environment::Env, runtime::Runtime}, utils::accounts::Keyring, }; @@ -34,18 +33,17 @@ impl Env for FudgeEnv { todo!() } - fn pass(&mut self, _blocks: Blocks) { - // Access to the handle to do everything - todo!() + fn state_mut(&mut self, f: impl FnOnce() -> R) -> R { + self.handle + .with_mut_state(Chain::Para(T::FudgeHandle::PARA_ID), f) } - fn state_mut(&mut self, _f: impl FnOnce() -> R) -> R { - // Access to the handle to do everything - todo!() + fn state(&self, f: impl FnOnce() -> R) -> R { + self.handle + .with_state(Chain::Para(T::FudgeHandle::PARA_ID), f) } - fn state(&self, _f: impl FnOnce() -> R) -> R { - // Access to the handle to do everything - todo!() + fn __priv_build_block(&mut self, _i: BlockNumber) { + self.handle.evolve(); } } diff --git a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs index 3e57d2ccb7..6cc603609d 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs @@ -8,6 +8,7 @@ use fudge::{ CreateInherentDataProviders, FudgeDummyInherentRelayParachain, FudgeInherentParaParachain, FudgeInherentTimestamp, }, + primitives::Chain, state::StateProvider, TWasmExecutor, }; @@ -123,6 +124,10 @@ pub trait FudgeHandle { &mut self, ) -> &mut ParachainBuilder; + fn with_state(&self, chain: Chain, f: impl FnOnce() -> R) -> R; + fn with_mut_state(&mut self, chain: Chain, f: impl FnOnce() -> R) -> R; + fn evolve(&mut self); + fn build(relay_storage: Storage, parachain_storage: Storage) -> Self; fn build_relay( diff --git a/runtime/integration-tests/src/generic/envs/runtime_env.rs b/runtime/integration-tests/src/generic/envs/runtime_env.rs index b4c2814112..d3b0b99834 100644 --- a/runtime/integration-tests/src/generic/envs/runtime_env.rs +++ b/runtime/integration-tests/src/generic/envs/runtime_env.rs @@ -19,10 +19,7 @@ use sp_runtime::{ use sp_timestamp::Timestamp; use crate::{ - generic::{ - environment::{Blocks, Env}, - runtime::Runtime, - }, + generic::{environment::Env, runtime::Runtime}, utils::accounts::Keyring, }; @@ -77,41 +74,6 @@ impl Env for RuntimeEnv { }) } - fn pass(&mut self, blocks: Blocks) { - self.ext.borrow_mut().execute_with(|| { - let next = frame_system::Pallet::::block_number() + 1; - - let end_block = match blocks { - Blocks::ByNumber(n) => next + n, - Blocks::BySeconds(secs) => { - let blocks = secs / pallet_aura::Pallet::::slot_duration(); - if blocks % pallet_aura::Pallet::::slot_duration() != 0 { - blocks as BlockNumber + 1 - } else { - blocks as BlockNumber - } - } - Blocks::UntilEvent { limit, .. } => limit, - }; - - for i in next..end_block { - T::finalize_block(); - Self::prepare_block(i); - - if let Blocks::UntilEvent { event, .. } = blocks.clone() { - let event: T::RuntimeEventExt = event.into(); - if frame_system::Pallet::::events() - .into_iter() - .find(|record| record.event == event) - .is_some() - { - break; - } - } - } - }) - } - fn state_mut(&mut self, f: impl FnOnce() -> R) -> R { self.ext.borrow_mut().execute_with(f) } @@ -125,6 +87,13 @@ impl Env for RuntimeEnv { .unwrap() }) } + + fn __priv_build_block(&mut self, i: BlockNumber) { + self.state_mut(|| { + T::finalize_block(); + Self::prepare_block(i); + }); + } } impl RuntimeEnv { diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index 43ca85f579..b08e602af8 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -66,6 +66,7 @@ macro_rules! test_for_runtimes { /// TODO generate this for all runtimes with a macro mod fudge_handles { + use fudge::primitives::Chain; use polkadot_core_primitives::Block as RelayBlock; use sp_api::ConstructRuntimeApi; use sp_runtime::Storage; @@ -132,6 +133,16 @@ mod fudge_handles { fn parachain_mut(&mut self) -> &mut Parachain { &mut self.parachain } + + fn with_state(&self, chain: Chain, f: impl FnOnce() -> R) -> R { + self.with_state(chain, f).unwrap() + } + + fn with_mut_state(&mut self, chain: Chain, f: impl FnOnce() -> R) -> R { + self.with_mut_state(chain, f).unwrap() + } + + fn evolve(&mut self) {} } impl FudgeSupport for development_runtime::Runtime { From 6c5f848213a22dc2088cff03aaf15b33f2d00e7a Mon Sep 17 00:00:00 2001 From: lemunozm Date: Tue, 10 Oct 2023 19:14:40 +0200 Subject: [PATCH 03/27] Support Client APIs --- .../src/generic/cases/example.rs | 27 ++++++++++++++-- .../src/generic/envs/fudge_env.rs | 32 +++++++++++++++++-- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/example.rs b/runtime/integration-tests/src/generic/cases/example.rs index 484c15422d..a419b31f6a 100644 --- a/runtime/integration-tests/src/generic/cases/example.rs +++ b/runtime/integration-tests/src/generic/cases/example.rs @@ -111,7 +111,7 @@ fn check_fee() { }); } -fn using_fudge() { +fn fudge_example() { let _env = FudgeEnv::::from_storage( Genesis::default() .add(pallet_aura::GenesisConfig:: { @@ -126,11 +126,34 @@ fn using_fudge() { //TODO } +fn fudge_call_api() { + let env = FudgeEnv::::from_storage( + Genesis::default() + .add(pallet_aura::GenesisConfig:: { + authorities: vec![AuraId::from(Keyring::Charlie.public())], + }) + .storage(), + ); + + // Exclusive from fudge environment. + // It uses a client to access the runtime api. + env.with_api(|api, latest| { + // We include the API we want to use + use sp_api::Core; + + assert_eq!( + api.version(&latest).unwrap(), + ::Version::get() + ); + }) +} + // Generate tests for all runtimes crate::test_for_runtimes!([development, altair, centrifuge], transfer_balance); crate::test_for_runtimes!(all, call_api); crate::test_for_runtimes!(all, check_fee); -crate::test_for_runtimes!([development], using_fudge); +crate::test_for_runtimes!([development], fudge_example); +crate::test_for_runtimes!([development], fudge_call_api); // Output: for `cargo test -p runtime-integration-tests transfer_balance` // running 6 tests diff --git a/runtime/integration-tests/src/generic/envs/fudge_env.rs b/runtime/integration-tests/src/generic/envs/fudge_env.rs index 95de2912a1..508274ebce 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env.rs @@ -2,8 +2,10 @@ pub mod handle; use cfg_primitives::BlockNumber; use fudge::primitives::Chain; -use handle::FudgeHandle; -use sp_runtime::{DispatchResult, Storage}; +use handle::{FudgeHandle, ParachainClient}; +use sc_client_api::HeaderBackend; +use sp_api::{ApiRef, ProvideRuntimeApi}; +use sp_runtime::{generic::BlockId, DispatchResult, Storage}; use crate::{ generic::{environment::Env, runtime::Runtime}, @@ -47,3 +49,29 @@ impl Env for FudgeEnv { self.handle.evolve(); } } + +type ApiRefOf<'a, T> = + ApiRef< + 'a, + ::ParachainBlock, + ::ParachainConstructApi, + > as sp_api::ProvideRuntimeApi<::ParachainBlock>>::Api, + >; + +impl FudgeEnv { + pub fn with_api(&self, exec: F) + where + F: FnOnce( + ApiRefOf, + BlockId<::ParachainBlock>, + ), + { + let client = self.handle.parachain().client(); + let best_hash = client.info().best_hash; + let api = client.runtime_api(); + let best_hash = BlockId::hash(best_hash); + + exec(api, best_hash); + } +} From fa48bea949a59fba65891e0e107800e9bf01954d Mon Sep 17 00:00:00 2001 From: lemunozm Date: Tue, 10 Oct 2023 19:22:59 +0200 Subject: [PATCH 04/27] simplify test cases --- .../src/generic/cases/example.rs | 27 +++---------------- .../src/generic/envs/runtime_env.rs | 14 +++++++--- 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/example.rs b/runtime/integration-tests/src/generic/cases/example.rs index a419b31f6a..b4b75f9962 100644 --- a/runtime/integration-tests/src/generic/cases/example.rs +++ b/runtime/integration-tests/src/generic/cases/example.rs @@ -1,4 +1,4 @@ -use cfg_primitives::{AuraId, Balance, CFG}; +use cfg_primitives::{Balance, CFG}; use frame_support::traits::Get; use crate::{ @@ -23,9 +23,6 @@ fn transfer_balance() { // environment. let mut env = RuntimeEnv::::from_storage( Genesis::default() - .add(pallet_aura::GenesisConfig:: { - authorities: vec![AuraId::from(Keyring::Charlie.public())], - }) .add(pallet_balances::GenesisConfig:: { balances: vec![( Keyring::Alice.to_account_id(), @@ -66,13 +63,7 @@ fn transfer_balance() { } fn call_api() { - let env = RuntimeEnv::::from_storage( - Genesis::default() - .add(pallet_aura::GenesisConfig:: { - authorities: vec![AuraId::from(Keyring::Charlie.public())], - }) - .storage(), - ); + let env = RuntimeEnv::::from_storage(Default::default()); env.state(|| { // Call to Core::version() API. @@ -85,9 +76,6 @@ fn call_api() { fn check_fee() { let mut env = RuntimeEnv::::from_storage( Genesis::default() - .add(pallet_aura::GenesisConfig:: { - authorities: vec![AuraId::from(Keyring::Charlie.public())], - }) .add(pallet_balances::GenesisConfig:: { balances: vec![(Keyring::Alice.to_account_id(), 1 * CFG)], }) @@ -114,9 +102,6 @@ fn check_fee() { fn fudge_example() { let _env = FudgeEnv::::from_storage( Genesis::default() - .add(pallet_aura::GenesisConfig:: { - authorities: vec![AuraId::from(Keyring::Charlie.public())], - }) .add(pallet_balances::GenesisConfig:: { balances: vec![(Keyring::Alice.to_account_id(), 1 * CFG)], }) @@ -127,13 +112,7 @@ fn fudge_example() { } fn fudge_call_api() { - let env = FudgeEnv::::from_storage( - Genesis::default() - .add(pallet_aura::GenesisConfig:: { - authorities: vec![AuraId::from(Keyring::Charlie.public())], - }) - .storage(), - ); + let env = FudgeEnv::::from_storage(Default::default()); // Exclusive from fudge environment. // It uses a client to access the runtime api. diff --git a/runtime/integration-tests/src/generic/envs/runtime_env.rs b/runtime/integration-tests/src/generic/envs/runtime_env.rs index d3b0b99834..80fe8d6c22 100644 --- a/runtime/integration-tests/src/generic/envs/runtime_env.rs +++ b/runtime/integration-tests/src/generic/envs/runtime_env.rs @@ -1,6 +1,6 @@ use std::{cell::RefCell, marker::PhantomData, rc::Rc}; -use cfg_primitives::{Address, BlockNumber, Header, Index}; +use cfg_primitives::{Address, AuraId, BlockNumber, Header, Index}; use codec::Encode; use cumulus_primitives_core::PersistedValidationData; use cumulus_primitives_parachain_inherent::ParachainInherentData; @@ -8,9 +8,10 @@ use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; use frame_support::{ inherent::{InherentData, ProvideInherent}, storage::transactional, + traits::GenesisBuild, }; use sp_consensus_aura::{Slot, AURA_ENGINE_ID}; -use sp_core::H256; +use sp_core::{sr25519::Public, H256}; use sp_runtime::{ generic::{Era, SignedPayload}, traits::{Block, Extrinsic}, @@ -32,7 +33,14 @@ pub struct RuntimeEnv { } impl Env for RuntimeEnv { - fn from_storage(storage: Storage) -> Self { + fn from_storage(mut storage: Storage) -> Self { + // Needed for the aura usage + pallet_aura::GenesisConfig:: { + authorities: vec![AuraId::from(Public([0; 32]))], + } + .assimilate_storage(&mut storage) + .unwrap(); + let mut ext = sp_io::TestExternalities::new(storage); ext.execute_with(|| Self::prepare_block(1)); From 5f17c11b9299831e916be0a8b94165e256ef0c95 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Tue, 10 Oct 2023 19:54:08 +0200 Subject: [PATCH 05/27] Add spetial fudge methos --- .../src/generic/envs/fudge_env.rs | 18 ++++++++++++++---- .../src/generic/envs/fudge_env/handle.rs | 2 ++ runtime/integration-tests/src/generic/mod.rs | 8 +++++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/runtime/integration-tests/src/generic/envs/fudge_env.rs b/runtime/integration-tests/src/generic/envs/fudge_env.rs index 508274ebce..dcb66b0bfb 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env.rs @@ -31,18 +31,19 @@ impl Env for FudgeEnv { } fn submit(&mut self, _who: Keyring, _call: impl Into) -> DispatchResult { + // TODO: create extrinsic + // self.handle.parachain_mut().append_extrinsic(extrinsic) + // Access to the handle to do everything todo!() } fn state_mut(&mut self, f: impl FnOnce() -> R) -> R { - self.handle - .with_mut_state(Chain::Para(T::FudgeHandle::PARA_ID), f) + self.handle.parachain_mut().with_mut_state(f).unwrap() } fn state(&self, f: impl FnOnce() -> R) -> R { - self.handle - .with_state(Chain::Para(T::FudgeHandle::PARA_ID), f) + self.handle.parachain().with_state(f).unwrap() } fn __priv_build_block(&mut self, _i: BlockNumber) { @@ -59,7 +60,16 @@ type ApiRefOf<'a, T> = > as sp_api::ProvideRuntimeApi<::ParachainBlock>>::Api, >; +/// Specialized fudge methods impl FudgeEnv { + pub fn chain_state_mut(&mut self, chain: Chain, f: impl FnOnce() -> R) -> R { + self.handle.with_mut_state(chain, f) + } + + pub fn chain_state(&self, chain: Chain, f: impl FnOnce() -> R) -> R { + self.handle.with_state(chain, f) + } + pub fn with_api(&self, exec: F) where F: FnOnce( diff --git a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs index 6cc603609d..9585abb7c9 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs @@ -124,6 +124,8 @@ pub trait FudgeHandle { &mut self, ) -> &mut ParachainBuilder; + fn append_extrinsic(&mut self, chain: Chain, extrinsic: Vec) -> Result<(), ()>; + fn with_state(&self, chain: Chain, f: impl FnOnce() -> R) -> R; fn with_mut_state(&mut self, chain: Chain, f: impl FnOnce() -> R) -> R; fn evolve(&mut self); diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index b08e602af8..e3bb598aff 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -134,6 +134,10 @@ mod fudge_handles { &mut self.parachain } + fn append_extrinsic(&mut self, chain: Chain, extrinsic: Vec) -> Result<(), ()> { + self.append_extrinsic(chain, extrinsic) + } + fn with_state(&self, chain: Chain, f: impl FnOnce() -> R) -> R { self.with_state(chain, f).unwrap() } @@ -142,7 +146,9 @@ mod fudge_handles { self.with_mut_state(chain, f).unwrap() } - fn evolve(&mut self) {} + fn evolve(&mut self) { + self.evolve().unwrap() + } } impl FudgeSupport for development_runtime::Runtime { From c45a04f951564b94309157469069c0a91a4bea76 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Tue, 10 Oct 2023 23:46:03 +0200 Subject: [PATCH 06/27] Add T to FudgeHandle --- .../src/generic/cases/example.rs | 23 +++++-- .../src/generic/envs/fudge_env.rs | 69 ++++++++++++------- .../src/generic/envs/fudge_env/handle.rs | 42 +++++------ runtime/integration-tests/src/generic/mod.rs | 26 +++---- .../integration-tests/src/generic/runtime.rs | 2 +- 5 files changed, 96 insertions(+), 66 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/example.rs b/runtime/integration-tests/src/generic/cases/example.rs index b4b75f9962..9b2467b366 100644 --- a/runtime/integration-tests/src/generic/cases/example.rs +++ b/runtime/integration-tests/src/generic/cases/example.rs @@ -99,15 +99,30 @@ fn check_fee() { }); } -fn fudge_example() { - let _env = FudgeEnv::::from_storage( +fn fudge_transfer_balance() { + const TRANSFER: Balance = 1000 * CFG; + const FOR_FEES: Balance = 1 * CFG; + + let mut env = FudgeEnv::::from_storage( Genesis::default() .add(pallet_balances::GenesisConfig:: { - balances: vec![(Keyring::Alice.to_account_id(), 1 * CFG)], + balances: vec![( + Keyring::Alice.to_account_id(), + T::ExistentialDeposit::get() + FOR_FEES + TRANSFER, + )], }) .storage(), ); + env.submit( + Keyring::Alice, + pallet_balances::Call::transfer { + dest: Keyring::Bob.into(), + value: TRANSFER, + }, + ) + .unwrap(); + //TODO } @@ -131,7 +146,7 @@ fn fudge_call_api() { crate::test_for_runtimes!([development, altair, centrifuge], transfer_balance); crate::test_for_runtimes!(all, call_api); crate::test_for_runtimes!(all, check_fee); -crate::test_for_runtimes!([development], fudge_example); +crate::test_for_runtimes!([development], fudge_transfer_balance); crate::test_for_runtimes!([development], fudge_call_api); // Output: for `cargo test -p runtime-integration-tests transfer_balance` diff --git a/runtime/integration-tests/src/generic/envs/fudge_env.rs b/runtime/integration-tests/src/generic/envs/fudge_env.rs index dcb66b0bfb..4f45a07ecd 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env.rs @@ -1,21 +1,26 @@ pub mod handle; -use cfg_primitives::BlockNumber; +use cfg_primitives::{Address, BlockNumber}; +use codec::Encode; use fudge::primitives::Chain; use handle::{FudgeHandle, ParachainClient}; use sc_client_api::HeaderBackend; use sp_api::{ApiRef, ProvideRuntimeApi}; -use sp_runtime::{generic::BlockId, DispatchResult, Storage}; +use sp_runtime::{ + generic::{BlockId, Era, SignedPayload}, + traits::{Block, Extrinsic}, + DispatchResult, MultiSignature, Storage, +}; use crate::{ generic::{environment::Env, runtime::Runtime}, utils::accounts::Keyring, }; -/// Trait that represent the entity has Fudge support -pub trait FudgeSupport { - /// Type to interact with fudge chains - type FudgeHandle: FudgeHandle; +/// Trait that represent a runtime with Fudge support +pub trait FudgeSupport: Runtime { + /// Type to interact with fudge + type FudgeHandle: FudgeHandle; } /// Evironment that uses fudge to interact with the runtime @@ -30,12 +35,34 @@ impl Env for FudgeEnv { } } - fn submit(&mut self, _who: Keyring, _call: impl Into) -> DispatchResult { - // TODO: create extrinsic - // self.handle.parachain_mut().append_extrinsic(extrinsic) + fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult { + let runtime_call = call.into(); + let signed_extra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(Era::mortal(256, 0)), + frame_system::CheckNonce::::from(0), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + ); + + let raw_payload = SignedPayload::new(runtime_call.clone(), signed_extra.clone()).unwrap(); + let signature = + MultiSignature::Sr25519(raw_payload.using_encoded(|payload| who.sign(payload))); + + let multi_address = (Address::Id(who.to_account_id()), signature, signed_extra); + + let extrinsic = + ::Extrinsic::new(runtime_call, Some(multi_address)).unwrap(); + + self.handle + .parachain_mut() + .append_extrinsic(extrinsic) + .unwrap(); - // Access to the handle to do everything - todo!() + Ok(()) } fn state_mut(&mut self, f: impl FnOnce() -> R) -> R { @@ -51,14 +78,13 @@ impl Env for FudgeEnv { } } -type ApiRefOf<'a, T> = - ApiRef< - 'a, - ::ParachainBlock, - ::ParachainConstructApi, - > as sp_api::ProvideRuntimeApi<::ParachainBlock>>::Api, - >; +type ApiRefOf<'a, T> = ApiRef< + 'a, + ::Block, + <::FudgeHandle as FudgeHandle>::ParachainConstructApi, + > as sp_api::ProvideRuntimeApi<::Block>>::Api, +>; /// Specialized fudge methods impl FudgeEnv { @@ -72,10 +98,7 @@ impl FudgeEnv { pub fn with_api(&self, exec: F) where - F: FnOnce( - ApiRefOf, - BlockId<::ParachainBlock>, - ), + F: FnOnce(ApiRefOf, BlockId), { let client = self.handle.parachain().client(); let best_hash = client.info().best_hash; diff --git a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs index 9585abb7c9..71cb114300 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs @@ -18,7 +18,7 @@ use polkadot_primitives::runtime_api::ParachainHost; use sc_block_builder::BlockBuilderApi; use sc_client_api::Backend; use sc_service::{TFullBackend, TFullClient}; -use sp_api::{ApiExt, BlockT, ConstructRuntimeApi}; +use sp_api::{ApiExt, ConstructRuntimeApi}; use sp_consensus_aura::{sr25519::AuthorityId, AuraApi}; use sp_consensus_babe::BabeApi; use sp_consensus_slots::SlotDuration; @@ -73,7 +73,7 @@ pub type ParachainBuilder = fudge::ParachainBuilder< pub type RelayClient = TFullClient; pub type ParachainClient = TFullClient; -pub trait FudgeHandle { +pub trait FudgeHandle { type RelayRuntime: frame_system::Config + polkadot_runtime_parachains::paras::Config + polkadot_runtime_parachains::session_info::Config @@ -93,24 +93,18 @@ pub trait FudgeHandle { + ApiExt as Backend>::State> + TaggedTransactionQueue; - type ParachainRuntime: Runtime; - - type ParachainBlock: BlockT; - type ParachainConstructApi: ConstructRuntimeApi< - Self::ParachainBlock, - ParachainClient, + T::Block, + ParachainClient, RuntimeApi = Self::ParachainApi, > + Send + Sync + 'static; - type ParachainApi: BlockBuilderApi - + ApiExt< - Self::ParachainBlock, - StateBackend = as Backend>::State, - > + AuraApi - + TaggedTransactionQueue; + type ParachainApi: BlockBuilderApi + + ApiExt as Backend>::State> + + AuraApi + + TaggedTransactionQueue; const RELAY_CODE: Option<&'static [u8]>; const PARACHAIN_CODE: Option<&'static [u8]>; @@ -119,10 +113,8 @@ pub trait FudgeHandle { fn relay(&self) -> &RelaychainBuilder; fn relay_mut(&mut self) -> &mut RelaychainBuilder; - fn parachain(&self) -> &ParachainBuilder; - fn parachain_mut( - &mut self, - ) -> &mut ParachainBuilder; + fn parachain(&self) -> &ParachainBuilder; + fn parachain_mut(&mut self) -> &mut ParachainBuilder; fn append_extrinsic(&mut self, chain: Chain, extrinsic: Vec) -> Result<(), ()>; @@ -200,7 +192,7 @@ pub trait FudgeHandle { fn build_parachain( relay: &RelaychainBuilder, storage: Storage, - ) -> ParachainBuilder { + ) -> ParachainBuilder { sp_tracing::enter_span!(sp_tracing::Level::INFO, "Centrifuge - StartUp"); let code = Self::PARACHAIN_CODE.unwrap(); @@ -210,11 +202,11 @@ pub trait FudgeHandle { frame_system::GenesisConfig { code: code.to_vec(), } - .build_storage::() + .build_storage::() .unwrap(), ); state.insert_storage( - pallet_aura::GenesisConfig:: { + pallet_aura::GenesisConfig:: { authorities: vec![AuraId::from(sp_core::sr25519::Public([0u8; 32]))], } .build_storage() @@ -250,16 +242,14 @@ pub trait FudgeHandle { } }); - let dp = |clone_client: Arc< - ParachainClient, - >| { + let dp = |clone_client: Arc>| { Box::new(move |parent, inherents| { let client = clone_client.clone(); async move { let aura = FudgeAuraDigest::< - Self::ParachainBlock, - ParachainClient, + T::Block, + ParachainClient, >::new(&*client); let digest = aura.build_digest(&parent, &inherents).await?; diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index e3bb598aff..2c63e23078 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -78,28 +78,24 @@ mod fudge_handles { const DEVELOPMENT_PARA_ID: u32 = 2000; - type Relaychain = RelaychainBuilder; - type Parachain = ParachainBuilder; - #[fudge::companion] pub struct DevelopmentFudge { #[fudge::relaychain] - pub relay: Relaychain, + pub relay: RelaychainBuilder, #[fudge::parachain(DEVELOPMENT_PARA_ID)] - pub parachain: Parachain, + pub parachain: + ParachainBuilder, } // TODO: Implement for T only once when fudge::companion // supports generic in the struct signature. - impl FudgeHandle for DevelopmentFudge { + impl FudgeHandle for DevelopmentFudge { type ParachainApi = , >>::RuntimeApi; - type ParachainBlock = development_runtime::Block; type ParachainConstructApi = development_runtime::RuntimeApi; - type ParachainRuntime = development_runtime::Runtime; type RelayApi = , @@ -118,19 +114,25 @@ mod fudge_handles { Self { relay, parachain } } - fn relay(&self) -> &Relaychain { + fn relay(&self) -> &RelaychainBuilder { &self.relay } - fn relay_mut(&mut self) -> &mut Relaychain { + fn relay_mut( + &mut self, + ) -> &mut RelaychainBuilder { &mut self.relay } - fn parachain(&self) -> &Parachain { + fn parachain( + &self, + ) -> &ParachainBuilder { &self.parachain } - fn parachain_mut(&mut self) -> &mut Parachain { + fn parachain_mut( + &mut self, + ) -> &mut ParachainBuilder { &mut self.parachain } diff --git a/runtime/integration-tests/src/generic/runtime.rs b/runtime/integration-tests/src/generic/runtime.rs index fb3e8e69cb..5cb0136bc7 100644 --- a/runtime/integration-tests/src/generic/runtime.rs +++ b/runtime/integration-tests/src/generic/runtime.rs @@ -97,7 +97,7 @@ pub trait Runtime: + From> + From> + From> - + From>; + + From> + Sync + Send; /// Just the RuntimeEvent type, but redefined with extra bounds. /// You can add `TryInto` and `From` bounds in order to convert pallet From 12beb070a07b0f16785b2f7e02d16be40d882d2b Mon Sep 17 00:00:00 2001 From: lemunozm Date: Wed, 11 Oct 2023 15:31:21 +0200 Subject: [PATCH 07/27] sumbmit extrinsic works --- .../src/generic/cases/example.rs | 25 +++++--- .../src/generic/environment.rs | 63 ++++++++++++++----- .../src/generic/envs/fudge_env.rs | 62 ++++++------------ .../src/generic/envs/fudge_env/handle.rs | 2 +- .../src/generic/envs/runtime_env.rs | 47 +++----------- runtime/integration-tests/src/generic/mod.rs | 13 +++- .../integration-tests/src/generic/runtime.rs | 2 + 7 files changed, 111 insertions(+), 103 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/example.rs b/runtime/integration-tests/src/generic/cases/example.rs index 9b2467b366..06c9801ec4 100644 --- a/runtime/integration-tests/src/generic/cases/example.rs +++ b/runtime/integration-tests/src/generic/cases/example.rs @@ -123,7 +123,23 @@ fn fudge_transfer_balance() { ) .unwrap(); - //TODO + env.pass(Blocks::ByNumber(1)); + + // Check the state + env.state(|| { + assert_eq!( + pallet_balances::Pallet::::free_balance(Keyring::Bob.to_account_id()), + TRANSFER + ); + }); + + // Check for an even occurred in this block + env.check_event(pallet_balances::Event::Transfer { + from: Keyring::Alice.to_account_id(), + to: Keyring::Bob.to_account_id(), + amount: TRANSFER, + }) + .unwrap(); } fn fudge_call_api() { @@ -142,15 +158,8 @@ fn fudge_call_api() { }) } -// Generate tests for all runtimes crate::test_for_runtimes!([development, altair, centrifuge], transfer_balance); crate::test_for_runtimes!(all, call_api); crate::test_for_runtimes!(all, check_fee); crate::test_for_runtimes!([development], fudge_transfer_balance); crate::test_for_runtimes!([development], fudge_call_api); - -// Output: for `cargo test -p runtime-integration-tests transfer_balance` -// running 6 tests -// test generic::cases::example::transfer_balance::altair ... ok -// test generic::cases::example::transfer_balance::development ... ok -// test generic::cases::example::transfer_balance::centrifuge ... ok diff --git a/runtime/integration-tests/src/generic/environment.rs b/runtime/integration-tests/src/generic/environment.rs index bb0e9d2a7b..a25ef98dee 100644 --- a/runtime/integration-tests/src/generic/environment.rs +++ b/runtime/integration-tests/src/generic/environment.rs @@ -1,5 +1,10 @@ -use cfg_primitives::{Balance, BlockNumber, Moment}; -use sp_runtime::{DispatchResult, Storage}; +use cfg_primitives::{Address, Balance, BlockNumber, Moment}; +use codec::Encode; +use sp_runtime::{ + generic::{Era, SignedPayload}, + traits::{Block, Extrinsic}, + DispatchResult, MultiSignature, Storage, +}; use crate::{generic::runtime::Runtime, utils::accounts::Keyring}; @@ -26,8 +31,42 @@ pub trait Env { /// Load the environment from a storage fn from_storage(storage: Storage) -> Self; + /// Creates an extrinsic, used by mainly by the own environment. + /// To create and submit an extrinsic, see `submit()` + fn create_extrinsic( + &self, + who: Keyring, + call: impl Into, + ) -> ::Extrinsic { + self.state(|| { + let runtime_call = call.into(); + let signed_extra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(Era::mortal(256, 0)), + frame_system::CheckNonce::::from(0), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + ); + + let raw_payload = + SignedPayload::new(runtime_call.clone(), signed_extra.clone()).unwrap(); + let signature = + MultiSignature::Sr25519(raw_payload.using_encoded(|payload| who.sign(payload))); + + let multi_address = (Address::Id(who.to_account_id()), signature, signed_extra); + + ::Extrinsic::new(runtime_call, Some(multi_address)).unwrap() + }) + } + /// Submit an extrinsic mutating the state - fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult; + fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult { + let extrinsic = self.create_extrinsic(who, call); + self.__priv_apply_extrinsic(extrinsic) + } /// Pass any number of blocks fn pass(&mut self, blocks: Blocks) { @@ -54,15 +93,7 @@ pub trait Env { self.__priv_build_block(i); if let Blocks::UntilEvent { event, .. } = blocks.clone() { - let found = self.state(|| { - let event: T::RuntimeEventExt = event.into(); - frame_system::Pallet::::events() - .into_iter() - .find(|record| record.event == event) - .is_some() - }); - - if found { + if self.check_event(event).is_some() { break; } } @@ -103,8 +134,7 @@ pub trait Env { frame_system::Pallet::::events() .into_iter() .rev() - .map(|record| record.event.try_into().ok()) - .find_map(|event| event.map(|e| f(e))) + .find_map(|record| record.event.try_into().map(|e| f(e)).ok()) .flatten() }) } @@ -121,4 +151,9 @@ pub trait Env { } fn __priv_build_block(&mut self, i: BlockNumber); + + fn __priv_apply_extrinsic( + &mut self, + extrinsic: ::Extrinsic, + ) -> DispatchResult; } diff --git a/runtime/integration-tests/src/generic/envs/fudge_env.rs b/runtime/integration-tests/src/generic/envs/fudge_env.rs index 4f45a07ecd..0e147649d6 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env.rs @@ -1,21 +1,13 @@ pub mod handle; -use cfg_primitives::{Address, BlockNumber}; -use codec::Encode; +use cfg_primitives::BlockNumber; use fudge::primitives::Chain; use handle::{FudgeHandle, ParachainClient}; use sc_client_api::HeaderBackend; use sp_api::{ApiRef, ProvideRuntimeApi}; -use sp_runtime::{ - generic::{BlockId, Era, SignedPayload}, - traits::{Block, Extrinsic}, - DispatchResult, MultiSignature, Storage, -}; +use sp_runtime::{generic::BlockId, traits::Block, DispatchError, DispatchResult, Storage}; -use crate::{ - generic::{environment::Env, runtime::Runtime}, - utils::accounts::Keyring, -}; +use crate::generic::{environment::Env, runtime::Runtime}; /// Trait that represent a runtime with Fudge support pub trait FudgeSupport: Runtime { @@ -30,39 +22,11 @@ pub struct FudgeEnv { impl Env for FudgeEnv { fn from_storage(storage: Storage) -> Self { - Self { - handle: T::FudgeHandle::build(Storage::default(), storage), - } - } - - fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult { - let runtime_call = call.into(); - let signed_extra = ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(Era::mortal(256, 0)), - frame_system::CheckNonce::::from(0), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(0), - ); - - let raw_payload = SignedPayload::new(runtime_call.clone(), signed_extra.clone()).unwrap(); - let signature = - MultiSignature::Sr25519(raw_payload.using_encoded(|payload| who.sign(payload))); - - let multi_address = (Address::Id(who.to_account_id()), signature, signed_extra); + let mut handle = T::FudgeHandle::build(Storage::default(), storage); - let extrinsic = - ::Extrinsic::new(runtime_call, Some(multi_address)).unwrap(); + handle.evolve(); - self.handle - .parachain_mut() - .append_extrinsic(extrinsic) - .unwrap(); - - Ok(()) + Self { handle } } fn state_mut(&mut self, f: impl FnOnce() -> R) -> R { @@ -76,6 +40,20 @@ impl Env for FudgeEnv { fn __priv_build_block(&mut self, _i: BlockNumber) { self.handle.evolve(); } + + fn __priv_apply_extrinsic( + &mut self, + extrinsic: ::Extrinsic, + ) -> DispatchResult { + self.handle + .parachain_mut() + .append_extrinsic(extrinsic) + .map(|_| ()) + .map_err(|_| { + // More information, issue: https://github.com/centrifuge/fudge/issues/67 + DispatchError::Other("Specific kind of DispatchError not supported by fudge now") + }) + } } type ApiRefOf<'a, T> = ApiRef< diff --git a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs index 71cb114300..4a357dc597 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs @@ -225,7 +225,7 @@ pub trait FudgeHandle { Some(std::time::Duration::from_millis(START_DATE)), ); - let cidp = Box::new(move |_parent, ()| { + let cidp = Box::new(move |_parent: H256, ()| { let inherent_builder_clone = inherent_builder.clone(); async move { let timestamp = FudgeInherentTimestamp::get_instance(instance_id) diff --git a/runtime/integration-tests/src/generic/envs/runtime_env.rs b/runtime/integration-tests/src/generic/envs/runtime_env.rs index 80fe8d6c22..2faac977a7 100644 --- a/runtime/integration-tests/src/generic/envs/runtime_env.rs +++ b/runtime/integration-tests/src/generic/envs/runtime_env.rs @@ -1,6 +1,6 @@ use std::{cell::RefCell, marker::PhantomData, rc::Rc}; -use cfg_primitives::{Address, AuraId, BlockNumber, Header, Index}; +use cfg_primitives::{AuraId, BlockNumber, Header, Index}; use codec::Encode; use cumulus_primitives_core::PersistedValidationData; use cumulus_primitives_parachain_inherent::ParachainInherentData; @@ -13,16 +13,12 @@ use frame_support::{ use sp_consensus_aura::{Slot, AURA_ENGINE_ID}; use sp_core::{sr25519::Public, H256}; use sp_runtime::{ - generic::{Era, SignedPayload}, traits::{Block, Extrinsic}, - Digest, DigestItem, DispatchError, DispatchResult, MultiSignature, Storage, TransactionOutcome, + Digest, DigestItem, DispatchError, DispatchResult, Storage, TransactionOutcome, }; use sp_timestamp::Timestamp; -use crate::{ - generic::{environment::Env, runtime::Runtime}, - utils::accounts::Keyring, -}; +use crate::generic::{environment::Env, runtime::Runtime}; /// Evironment that interact directly with the runtime, /// without the usage of a client. @@ -52,36 +48,6 @@ impl Env for RuntimeEnv { } } - fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult { - self.ext.borrow_mut().execute_with(|| { - let runtime_call = call.into(); - let signed_extra = ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(Era::mortal(256, 0)), - frame_system::CheckNonce::::from(self.nonce), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(0), - ); - - let raw_payload = - SignedPayload::new(runtime_call.clone(), signed_extra.clone()).unwrap(); - let signature = - MultiSignature::Sr25519(raw_payload.using_encoded(|payload| who.sign(payload))); - - let multi_address = (Address::Id(who.to_account_id()), signature, signed_extra); - - let extrinsic = - ::Extrinsic::new(runtime_call, Some(multi_address)).unwrap(); - - self.nonce += 1; - - T::apply_extrinsic(extrinsic).unwrap() - }) - } - fn state_mut(&mut self, f: impl FnOnce() -> R) -> R { self.ext.borrow_mut().execute_with(f) } @@ -102,6 +68,13 @@ impl Env for RuntimeEnv { Self::prepare_block(i); }); } + + fn __priv_apply_extrinsic( + &mut self, + extrinsic: ::Extrinsic, + ) -> DispatchResult { + self.state_mut(|| T::apply_extrinsic(extrinsic).unwrap()) + } } impl RuntimeEnv { diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index 2c63e23078..bb2c574165 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -36,6 +36,17 @@ impl_config!(development_runtime, Development); impl_config!(altair_runtime, Altair); impl_config!(centrifuge_runtime, Centrifuge); +/// Generate tests for all runtimes +/// See `example.rs` file for the usage +/// +/// ```sh +/// Output: for `cargo test -p runtime-integration-tests transfer_balance` +/// running 3 tests +/// +/// test generic::cases::example::transfer_balance::altair ... ok +/// test generic::cases::example::transfer_balance::development ... ok +/// test generic::cases::example::transfer_balance::centrifuge ... ok +/// ``` #[macro_export] macro_rules! test_for_runtimes { ( [ $($runtime:ident),* ], $name:ident ) => { @@ -111,7 +122,7 @@ mod fudge_handles { let relay = Self::build_relay(relay_storage); let parachain = Self::build_parachain(&relay, parachain_storage); - Self { relay, parachain } + Self::new(relay, parachain).unwrap() } fn relay(&self) -> &RelaychainBuilder { diff --git a/runtime/integration-tests/src/generic/runtime.rs b/runtime/integration-tests/src/generic/runtime.rs index 5cb0136bc7..75c2331fb5 100644 --- a/runtime/integration-tests/src/generic/runtime.rs +++ b/runtime/integration-tests/src/generic/runtime.rs @@ -19,6 +19,7 @@ use runtime_common::{ apis, fees::{DealWithFees, WeightToFee}, }; +use sp_core::H256; use sp_runtime::traits::{AccountIdLookup, Block, Dispatchable, Member}; /// Kind of runtime to check in runtime time @@ -116,6 +117,7 @@ pub trait Runtime: /// Block used by the runtime type Block: Block< + Hash = H256, Header = Header, Extrinsic = UncheckedExtrinsic< Address, From 170b4a214bf724017da85f6c1e11c8f5bac5c431 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Wed, 11 Oct 2023 15:40:52 +0200 Subject: [PATCH 08/27] use correct nonce --- runtime/integration-tests/src/generic/environment.rs | 3 ++- runtime/integration-tests/src/generic/envs/runtime_env.rs | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/runtime/integration-tests/src/generic/environment.rs b/runtime/integration-tests/src/generic/environment.rs index a25ef98dee..43f983861b 100644 --- a/runtime/integration-tests/src/generic/environment.rs +++ b/runtime/integration-tests/src/generic/environment.rs @@ -40,13 +40,14 @@ pub trait Env { ) -> ::Extrinsic { self.state(|| { let runtime_call = call.into(); + let nonce = frame_system::Pallet::::account(who.to_account_id()).nonce; let signed_extra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), frame_system::CheckEra::::from(Era::mortal(256, 0)), - frame_system::CheckNonce::::from(0), + frame_system::CheckNonce::::from(nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), ); diff --git a/runtime/integration-tests/src/generic/envs/runtime_env.rs b/runtime/integration-tests/src/generic/envs/runtime_env.rs index 2faac977a7..afc070df86 100644 --- a/runtime/integration-tests/src/generic/envs/runtime_env.rs +++ b/runtime/integration-tests/src/generic/envs/runtime_env.rs @@ -23,7 +23,6 @@ use crate::generic::{environment::Env, runtime::Runtime}; /// Evironment that interact directly with the runtime, /// without the usage of a client. pub struct RuntimeEnv { - nonce: Index, ext: Rc>, _config: PhantomData, } @@ -42,7 +41,6 @@ impl Env for RuntimeEnv { ext.execute_with(|| Self::prepare_block(1)); Self { - nonce: 0, ext: Rc::new(RefCell::new(ext)), _config: PhantomData, } From b6c807579deccda883fb6c06d462b5708b2fb0bc Mon Sep 17 00:00:00 2001 From: lemunozm Date: Wed, 11 Oct 2023 15:50:21 +0200 Subject: [PATCH 09/27] minor Env trait simplification --- .../src/generic/environment.rs | 10 +----- .../src/generic/envs/fudge_env.rs | 34 ++++++++++--------- .../src/generic/envs/runtime_env.rs | 23 +++++++------ runtime/integration-tests/src/generic/mod.rs | 3 +- 4 files changed, 33 insertions(+), 37 deletions(-) diff --git a/runtime/integration-tests/src/generic/environment.rs b/runtime/integration-tests/src/generic/environment.rs index 43f983861b..8862e911a1 100644 --- a/runtime/integration-tests/src/generic/environment.rs +++ b/runtime/integration-tests/src/generic/environment.rs @@ -64,10 +64,7 @@ pub trait Env { } /// Submit an extrinsic mutating the state - fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult { - let extrinsic = self.create_extrinsic(who, call); - self.__priv_apply_extrinsic(extrinsic) - } + fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult; /// Pass any number of blocks fn pass(&mut self, blocks: Blocks) { @@ -152,9 +149,4 @@ pub trait Env { } fn __priv_build_block(&mut self, i: BlockNumber); - - fn __priv_apply_extrinsic( - &mut self, - extrinsic: ::Extrinsic, - ) -> DispatchResult; } diff --git a/runtime/integration-tests/src/generic/envs/fudge_env.rs b/runtime/integration-tests/src/generic/envs/fudge_env.rs index 0e147649d6..c590be111b 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env.rs @@ -5,9 +5,12 @@ use fudge::primitives::Chain; use handle::{FudgeHandle, ParachainClient}; use sc_client_api::HeaderBackend; use sp_api::{ApiRef, ProvideRuntimeApi}; -use sp_runtime::{generic::BlockId, traits::Block, DispatchError, DispatchResult, Storage}; +use sp_runtime::{generic::BlockId, DispatchError, DispatchResult, Storage}; -use crate::generic::{environment::Env, runtime::Runtime}; +use crate::{ + generic::{environment::Env, runtime::Runtime}, + utils::accounts::Keyring, +}; /// Trait that represent a runtime with Fudge support pub trait FudgeSupport: Runtime { @@ -29,6 +32,19 @@ impl Env for FudgeEnv { Self { handle } } + fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult { + let extrinsic = self.create_extrinsic(who, call); + + self.handle + .parachain_mut() + .append_extrinsic(extrinsic) + .map(|_| ()) + .map_err(|_| { + DispatchError::Other("Specific kind of DispatchError not supported by fudge now") + // More information, issue: https://github.com/centrifuge/fudge/issues/67 + }) + } + fn state_mut(&mut self, f: impl FnOnce() -> R) -> R { self.handle.parachain_mut().with_mut_state(f).unwrap() } @@ -40,20 +56,6 @@ impl Env for FudgeEnv { fn __priv_build_block(&mut self, _i: BlockNumber) { self.handle.evolve(); } - - fn __priv_apply_extrinsic( - &mut self, - extrinsic: ::Extrinsic, - ) -> DispatchResult { - self.handle - .parachain_mut() - .append_extrinsic(extrinsic) - .map(|_| ()) - .map_err(|_| { - // More information, issue: https://github.com/centrifuge/fudge/issues/67 - DispatchError::Other("Specific kind of DispatchError not supported by fudge now") - }) - } } type ApiRefOf<'a, T> = ApiRef< diff --git a/runtime/integration-tests/src/generic/envs/runtime_env.rs b/runtime/integration-tests/src/generic/envs/runtime_env.rs index afc070df86..9e1fc13b26 100644 --- a/runtime/integration-tests/src/generic/envs/runtime_env.rs +++ b/runtime/integration-tests/src/generic/envs/runtime_env.rs @@ -1,6 +1,6 @@ use std::{cell::RefCell, marker::PhantomData, rc::Rc}; -use cfg_primitives::{AuraId, BlockNumber, Header, Index}; +use cfg_primitives::{AuraId, BlockNumber, Header}; use codec::Encode; use cumulus_primitives_core::PersistedValidationData; use cumulus_primitives_parachain_inherent::ParachainInherentData; @@ -13,12 +13,15 @@ use frame_support::{ use sp_consensus_aura::{Slot, AURA_ENGINE_ID}; use sp_core::{sr25519::Public, H256}; use sp_runtime::{ - traits::{Block, Extrinsic}, - Digest, DigestItem, DispatchError, DispatchResult, Storage, TransactionOutcome, + traits::Extrinsic, Digest, DigestItem, DispatchError, DispatchResult, Storage, + TransactionOutcome, }; use sp_timestamp::Timestamp; -use crate::generic::{environment::Env, runtime::Runtime}; +use crate::{ + generic::{environment::Env, runtime::Runtime}, + utils::accounts::Keyring, +}; /// Evironment that interact directly with the runtime, /// without the usage of a client. @@ -46,6 +49,11 @@ impl Env for RuntimeEnv { } } + fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult { + let extrinsic = self.create_extrinsic(who, call); + self.state_mut(|| T::apply_extrinsic(extrinsic).unwrap()) + } + fn state_mut(&mut self, f: impl FnOnce() -> R) -> R { self.ext.borrow_mut().execute_with(f) } @@ -66,13 +74,6 @@ impl Env for RuntimeEnv { Self::prepare_block(i); }); } - - fn __priv_apply_extrinsic( - &mut self, - extrinsic: ::Extrinsic, - ) -> DispatchResult { - self.state_mut(|| T::apply_extrinsic(extrinsic).unwrap()) - } } impl RuntimeEnv { diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index bb2c574165..f0195ee267 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -99,8 +99,9 @@ mod fudge_handles { ParachainBuilder, } - // TODO: Implement for T only once when fudge::companion + // Implement for T only once when fudge::companion // supports generic in the struct signature. + // Issue: https://github.com/centrifuge/fudge/issues/21 impl FudgeHandle for DevelopmentFudge { type ParachainApi = Date: Wed, 11 Oct 2023 17:50:55 +0200 Subject: [PATCH 10/27] minor example reorder --- .../src/generic/cases/example.rs | 87 ++++++++++--------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/example.rs b/runtime/integration-tests/src/generic/cases/example.rs index 06c9801ec4..88c597b896 100644 --- a/runtime/integration-tests/src/generic/cases/example.rs +++ b/runtime/integration-tests/src/generic/cases/example.rs @@ -42,6 +42,9 @@ fn transfer_balance() { ) .unwrap(); + // Pass blocks to evolve the system + env.pass(Blocks::ByNumber(1)); + // Check for an even occurred in this block env.check_event(pallet_balances::Event::Transfer { from: Keyring::Alice.to_account_id(), @@ -50,9 +53,6 @@ fn transfer_balance() { }) .unwrap(); - // Pass blocks to evolve the system - env.pass(Blocks::ByNumber(1)); - // Check the state env.state(|| { assert_eq!( @@ -62,43 +62,7 @@ fn transfer_balance() { }); } -fn call_api() { - let env = RuntimeEnv::::from_storage(Default::default()); - - env.state(|| { - // Call to Core::version() API. - // It's automatically implemented by the runtime T, so you can easily do: - // T::version() - assert_eq!(T::version(), ::Version::get()); - }) -} - -fn check_fee() { - let mut env = RuntimeEnv::::from_storage( - Genesis::default() - .add(pallet_balances::GenesisConfig:: { - balances: vec![(Keyring::Alice.to_account_id(), 1 * CFG)], - }) - .storage(), - ); - - env.submit( - Keyring::Alice, - frame_system::Call::remark { remark: vec![] }, - ) - .unwrap(); - - // Get the fee of the last submitted extrinsic - let fee = env.last_fee(); - - env.state(|| { - assert_eq!( - pallet_balances::Pallet::::free_balance(Keyring::Alice.to_account_id()), - 1 * CFG - fee - ); - }); -} - +// Identical to `transfer_balance()` test but using fudge. fn fudge_transfer_balance() { const TRANSFER: Balance = 1000 * CFG; const FOR_FEES: Balance = 1 * CFG; @@ -142,6 +106,17 @@ fn fudge_transfer_balance() { .unwrap(); } +fn call_api() { + let env = RuntimeEnv::::from_storage(Default::default()); + + env.state(|| { + // Call to Core::version() API. + // It's automatically implemented by the runtime T, so you can easily do: + // T::version() + assert_eq!(T::version(), ::Version::get()); + }) +} + fn fudge_call_api() { let env = FudgeEnv::::from_storage(Default::default()); @@ -151,11 +126,37 @@ fn fudge_call_api() { // We include the API we want to use use sp_api::Core; + let result = api.version(&latest).unwrap(); + + assert_eq!(result, T::version()); + assert_eq!(result, ::Version::get()); + }) +} + +fn check_fee() { + let mut env = RuntimeEnv::::from_storage( + Genesis::default() + .add(pallet_balances::GenesisConfig:: { + balances: vec![(Keyring::Alice.to_account_id(), 1 * CFG)], + }) + .storage(), + ); + + env.submit( + Keyring::Alice, + frame_system::Call::remark { remark: vec![] }, + ) + .unwrap(); + + // Get the fee of the last submitted extrinsic + let fee = env.last_fee(); + + env.state(|| { assert_eq!( - api.version(&latest).unwrap(), - ::Version::get() + pallet_balances::Pallet::::free_balance(Keyring::Alice.to_account_id()), + 1 * CFG - fee ); - }) + }); } crate::test_for_runtimes!([development, altair, centrifuge], transfer_balance); From 084d1481f4b2436d381e22806778360e1a30113a Mon Sep 17 00:00:00 2001 From: lemunozm Date: Wed, 11 Oct 2023 19:52:05 +0200 Subject: [PATCH 11/27] fudge support for all runtimes --- .../src/generic/cases/example.rs | 10 +- runtime/integration-tests/src/generic/mod.rs | 266 ++++++++++-------- 2 files changed, 151 insertions(+), 125 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/example.rs b/runtime/integration-tests/src/generic/cases/example.rs index 88c597b896..dd21f58e2b 100644 --- a/runtime/integration-tests/src/generic/cases/example.rs +++ b/runtime/integration-tests/src/generic/cases/example.rs @@ -42,9 +42,6 @@ fn transfer_balance() { ) .unwrap(); - // Pass blocks to evolve the system - env.pass(Blocks::ByNumber(1)); - // Check for an even occurred in this block env.check_event(pallet_balances::Event::Transfer { from: Keyring::Alice.to_account_id(), @@ -53,6 +50,9 @@ fn transfer_balance() { }) .unwrap(); + // Pass blocks to evolve the system + env.pass(Blocks::ByNumber(1)); + // Check the state env.state(|| { assert_eq!( @@ -162,5 +162,5 @@ fn check_fee() { crate::test_for_runtimes!([development, altair, centrifuge], transfer_balance); crate::test_for_runtimes!(all, call_api); crate::test_for_runtimes!(all, check_fee); -crate::test_for_runtimes!([development], fudge_transfer_balance); -crate::test_for_runtimes!([development], fudge_call_api); +crate::test_for_runtimes!(all, fudge_transfer_balance); +crate::test_for_runtimes!(all, fudge_call_api); diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index f0195ee267..2c98116c24 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -20,37 +20,34 @@ mod cases { use runtime::{Runtime, RuntimeKind}; -macro_rules! impl_config { - ($runtime:ident, $kind:ident) => { - impl Runtime for $runtime::Runtime { - type Block = $runtime::Block; - type RuntimeCallExt = $runtime::RuntimeCall; - type RuntimeEventExt = $runtime::RuntimeEvent; - - const KIND: RuntimeKind = RuntimeKind::$kind; - } - }; -} - -impl_config!(development_runtime, Development); -impl_config!(altair_runtime, Altair); -impl_config!(centrifuge_runtime, Centrifuge); - -/// Generate tests for all runtimes -/// See `example.rs` file for the usage +/// Generate tests for the specified runtimes or all runtimes. +/// Usage /// -/// ```sh -/// Output: for `cargo test -p runtime-integration-tests transfer_balance` -/// running 3 tests +/// ```rust +/// use crate::generic::runtime::Runtime; /// -/// test generic::cases::example::transfer_balance::altair ... ok -/// test generic::cases::example::transfer_balance::development ... ok -/// test generic::cases::example::transfer_balance::centrifuge ... ok +/// fn foo { +/// /// Your test here... +/// } +/// +/// crate::test_for_runtimes!([development, altair, centrifuge], foo); /// ``` +/// For the following command: `cargo test -p runtime-integration-tests foo`, +/// it will generate the following output: +/// +/// ```text +/// test generic::foo::altair ... ok +/// test generic::foo::development ... ok +/// test generic::foo::centrifuge ... ok +/// ``` +/// +/// Available input for the first argument is: +/// - Any combination of `development`, `altair`, `centrifuge` inside `[]`. +/// - The world `all`. #[macro_export] macro_rules! test_for_runtimes { - ( [ $($runtime:ident),* ], $name:ident ) => { - mod $name { + ( [ $($runtime_name:ident),* ], $test_name:ident ) => { + mod $test_name { use super::*; #[allow(unused)] @@ -64,108 +61,137 @@ macro_rules! test_for_runtimes { $( #[tokio::test] - async fn $runtime() { - $name::<$runtime::Runtime>() + async fn $runtime_name() { + $test_name::<$runtime_name::Runtime>() } )* } }; - ( all , $name:ident ) => { - $crate::test_for_runtimes!([development, altair, centrifuge], $name); + ( all , $test_name:ident ) => { + $crate::test_for_runtimes!([development, altair, centrifuge], $test_name); }; } -/// TODO generate this for all runtimes with a macro -mod fudge_handles { - use fudge::primitives::Chain; - use polkadot_core_primitives::Block as RelayBlock; - use sp_api::ConstructRuntimeApi; - use sp_runtime::Storage; - - use crate::generic::envs::fudge_env::{ - handle::{FudgeHandle, ParachainBuilder, ParachainClient, RelayClient, RelaychainBuilder}, - FudgeSupport, - }; - - const DEVELOPMENT_PARA_ID: u32 = 2000; - - #[fudge::companion] - pub struct DevelopmentFudge { - #[fudge::relaychain] - pub relay: RelaychainBuilder, - - #[fudge::parachain(DEVELOPMENT_PARA_ID)] - pub parachain: - ParachainBuilder, - } - - // Implement for T only once when fudge::companion - // supports generic in the struct signature. - // Issue: https://github.com/centrifuge/fudge/issues/21 - impl FudgeHandle for DevelopmentFudge { - type ParachainApi = , - >>::RuntimeApi; - type ParachainConstructApi = development_runtime::RuntimeApi; - type RelayApi = , - >>::RuntimeApi; - type RelayConstructApi = rococo_runtime::RuntimeApi; - type RelayRuntime = rococo_runtime::Runtime; - - const PARACHAIN_CODE: Option<&'static [u8]> = development_runtime::WASM_BINARY; - const PARA_ID: u32 = DEVELOPMENT_PARA_ID; - const RELAY_CODE: Option<&'static [u8]> = rococo_runtime::WASM_BINARY; - - fn build(relay_storage: Storage, parachain_storage: Storage) -> Self { - let relay = Self::build_relay(relay_storage); - let parachain = Self::build_parachain(&relay, parachain_storage); - - Self::new(relay, parachain).unwrap() - } - - fn relay(&self) -> &RelaychainBuilder { - &self.relay - } - - fn relay_mut( - &mut self, - ) -> &mut RelaychainBuilder { - &mut self.relay - } +/// Implements the `Runtime` trait for a runtime +macro_rules! impl_runtime { + ($runtime_path:ident, $kind:ident) => { + impl Runtime for $runtime_path::Runtime { + type Block = $runtime_path::Block; + type RuntimeCallExt = $runtime_path::RuntimeCall; + type RuntimeEventExt = $runtime_path::RuntimeEvent; - fn parachain( - &self, - ) -> &ParachainBuilder { - &self.parachain - } - - fn parachain_mut( - &mut self, - ) -> &mut ParachainBuilder { - &mut self.parachain - } - - fn append_extrinsic(&mut self, chain: Chain, extrinsic: Vec) -> Result<(), ()> { - self.append_extrinsic(chain, extrinsic) - } - - fn with_state(&self, chain: Chain, f: impl FnOnce() -> R) -> R { - self.with_state(chain, f).unwrap() - } - - fn with_mut_state(&mut self, chain: Chain, f: impl FnOnce() -> R) -> R { - self.with_mut_state(chain, f).unwrap() - } - - fn evolve(&mut self) { - self.evolve().unwrap() + const KIND: RuntimeKind = RuntimeKind::$kind; } - } + }; +} - impl FudgeSupport for development_runtime::Runtime { - type FudgeHandle = DevelopmentFudge; - } +impl_runtime!(development_runtime, Development); +impl_runtime!(altair_runtime, Altair); +impl_runtime!(centrifuge_runtime, Centrifuge); + +/// Implements fudge support for a runtime +macro_rules! impl_fudge_support { + ( + $fudge_companion_type:ident, + $relay_path:ident, + $parachain_path:ident, + $parachain_id:literal + ) => { + const _: () = { + use fudge::primitives::Chain; + use polkadot_core_primitives::Block as RelayBlock; + use sp_api::ConstructRuntimeApi; + use sp_runtime::Storage; + + use crate::generic::envs::fudge_env::{ + handle::{ + FudgeHandle, ParachainBuilder, ParachainClient, RelayClient, RelaychainBuilder, + }, + FudgeSupport, + }; + + #[fudge::companion] + pub struct $fudge_companion_type { + #[fudge::relaychain] + pub relay: RelaychainBuilder<$relay_path::RuntimeApi, $relay_path::Runtime>, + + #[fudge::parachain($parachain_id)] + pub parachain: + ParachainBuilder<$parachain_path::Block, $parachain_path::RuntimeApi>, + } + + // Implement for T only one time when fudge::companion + // supports generic in the struct signature. + impl FudgeHandle<$parachain_path::Runtime> for $fudge_companion_type { + type ParachainApi = <$parachain_path::RuntimeApi as ConstructRuntimeApi< + $parachain_path::Block, + ParachainClient<$parachain_path::Block, Self::ParachainConstructApi>, + >>::RuntimeApi; + type ParachainConstructApi = $parachain_path::RuntimeApi; + type RelayApi = <$relay_path::RuntimeApi as ConstructRuntimeApi< + RelayBlock, + RelayClient, + >>::RuntimeApi; + type RelayConstructApi = $relay_path::RuntimeApi; + type RelayRuntime = $relay_path::Runtime; + + const PARACHAIN_CODE: Option<&'static [u8]> = $parachain_path::WASM_BINARY; + const PARA_ID: u32 = $parachain_id; + const RELAY_CODE: Option<&'static [u8]> = $relay_path::WASM_BINARY; + + fn build(relay_storage: Storage, parachain_storage: Storage) -> Self { + let relay = Self::build_relay(relay_storage); + let parachain = Self::build_parachain(&relay, parachain_storage); + + Self::new(relay, parachain).unwrap() + } + + fn relay(&self) -> &RelaychainBuilder { + &self.relay + } + + fn relay_mut( + &mut self, + ) -> &mut RelaychainBuilder { + &mut self.relay + } + + fn parachain( + &self, + ) -> &ParachainBuilder<$parachain_path::Block, Self::ParachainConstructApi> { + &self.parachain + } + + fn parachain_mut( + &mut self, + ) -> &mut ParachainBuilder<$parachain_path::Block, Self::ParachainConstructApi> { + &mut self.parachain + } + + fn append_extrinsic(&mut self, chain: Chain, extrinsic: Vec) -> Result<(), ()> { + self.append_extrinsic(chain, extrinsic) + } + + fn with_state(&self, chain: Chain, f: impl FnOnce() -> R) -> R { + self.with_state(chain, f).unwrap() + } + + fn with_mut_state(&mut self, chain: Chain, f: impl FnOnce() -> R) -> R { + self.with_mut_state(chain, f).unwrap() + } + + fn evolve(&mut self) { + self.evolve().unwrap() + } + } + + impl FudgeSupport for $parachain_path::Runtime { + type FudgeHandle = $fudge_companion_type; + } + }; + }; } + +impl_fudge_support!(FudgeDevelopment, rococo_runtime, development_runtime, 2000); +impl_fudge_support!(FudgeAltair, kusama_runtime, altair_runtime, 2088); +impl_fudge_support!(CentrifugeAltair, polkadot_runtime, centrifuge_runtime, 2031); From c94c1ad8de42d0ee7dfe4c02ed5913f72426e43b Mon Sep 17 00:00:00 2001 From: lemunozm Date: Fri, 13 Oct 2023 11:56:16 +0200 Subject: [PATCH 12/27] fix nonce and divide api between submit now and later --- .../src/generic/cases/example.rs | 87 ++++++------ .../src/generic/environment.rs | 29 ++-- .../src/generic/envs/fudge_env.rs | 69 +++++++++- .../src/generic/envs/runtime_env.rs | 124 +++++++++++++++--- 4 files changed, 226 insertions(+), 83 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/example.rs b/runtime/integration-tests/src/generic/cases/example.rs index dd21f58e2b..e4e8fb7dac 100644 --- a/runtime/integration-tests/src/generic/cases/example.rs +++ b/runtime/integration-tests/src/generic/cases/example.rs @@ -33,14 +33,15 @@ fn transfer_balance() { ); // Call an extrinsic that would be processed immediately - env.submit( - Keyring::Alice, - pallet_balances::Call::transfer { - dest: Keyring::Bob.into(), - value: TRANSFER, - }, - ) - .unwrap(); + let fee = env + .submit_now( + Keyring::Alice, + pallet_balances::Call::transfer { + dest: Keyring::Bob.into(), + value: TRANSFER, + }, + ) + .unwrap(); // Check for an even occurred in this block env.check_event(pallet_balances::Event::Transfer { @@ -50,16 +51,20 @@ fn transfer_balance() { }) .unwrap(); - // Pass blocks to evolve the system - env.pass(Blocks::ByNumber(1)); - // Check the state env.state(|| { + assert_eq!( + pallet_balances::Pallet::::free_balance(Keyring::Alice.to_account_id()), + T::ExistentialDeposit::get() + FOR_FEES - fee, + ); assert_eq!( pallet_balances::Pallet::::free_balance(Keyring::Bob.to_account_id()), TRANSFER ); }); + + // Pass blocks to evolve the system + env.pass(Blocks::ByNumber(1)); } // Identical to `transfer_balance()` test but using fudge. @@ -78,7 +83,7 @@ fn fudge_transfer_balance() { .storage(), ); - env.submit( + env.submit_later( Keyring::Alice, pallet_balances::Call::transfer { dest: Keyring::Bob.into(), @@ -87,16 +92,9 @@ fn fudge_transfer_balance() { ) .unwrap(); + // submit-later will only take effect if a block has passed env.pass(Blocks::ByNumber(1)); - // Check the state - env.state(|| { - assert_eq!( - pallet_balances::Pallet::::free_balance(Keyring::Bob.to_account_id()), - TRANSFER - ); - }); - // Check for an even occurred in this block env.check_event(pallet_balances::Event::Transfer { from: Keyring::Alice.to_account_id(), @@ -104,6 +102,28 @@ fn fudge_transfer_balance() { amount: TRANSFER, }) .unwrap(); + + // Look for the fee for the last transaction + let fee = env + .find_event(|e| match e { + pallet_transaction_payment::Event::TransactionFeePaid { actual_fee, .. } => { + Some(actual_fee) + } + _ => None, + }) + .unwrap(); + + // Check the state + env.state(|| { + assert_eq!( + pallet_balances::Pallet::::free_balance(Keyring::Alice.to_account_id()), + T::ExistentialDeposit::get() + FOR_FEES - fee, + ); + assert_eq!( + pallet_balances::Pallet::::free_balance(Keyring::Bob.to_account_id()), + TRANSFER + ); + }); } fn call_api() { @@ -133,34 +153,7 @@ fn fudge_call_api() { }) } -fn check_fee() { - let mut env = RuntimeEnv::::from_storage( - Genesis::default() - .add(pallet_balances::GenesisConfig:: { - balances: vec![(Keyring::Alice.to_account_id(), 1 * CFG)], - }) - .storage(), - ); - - env.submit( - Keyring::Alice, - frame_system::Call::remark { remark: vec![] }, - ) - .unwrap(); - - // Get the fee of the last submitted extrinsic - let fee = env.last_fee(); - - env.state(|| { - assert_eq!( - pallet_balances::Pallet::::free_balance(Keyring::Alice.to_account_id()), - 1 * CFG - fee - ); - }); -} - crate::test_for_runtimes!([development, altair, centrifuge], transfer_balance); crate::test_for_runtimes!(all, call_api); -crate::test_for_runtimes!(all, check_fee); crate::test_for_runtimes!(all, fudge_transfer_balance); crate::test_for_runtimes!(all, fudge_call_api); diff --git a/runtime/integration-tests/src/generic/environment.rs b/runtime/integration-tests/src/generic/environment.rs index 8862e911a1..ba8ce42b72 100644 --- a/runtime/integration-tests/src/generic/environment.rs +++ b/runtime/integration-tests/src/generic/environment.rs @@ -1,9 +1,9 @@ -use cfg_primitives::{Address, Balance, BlockNumber, Moment}; +use cfg_primitives::{Address, Balance, BlockNumber, Index, Moment}; use codec::Encode; use sp_runtime::{ generic::{Era, SignedPayload}, traits::{Block, Extrinsic}, - DispatchResult, MultiSignature, Storage, + DispatchError, DispatchResult, MultiSignature, Storage, }; use crate::{generic::runtime::Runtime, utils::accounts::Keyring}; @@ -37,10 +37,10 @@ pub trait Env { &self, who: Keyring, call: impl Into, + nonce: Index, ) -> ::Extrinsic { self.state(|| { let runtime_call = call.into(); - let nonce = frame_system::Pallet::::account(who.to_account_id()).nonce; let signed_extra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), @@ -63,8 +63,16 @@ pub trait Env { }) } - /// Submit an extrinsic mutating the state - fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult; + /// Submit an extrinsic mutating the state instantly and returning the + /// consumed fee + fn submit_now( + &mut self, + who: Keyring, + call: impl Into, + ) -> Result; + + /// Submit an extrinsic mutating the state when the block is finalized + fn submit_later(&mut self, who: Keyring, call: impl Into) -> DispatchResult; /// Pass any number of blocks fn pass(&mut self, blocks: Blocks) { @@ -137,16 +145,5 @@ pub trait Env { }) } - /// Retrieve the fees used in the last submit call - fn last_fee(&self) -> Balance { - self.find_event(|e| match e { - pallet_transaction_payment::Event::TransactionFeePaid { actual_fee, .. } => { - Some(actual_fee) - } - _ => None, - }) - .expect("Expected transaction") - } - fn __priv_build_block(&mut self, i: BlockNumber); } diff --git a/runtime/integration-tests/src/generic/envs/fudge_env.rs b/runtime/integration-tests/src/generic/envs/fudge_env.rs index c590be111b..1882e32a14 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env.rs @@ -1,6 +1,8 @@ pub mod handle; -use cfg_primitives::BlockNumber; +use std::collections::HashMap; + +use cfg_primitives::{Balance, BlockNumber, Index}; use fudge::primitives::Chain; use handle::{FudgeHandle, ParachainClient}; use sc_client_api::HeaderBackend; @@ -21,6 +23,7 @@ pub trait FudgeSupport: Runtime { /// Evironment that uses fudge to interact with the runtime pub struct FudgeEnv { handle: T::FudgeHandle, + nonce_storage: HashMap, } impl Env for FudgeEnv { @@ -29,11 +32,24 @@ impl Env for FudgeEnv { handle.evolve(); - Self { handle } + Self { + handle, + nonce_storage: HashMap::default(), + } + } + + fn submit_now( + &mut self, + _who: Keyring, + _call: impl Into, + ) -> Result { + unimplemented!("FudgeEnv does not support submit_now() try submit_later()") } - fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult { - let extrinsic = self.create_extrinsic(who, call); + fn submit_later(&mut self, who: Keyring, call: impl Into) -> DispatchResult { + let nonce = *self.nonce_storage.entry(who).or_default(); + + let extrinsic = self.create_extrinsic(who, call, nonce); self.handle .parachain_mut() @@ -42,7 +58,11 @@ impl Env for FudgeEnv { .map_err(|_| { DispatchError::Other("Specific kind of DispatchError not supported by fudge now") // More information, issue: https://github.com/centrifuge/fudge/issues/67 - }) + })?; + + self.nonce_storage.insert(who, nonce + 1); + + Ok(()) } fn state_mut(&mut self, f: impl FnOnce() -> R) -> R { @@ -88,3 +108,42 @@ impl FudgeEnv { exec(api, best_hash); } } + +mod tests { + use cfg_primitives::CFG; + + use super::*; + use crate::generic::{environment::Blocks, utils::genesis::Genesis}; + + fn correct_nonce_for_submit_later() { + let mut env = FudgeEnv::::from_storage( + Genesis::default() + .add(pallet_balances::GenesisConfig:: { + balances: vec![(Keyring::Alice.to_account_id(), 1 * CFG)], + }) + .storage(), + ); + + env.submit_later( + Keyring::Alice, + frame_system::Call::remark { remark: vec![] }, + ) + .unwrap(); + + env.submit_later( + Keyring::Alice, + frame_system::Call::remark { remark: vec![] }, + ) + .unwrap(); + + env.pass(Blocks::ByNumber(1)); + + env.submit_later( + Keyring::Alice, + frame_system::Call::remark { remark: vec![] }, + ) + .unwrap(); + } + + crate::test_for_runtimes!(all, correct_nonce_for_submit_later); +} diff --git a/runtime/integration-tests/src/generic/envs/runtime_env.rs b/runtime/integration-tests/src/generic/envs/runtime_env.rs index 9e1fc13b26..050ad94a11 100644 --- a/runtime/integration-tests/src/generic/envs/runtime_env.rs +++ b/runtime/integration-tests/src/generic/envs/runtime_env.rs @@ -1,21 +1,17 @@ -use std::{cell::RefCell, marker::PhantomData, rc::Rc}; +use std::{cell::RefCell, marker::PhantomData, mem, rc::Rc}; -use cfg_primitives::{AuraId, BlockNumber, Header}; +use cfg_primitives::{AuraId, Balance, BlockNumber, Header}; use codec::Encode; use cumulus_primitives_core::PersistedValidationData; use cumulus_primitives_parachain_inherent::ParachainInherentData; use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; use frame_support::{ inherent::{InherentData, ProvideInherent}, - storage::transactional, traits::GenesisBuild, }; use sp_consensus_aura::{Slot, AURA_ENGINE_ID}; use sp_core::{sr25519::Public, H256}; -use sp_runtime::{ - traits::Extrinsic, Digest, DigestItem, DispatchError, DispatchResult, Storage, - TransactionOutcome, -}; +use sp_runtime::{traits::Extrinsic, Digest, DigestItem, DispatchError, DispatchResult, Storage}; use sp_timestamp::Timestamp; use crate::{ @@ -27,6 +23,7 @@ use crate::{ /// without the usage of a client. pub struct RuntimeEnv { ext: Rc>, + pending_extrinsics: Vec<(Keyring, T::RuntimeCall)>, _config: PhantomData, } @@ -45,13 +42,35 @@ impl Env for RuntimeEnv { Self { ext: Rc::new(RefCell::new(ext)), + pending_extrinsics: Vec::default(), _config: PhantomData, } } - fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult { - let extrinsic = self.create_extrinsic(who, call); - self.state_mut(|| T::apply_extrinsic(extrinsic).unwrap()) + fn submit_now( + &mut self, + who: Keyring, + call: impl Into, + ) -> Result { + let nonce = self.state(|| frame_system::Pallet::::account(who.to_account_id()).nonce); + let extrinsic = self.create_extrinsic(who, call, nonce); + self.state_mut(|| T::apply_extrinsic(extrinsic).unwrap())?; + + let fee = self + .find_event(|e| match e { + pallet_transaction_payment::Event::TransactionFeePaid { actual_fee, .. } => { + Some(actual_fee) + } + _ => None, + }) + .unwrap(); + + Ok(fee) + } + + fn submit_later(&mut self, who: Keyring, call: impl Into) -> DispatchResult { + self.pending_extrinsics.push((who, call.into())); + Ok(()) } fn state_mut(&mut self, f: impl FnOnce() -> R) -> R { @@ -60,15 +79,18 @@ impl Env for RuntimeEnv { fn state(&self, f: impl FnOnce() -> R) -> R { self.ext.borrow_mut().execute_with(|| { - transactional::with_transaction(|| { - // We revert all changes done by the closure to offer an inmutable state method - TransactionOutcome::Rollback::>(Ok(f())) - }) - .unwrap() + let version = frame_support::StateVersion::V1; + let hash = frame_support::storage_root(version); + + let result = f(); + + assert_eq!(hash, frame_support::storage_root(version)); + result }) } fn __priv_build_block(&mut self, i: BlockNumber) { + self.process_pending_extrinsics(); self.state_mut(|| { T::finalize_block(); Self::prepare_block(i); @@ -77,6 +99,16 @@ impl Env for RuntimeEnv { } impl RuntimeEnv { + fn process_pending_extrinsics(&mut self) { + let pending_extrinsics = mem::replace(&mut self.pending_extrinsics, Vec::default()); + for (who, call) in pending_extrinsics { + let nonce = + self.state(|| frame_system::Pallet::::account(who.to_account_id()).nonce); + let extrinsic = self.create_extrinsic(who, call, nonce); + self.state_mut(|| T::apply_extrinsic(extrinsic).unwrap().unwrap()); + } + } + fn prepare_block(i: BlockNumber) { let slot = Slot::from(i as u64); let digest = Digest { @@ -149,3 +181,65 @@ impl RuntimeEnv { .into() } } + +mod tests { + use cfg_primitives::CFG; + + use super::*; + use crate::generic::{environment::Blocks, utils::genesis::Genesis}; + + fn correct_nonce_for_submit_now() { + let mut env = RuntimeEnv::::from_storage( + Genesis::default() + .add(pallet_balances::GenesisConfig:: { + balances: vec![(Keyring::Alice.to_account_id(), 1 * CFG)], + }) + .storage(), + ); + + env.submit_now( + Keyring::Alice, + frame_system::Call::remark { remark: vec![] }, + ) + .unwrap(); + + env.submit_now( + Keyring::Alice, + frame_system::Call::remark { remark: vec![] }, + ) + .unwrap(); + } + + fn correct_nonce_for_submit_later() { + let mut env = RuntimeEnv::::from_storage( + Genesis::default() + .add(pallet_balances::GenesisConfig:: { + balances: vec![(Keyring::Alice.to_account_id(), 1 * CFG)], + }) + .storage(), + ); + + env.submit_later( + Keyring::Alice, + frame_system::Call::remark { remark: vec![] }, + ) + .unwrap(); + + env.submit_later( + Keyring::Alice, + frame_system::Call::remark { remark: vec![] }, + ) + .unwrap(); + + env.pass(Blocks::ByNumber(1)); + + env.submit_later( + Keyring::Alice, + frame_system::Call::remark { remark: vec![] }, + ) + .unwrap(); + } + + crate::test_for_runtimes!(all, correct_nonce_for_submit_now); + crate::test_for_runtimes!(all, correct_nonce_for_submit_later); +} From 2fb97d599f52a537d7ca9d929835369fbbc0bcb6 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Fri, 13 Oct 2023 13:20:54 +0200 Subject: [PATCH 13/27] minor organization --- .../src/generic/environment.rs | 64 +++++++++---------- .../src/generic/envs/fudge_env.rs | 7 +- .../src/generic/envs/runtime_env.rs | 21 ++++-- 3 files changed, 52 insertions(+), 40 deletions(-) diff --git a/runtime/integration-tests/src/generic/environment.rs b/runtime/integration-tests/src/generic/environment.rs index ba8ce42b72..d9b98daae1 100644 --- a/runtime/integration-tests/src/generic/environment.rs +++ b/runtime/integration-tests/src/generic/environment.rs @@ -31,38 +31,6 @@ pub trait Env { /// Load the environment from a storage fn from_storage(storage: Storage) -> Self; - /// Creates an extrinsic, used by mainly by the own environment. - /// To create and submit an extrinsic, see `submit()` - fn create_extrinsic( - &self, - who: Keyring, - call: impl Into, - nonce: Index, - ) -> ::Extrinsic { - self.state(|| { - let runtime_call = call.into(); - let signed_extra = ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(Era::mortal(256, 0)), - frame_system::CheckNonce::::from(nonce), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(0), - ); - - let raw_payload = - SignedPayload::new(runtime_call.clone(), signed_extra.clone()).unwrap(); - let signature = - MultiSignature::Sr25519(raw_payload.using_encoded(|payload| who.sign(payload))); - - let multi_address = (Address::Id(who.to_account_id()), signature, signed_extra); - - ::Extrinsic::new(runtime_call, Some(multi_address)).unwrap() - }) - } - /// Submit an extrinsic mutating the state instantly and returning the /// consumed fee fn submit_now( @@ -147,3 +115,35 @@ pub trait Env { fn __priv_build_block(&mut self, i: BlockNumber); } + +pub mod utils { + use super::*; + + /// Creates an extrinsic, used mainly by the environment implementations. + /// To create and submit an extrinsic, see `submit()` + pub fn create_extrinsic( + who: Keyring, + call: impl Into, + nonce: Index, + ) -> ::Extrinsic { + let runtime_call = call.into(); + let signed_extra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(Era::mortal(256, 0)), + frame_system::CheckNonce::::from(nonce), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + ); + + let raw_payload = SignedPayload::new(runtime_call.clone(), signed_extra.clone()).unwrap(); + let signature = + MultiSignature::Sr25519(raw_payload.using_encoded(|payload| who.sign(payload))); + + let multi_address = (Address::Id(who.to_account_id()), signature, signed_extra); + + ::Extrinsic::new(runtime_call, Some(multi_address)).unwrap() + } +} diff --git a/runtime/integration-tests/src/generic/envs/fudge_env.rs b/runtime/integration-tests/src/generic/envs/fudge_env.rs index 1882e32a14..59570f2c9c 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env.rs @@ -10,7 +10,10 @@ use sp_api::{ApiRef, ProvideRuntimeApi}; use sp_runtime::{generic::BlockId, DispatchError, DispatchResult, Storage}; use crate::{ - generic::{environment::Env, runtime::Runtime}, + generic::{ + environment::{utils, Env}, + runtime::Runtime, + }, utils::accounts::Keyring, }; @@ -49,7 +52,7 @@ impl Env for FudgeEnv { fn submit_later(&mut self, who: Keyring, call: impl Into) -> DispatchResult { let nonce = *self.nonce_storage.entry(who).or_default(); - let extrinsic = self.create_extrinsic(who, call, nonce); + let extrinsic = self.state(|| utils::create_extrinsic::(who, call, nonce)); self.handle .parachain_mut() diff --git a/runtime/integration-tests/src/generic/envs/runtime_env.rs b/runtime/integration-tests/src/generic/envs/runtime_env.rs index 050ad94a11..5ce87bde24 100644 --- a/runtime/integration-tests/src/generic/envs/runtime_env.rs +++ b/runtime/integration-tests/src/generic/envs/runtime_env.rs @@ -15,7 +15,10 @@ use sp_runtime::{traits::Extrinsic, Digest, DigestItem, DispatchError, DispatchR use sp_timestamp::Timestamp; use crate::{ - generic::{environment::Env, runtime::Runtime}, + generic::{ + environment::{utils, Env}, + runtime::Runtime, + }, utils::accounts::Keyring, }; @@ -52,8 +55,11 @@ impl Env for RuntimeEnv { who: Keyring, call: impl Into, ) -> Result { - let nonce = self.state(|| frame_system::Pallet::::account(who.to_account_id()).nonce); - let extrinsic = self.create_extrinsic(who, call, nonce); + let extrinsic = self.state(|| { + let nonce = frame_system::Pallet::::account(who.to_account_id()).nonce; + utils::create_extrinsic::(who, call, nonce) + }); + self.state_mut(|| T::apply_extrinsic(extrinsic).unwrap())?; let fee = self @@ -101,10 +107,13 @@ impl Env for RuntimeEnv { impl RuntimeEnv { fn process_pending_extrinsics(&mut self) { let pending_extrinsics = mem::replace(&mut self.pending_extrinsics, Vec::default()); + for (who, call) in pending_extrinsics { - let nonce = - self.state(|| frame_system::Pallet::::account(who.to_account_id()).nonce); - let extrinsic = self.create_extrinsic(who, call, nonce); + let extrinsic = self.state(|| { + let nonce = frame_system::Pallet::::account(who.to_account_id()).nonce; + utils::create_extrinsic::(who, call, nonce) + }); + self.state_mut(|| T::apply_extrinsic(extrinsic).unwrap().unwrap()); } } From bf6269a44bfc3f360f9811cee31ffcbada621aa9 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Fri, 13 Oct 2023 21:58:34 +0200 Subject: [PATCH 14/27] init tests for loans --- Cargo.lock | 1 + runtime/integration-tests/Cargo.toml | 2 +- .../src/generic/cases/loans.rs | 47 ++++++++ .../src/generic/environment.rs | 6 +- .../src/generic/envs/fudge_env.rs | 4 +- .../src/generic/envs/runtime_env.rs | 10 +- runtime/integration-tests/src/generic/mod.rs | 5 +- .../src/generic/utils/genesis.rs | 101 +++++++++++++++++- .../src/generic/utils/mod.rs | 84 +++++++++++++++ .../integration-tests/src/utils/accounts.rs | 5 + 10 files changed, 246 insertions(+), 19 deletions(-) create mode 100644 runtime/integration-tests/src/generic/cases/loans.rs create mode 100644 runtime/integration-tests/src/generic/utils/mod.rs diff --git a/Cargo.lock b/Cargo.lock index e4c5166fbe..d14c76bb20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11117,6 +11117,7 @@ dependencies = [ "pallet-restricted-tokens", "pallet-rewards", "pallet-session", + "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", "pallet-treasury", diff --git a/runtime/integration-tests/Cargo.toml b/runtime/integration-tests/Cargo.toml index cbe7df6145..3cf3662520 100644 --- a/runtime/integration-tests/Cargo.toml +++ b/runtime/integration-tests/Cargo.toml @@ -30,7 +30,7 @@ pallet-uniques = { git = "https://github.com/paritytech/substrate", default-feat pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } - +pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } ## Substrate-Primitives sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } diff --git a/runtime/integration-tests/src/generic/cases/loans.rs b/runtime/integration-tests/src/generic/cases/loans.rs new file mode 100644 index 0000000000..fe6fda9407 --- /dev/null +++ b/runtime/integration-tests/src/generic/cases/loans.rs @@ -0,0 +1,47 @@ +use cfg_primitives::{AccountId, Balance, CollectionId, ItemId, PoolId, CFG}; +use frame_support::traits::Get; +use orml_traits::GetByKey; + +use crate::{ + generic::{ + environment::{Blocks, Env}, + envs::runtime_env::RuntimeEnv, + runtime::Runtime, + utils::{ + self, + genesis::{self, Genesis, MUSD_CURRENCY_ID}, + }, + }, + utils::accounts::Keyring, +}; + +const POOL_ADMIN: Keyring = Keyring::Admin; +const INVESTOR: Keyring = Keyring::Alice; +const BORROWER: Keyring = Keyring::Bob; + +const FOR_FEES: Balance = 1 * CFG; + +const POOL_A: PoolId = 23; +const NFT_A: (CollectionId, ItemId) = (1, ItemId(10)); + +fn borrow() { + let mut env = RuntimeEnv::::from_storage( + Genesis::::default() + .add(genesis::balances(T::ExistentialDeposit::get() + FOR_FEES)) + .add(genesis::tokens(vec![( + MUSD_CURRENCY_ID, + T::ExistentialDeposits::get(&MUSD_CURRENCY_ID), + )])) + .add(genesis::assets(vec![MUSD_CURRENCY_ID])) + .storage(), + ); + + env.state_mut(|| { + utils::give_balance_to::(POOL_ADMIN.id(), T::PoolDeposit::get()); + utils::give_nft_to::(BORROWER.id(), NFT_A); + }); + + env.state(|| { + //pallet_uniques::Pallet:::: + }); +} diff --git a/runtime/integration-tests/src/generic/environment.rs b/runtime/integration-tests/src/generic/environment.rs index d9b98daae1..0ff0d9dbc7 100644 --- a/runtime/integration-tests/src/generic/environment.rs +++ b/runtime/integration-tests/src/generic/environment.rs @@ -36,11 +36,11 @@ pub trait Env { fn submit_now( &mut self, who: Keyring, - call: impl Into, + call: impl Into, ) -> Result; /// Submit an extrinsic mutating the state when the block is finalized - fn submit_later(&mut self, who: Keyring, call: impl Into) -> DispatchResult; + fn submit_later(&mut self, who: Keyring, call: impl Into) -> DispatchResult; /// Pass any number of blocks fn pass(&mut self, blocks: Blocks) { @@ -123,7 +123,7 @@ pub mod utils { /// To create and submit an extrinsic, see `submit()` pub fn create_extrinsic( who: Keyring, - call: impl Into, + call: impl Into, nonce: Index, ) -> ::Extrinsic { let runtime_call = call.into(); diff --git a/runtime/integration-tests/src/generic/envs/fudge_env.rs b/runtime/integration-tests/src/generic/envs/fudge_env.rs index 59570f2c9c..9aa395102a 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env.rs @@ -44,12 +44,12 @@ impl Env for FudgeEnv { fn submit_now( &mut self, _who: Keyring, - _call: impl Into, + _call: impl Into, ) -> Result { unimplemented!("FudgeEnv does not support submit_now() try submit_later()") } - fn submit_later(&mut self, who: Keyring, call: impl Into) -> DispatchResult { + fn submit_later(&mut self, who: Keyring, call: impl Into) -> DispatchResult { let nonce = *self.nonce_storage.entry(who).or_default(); let extrinsic = self.state(|| utils::create_extrinsic::(who, call, nonce)); diff --git a/runtime/integration-tests/src/generic/envs/runtime_env.rs b/runtime/integration-tests/src/generic/envs/runtime_env.rs index 5ce87bde24..26c372a501 100644 --- a/runtime/integration-tests/src/generic/envs/runtime_env.rs +++ b/runtime/integration-tests/src/generic/envs/runtime_env.rs @@ -26,7 +26,7 @@ use crate::{ /// without the usage of a client. pub struct RuntimeEnv { ext: Rc>, - pending_extrinsics: Vec<(Keyring, T::RuntimeCall)>, + pending_extrinsics: Vec<(Keyring, T::RuntimeCallExt)>, _config: PhantomData, } @@ -53,7 +53,7 @@ impl Env for RuntimeEnv { fn submit_now( &mut self, who: Keyring, - call: impl Into, + call: impl Into, ) -> Result { let extrinsic = self.state(|| { let nonce = frame_system::Pallet::::account(who.to_account_id()).nonce; @@ -74,7 +74,7 @@ impl Env for RuntimeEnv { Ok(fee) } - fn submit_later(&mut self, who: Keyring, call: impl Into) -> DispatchResult { + fn submit_later(&mut self, who: Keyring, call: impl Into) -> DispatchResult { self.pending_extrinsics.push((who, call.into())); Ok(()) } @@ -145,7 +145,7 @@ impl RuntimeEnv { } } - fn cumulus_inherent(i: BlockNumber) -> T::RuntimeCall { + fn cumulus_inherent(i: BlockNumber) -> T::RuntimeCallExt { let mut inherent_data = InherentData::default(); let sproof_builder = RelayStateSproofBuilder::default(); @@ -176,7 +176,7 @@ impl RuntimeEnv { .into() } - fn timestamp_inherent(timestamp: u64) -> T::RuntimeCall { + fn timestamp_inherent(timestamp: u64) -> T::RuntimeCallExt { let mut inherent_data = InherentData::default(); let timestamp_inherent = Timestamp::new(timestamp); diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index 2c98116c24..1960349310 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -9,13 +9,12 @@ pub mod envs { pub mod runtime_env; } pub mod runtime; -pub mod utils { - pub mod genesis; -} +pub mod utils; // Test cases mod cases { mod example; + mod loans; } use runtime::{Runtime, RuntimeKind}; diff --git a/runtime/integration-tests/src/generic/utils/genesis.rs b/runtime/integration-tests/src/generic/utils/genesis.rs index f6b64d3ecf..8842d3e9d8 100644 --- a/runtime/integration-tests/src/generic/utils/genesis.rs +++ b/runtime/integration-tests/src/generic/utils/genesis.rs @@ -1,15 +1,29 @@ +use std::{collections::BTreeMap, marker::PhantomData}; + +use cfg_primitives::Balance; +use cfg_types::tokens::{AssetMetadata, CurrencyId, CustomMetadata}; +use codec::Encode; use frame_support::traits::GenesisBuild; use sp_runtime::Storage; -use crate::generic::runtime::Runtime; +use crate::{generic::runtime::Runtime, utils::accounts::default_accounts}; -#[derive(Default)] -pub struct Genesis { +pub struct Genesis { storage: Storage, + _config: PhantomData, +} + +impl Default for Genesis { + fn default() -> Self { + Self { + storage: Default::default(), + _config: Default::default(), + } + } } -impl Genesis { - pub fn add(mut self, builder: impl GenesisBuild) -> Genesis { +impl Genesis { + pub fn add(mut self, builder: impl GenesisBuild) -> Self { builder.assimilate_storage(&mut self.storage).unwrap(); self } @@ -18,3 +32,80 @@ impl Genesis { self.storage } } + +pub fn balances(balance: Balance) -> impl GenesisBuild { + pallet_balances::GenesisConfig:: { + balances: default_accounts() + .into_iter() + .map(|keyring| (keyring.id(), balance)) + .collect(), + } +} + +pub fn tokens(values: Vec<(CurrencyId, Balance)>) -> impl GenesisBuild { + orml_tokens::GenesisConfig:: { + balances: default_accounts() + .into_iter() + .map(|keyring| { + values + .clone() + .into_iter() + .map(|(curency_id, balance)| (keyring.id(), curency_id, balance)) + .collect::>() + }) + .flatten() + .collect(), + } +} + +pub const MUSD_DECIMALS: u32 = 6; +pub const MUSD_UNIT: Balance = 10u128.pow(MUSD_DECIMALS); +pub const MUSD_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(1); + +pub const AUSD_DECIMALS: u32 = 12; +pub const AUSD_UNIT: Balance = 10u128.pow(AUSD_DECIMALS); +pub const AUSD_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(2); + +pub fn assets(currency_ids: Vec) -> impl GenesisBuild { + let assets = BTreeMap::from([ + ( + MUSD_CURRENCY_ID, + AssetMetadata { + decimals: MUSD_DECIMALS, + name: "Mock USD".as_bytes().to_vec(), + symbol: "MUSD".as_bytes().to_vec(), + existential_deposit: 0, + location: None, + additional: CustomMetadata { + pool_currency: true, + ..Default::default() + }, + } + .encode(), + ), + ( + AUSD_CURRENCY_ID, + AssetMetadata { + decimals: 12, + name: "Acala Dollar".as_bytes().to_vec(), + symbol: "AUSD".as_bytes().to_vec(), + existential_deposit: 0, + location: None, + additional: CustomMetadata { + pool_currency: true, + ..Default::default() + }, + } + .encode(), + ), + // Add new currencies here + ]); + + orml_asset_registry::GenesisConfig:: { + assets: currency_ids + .into_iter() + .map(|id| (id, assets.get(&id).unwrap().clone())) + .collect(), + last_asset_id: Default::default(), // It seems deprecated + } +} diff --git a/runtime/integration-tests/src/generic/utils/mod.rs b/runtime/integration-tests/src/generic/utils/mod.rs new file mode 100644 index 0000000000..1e8ad5e31b --- /dev/null +++ b/runtime/integration-tests/src/generic/utils/mod.rs @@ -0,0 +1,84 @@ +// Divide this utilties into files when they grow + +use cfg_primitives::{Balance, CollectionId, ItemId, Moment, PoolId, TrancheId}; +use cfg_types::{ + permissions::{PermissionScope, PoolRole, Role}, + tokens::CurrencyId, +}; +use frame_system::RawOrigin; +use sp_runtime::{traits::StaticLookup, AccountId32}; +pub mod genesis; + +use crate::generic::runtime::Runtime; + +pub fn give_nft_to( + dest: AccountId32, + (collection_id, item_id): (CollectionId, ItemId), +) { + pallet_uniques::Pallet::::force_create( + RawOrigin::Root.into(), + collection_id, + T::Lookup::unlookup(dest.clone()), + true, + ) + .unwrap(); + + pallet_uniques::Pallet::::mint( + RawOrigin::Signed(dest.clone()).into(), + collection_id, + item_id, + T::Lookup::unlookup(dest), + ) + .unwrap() +} + +pub fn give_balance_to(dest: AccountId32, amount: Balance) { + let data = pallet_balances::Account::::get(dest.clone()); + pallet_balances::Pallet::::set_balance( + RawOrigin::Root.into(), + T::Lookup::unlookup(dest), + data.free + amount, + data.reserved, + ) + .unwrap(); +} + +pub fn give_token_to(dest: AccountId32, currency_id: CurrencyId, amount: Balance) { + let data = orml_tokens::Accounts::::get(dest.clone(), currency_id); + orml_tokens::Pallet::::set_balance( + RawOrigin::Root.into(), + T::Lookup::unlookup(dest), + currency_id, + data.free + amount, + data.reserved, + ) + .unwrap(); +} + +pub fn give_investor_role( + investor: AccountId32, + pool_id: PoolId, + tranche_id: TrancheId, +) { + let role = Role::PoolRole(PoolRole::TrancheInvestor(tranche_id, Moment::MAX)); + pallet_permissions::Pallet::::add( + RawOrigin::Root.into(), + role, + investor, + PermissionScope::Pool(pool_id), + role, + ) + .unwrap(); +} + +pub fn give_borrower_role(borrower: AccountId32, pool_id: PoolId) { + let role = Role::PoolRole(PoolRole::Borrower); + pallet_permissions::Pallet::::add( + RawOrigin::Root.into(), + role, + borrower, + PermissionScope::Pool(pool_id), + role, + ) + .unwrap(); +} diff --git a/runtime/integration-tests/src/utils/accounts.rs b/runtime/integration-tests/src/utils/accounts.rs index ae61b304d6..d4cc842c72 100644 --- a/runtime/integration-tests/src/utils/accounts.rs +++ b/runtime/integration-tests/src/utils/accounts.rs @@ -154,6 +154,11 @@ impl Keyring { self.public().0.into() } + /// Shorter alias for `to_account_id()` + pub fn id(self) -> AccountId32 { + self.to_account_id() + } + pub fn sign(self, msg: &[u8]) -> Signature { Pair::from(self).sign(msg) } From 21577d0f266381c64eaf5f9ba36b495f59be8667 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Sat, 14 Oct 2023 19:06:39 +0200 Subject: [PATCH 15/27] fix ongoing loans test --- .../src/generic/cases/loans.rs | 16 ++++++++++---- .../src/generic/utils/genesis.rs | 6 +++--- .../src/generic/utils/mod.rs | 21 +++++++------------ 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/loans.rs b/runtime/integration-tests/src/generic/cases/loans.rs index fe6fda9407..f529727774 100644 --- a/runtime/integration-tests/src/generic/cases/loans.rs +++ b/runtime/integration-tests/src/generic/cases/loans.rs @@ -1,11 +1,14 @@ -use cfg_primitives::{AccountId, Balance, CollectionId, ItemId, PoolId, CFG}; +use cfg_primitives::{Balance, CollectionId, ItemId, PoolId, CFG}; use frame_support::traits::Get; use orml_traits::GetByKey; use crate::{ generic::{ environment::{Blocks, Env}, - envs::runtime_env::RuntimeEnv, + envs::{ + fudge_env::{FudgeEnv, FudgeSupport}, + runtime_env::RuntimeEnv, + }, runtime::Runtime, utils::{ self, @@ -24,7 +27,7 @@ const FOR_FEES: Balance = 1 * CFG; const POOL_A: PoolId = 23; const NFT_A: (CollectionId, ItemId) = (1, ItemId(10)); -fn borrow() { +fn borrow() { let mut env = RuntimeEnv::::from_storage( Genesis::::default() .add(genesis::balances(T::ExistentialDeposit::get() + FOR_FEES)) @@ -42,6 +45,11 @@ fn borrow() { }); env.state(|| { - //pallet_uniques::Pallet:::: + assert_eq!( + pallet_uniques::Pallet::::owner(NFT_A.0, NFT_A.1).unwrap(), + BORROWER.id(), + ) }); } + +crate::test_for_runtimes!(all, borrow); diff --git a/runtime/integration-tests/src/generic/utils/genesis.rs b/runtime/integration-tests/src/generic/utils/genesis.rs index 8842d3e9d8..aca4254d8e 100644 --- a/runtime/integration-tests/src/generic/utils/genesis.rs +++ b/runtime/integration-tests/src/generic/utils/genesis.rs @@ -72,9 +72,9 @@ pub fn assets(currency_ids: Vec) -> impl GenesisBuild MUSD_CURRENCY_ID, AssetMetadata { decimals: MUSD_DECIMALS, - name: "Mock USD".as_bytes().to_vec(), + name: "Mock Dollar".as_bytes().to_vec(), symbol: "MUSD".as_bytes().to_vec(), - existential_deposit: 0, + existential_deposit: 0 as Balance, location: None, additional: CustomMetadata { pool_currency: true, @@ -89,7 +89,7 @@ pub fn assets(currency_ids: Vec) -> impl GenesisBuild decimals: 12, name: "Acala Dollar".as_bytes().to_vec(), symbol: "AUSD".as_bytes().to_vec(), - existential_deposit: 0, + existential_deposit: 0 as Balance, location: None, additional: CustomMetadata { pool_currency: true, diff --git a/runtime/integration-tests/src/generic/utils/mod.rs b/runtime/integration-tests/src/generic/utils/mod.rs index 1e8ad5e31b..b42c8a2aad 100644 --- a/runtime/integration-tests/src/generic/utils/mod.rs +++ b/runtime/integration-tests/src/generic/utils/mod.rs @@ -1,20 +1,17 @@ // Divide this utilties into files when they grow -use cfg_primitives::{Balance, CollectionId, ItemId, Moment, PoolId, TrancheId}; +use cfg_primitives::{AccountId, Balance, CollectionId, ItemId, Moment, PoolId, TrancheId}; use cfg_types::{ permissions::{PermissionScope, PoolRole, Role}, tokens::CurrencyId, }; use frame_system::RawOrigin; -use sp_runtime::{traits::StaticLookup, AccountId32}; +use sp_runtime::{traits::StaticLookup, AccountId}; pub mod genesis; use crate::generic::runtime::Runtime; -pub fn give_nft_to( - dest: AccountId32, - (collection_id, item_id): (CollectionId, ItemId), -) { +pub fn give_nft_to(dest: AccountId, (collection_id, item_id): (CollectionId, ItemId)) { pallet_uniques::Pallet::::force_create( RawOrigin::Root.into(), collection_id, @@ -32,7 +29,7 @@ pub fn give_nft_to( .unwrap() } -pub fn give_balance_to(dest: AccountId32, amount: Balance) { +pub fn give_balance_to(dest: AccountId, amount: Balance) { let data = pallet_balances::Account::::get(dest.clone()); pallet_balances::Pallet::::set_balance( RawOrigin::Root.into(), @@ -43,7 +40,7 @@ pub fn give_balance_to(dest: AccountId32, amount: Balance) { .unwrap(); } -pub fn give_token_to(dest: AccountId32, currency_id: CurrencyId, amount: Balance) { +pub fn give_token_to(dest: AccountId, currency_id: CurrencyId, amount: Balance) { let data = orml_tokens::Accounts::::get(dest.clone(), currency_id); orml_tokens::Pallet::::set_balance( RawOrigin::Root.into(), @@ -55,11 +52,7 @@ pub fn give_token_to(dest: AccountId32, currency_id: CurrencyId, amo .unwrap(); } -pub fn give_investor_role( - investor: AccountId32, - pool_id: PoolId, - tranche_id: TrancheId, -) { +pub fn give_investor_role(investor: AccountId, pool_id: PoolId, tranche_id: TrancheId) { let role = Role::PoolRole(PoolRole::TrancheInvestor(tranche_id, Moment::MAX)); pallet_permissions::Pallet::::add( RawOrigin::Root.into(), @@ -71,7 +64,7 @@ pub fn give_investor_role( .unwrap(); } -pub fn give_borrower_role(borrower: AccountId32, pool_id: PoolId) { +pub fn give_borrower_role(borrower: AccountId, pool_id: PoolId) { let role = Role::PoolRole(PoolRole::Borrower); pallet_permissions::Pallet::::add( RawOrigin::Root.into(), From f998636c18b07cc5fe1a31091a55b6ccef7f55cd Mon Sep 17 00:00:00 2001 From: lemunozm Date: Mon, 16 Oct 2023 11:28:01 +0200 Subject: [PATCH 16/27] fix compilation --- runtime/integration-tests/src/generic/utils/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/integration-tests/src/generic/utils/mod.rs b/runtime/integration-tests/src/generic/utils/mod.rs index b42c8a2aad..be3d8326cf 100644 --- a/runtime/integration-tests/src/generic/utils/mod.rs +++ b/runtime/integration-tests/src/generic/utils/mod.rs @@ -6,7 +6,7 @@ use cfg_types::{ tokens::CurrencyId, }; use frame_system::RawOrigin; -use sp_runtime::{traits::StaticLookup, AccountId}; +use sp_runtime::traits::StaticLookup; pub mod genesis; use crate::generic::runtime::Runtime; From 4b159c5e48dc9b2a16b821902aff1a7226e80b12 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Mon, 16 Oct 2023 18:31:26 +0200 Subject: [PATCH 17/27] minor renames --- runtime/integration-tests/src/generic/envs/fudge_env.rs | 2 +- .../integration-tests/src/generic/envs/fudge_env/handle.rs | 6 +++--- runtime/integration-tests/src/generic/mod.rs | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/runtime/integration-tests/src/generic/envs/fudge_env.rs b/runtime/integration-tests/src/generic/envs/fudge_env.rs index 9aa395102a..abb5e2e997 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env.rs @@ -31,7 +31,7 @@ pub struct FudgeEnv { impl Env for FudgeEnv { fn from_storage(storage: Storage) -> Self { - let mut handle = T::FudgeHandle::build(Storage::default(), storage); + let mut handle = T::FudgeHandle::new(Storage::default(), storage); handle.evolve(); diff --git a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs index 4a357dc597..c9b50277bd 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs @@ -122,9 +122,9 @@ pub trait FudgeHandle { fn with_mut_state(&mut self, chain: Chain, f: impl FnOnce() -> R) -> R; fn evolve(&mut self); - fn build(relay_storage: Storage, parachain_storage: Storage) -> Self; + fn new(relay_storage: Storage, parachain_storage: Storage) -> Self; - fn build_relay( + fn new_relay_builder( storage: Storage, ) -> RelaychainBuilder { sp_tracing::enter_span!(sp_tracing::Level::INFO, "Relay - StartUp"); @@ -189,7 +189,7 @@ pub trait FudgeHandle { RelaychainBuilder::new(init, |client| (cidp(client), dp)) } - fn build_parachain( + fn new_parachain_builder( relay: &RelaychainBuilder, storage: Storage, ) -> ParachainBuilder { diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index 1960349310..bdfb516e04 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -138,9 +138,9 @@ macro_rules! impl_fudge_support { const PARA_ID: u32 = $parachain_id; const RELAY_CODE: Option<&'static [u8]> = $relay_path::WASM_BINARY; - fn build(relay_storage: Storage, parachain_storage: Storage) -> Self { - let relay = Self::build_relay(relay_storage); - let parachain = Self::build_parachain(&relay, parachain_storage); + fn new(relay_storage: Storage, parachain_storage: Storage) -> Self { + let relay = Self::new_relay_builder(relay_storage); + let parachain = Self::new_parachain_builder(&relay, parachain_storage); Self::new(relay, parachain).unwrap() } From 5d056abd1809cf0ec6e0fb5f662e63909ce7d386 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Mon, 16 Oct 2023 19:05:50 +0200 Subject: [PATCH 18/27] restore expect --- .../src/generic/envs/fudge_env/handle.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs index c9b50277bd..59b0d4fa1d 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs @@ -129,13 +129,13 @@ pub trait FudgeHandle { ) -> RelaychainBuilder { sp_tracing::enter_span!(sp_tracing::Level::INFO, "Relay - StartUp"); - let code = Self::RELAY_CODE.unwrap(); + let code = Self::RELAY_CODE.expect("ESSENTIAL: WASM is built."); let mut state = StateProvider::new(code); state.insert_storage( polkadot_runtime_parachains::configuration::GenesisConfig::::default() .build_storage() - .unwrap() + .expect("ESSENTIAL: GenesisBuild must not fail at this stage.") ); state.insert_storage( @@ -143,7 +143,7 @@ pub trait FudgeHandle { code: code.to_vec(), } .build_storage::() - .unwrap(), + .expect("ESSENTIAL: GenesisBuild must not fail at this stage."), ); state.insert_storage(storage); @@ -195,7 +195,7 @@ pub trait FudgeHandle { ) -> ParachainBuilder { sp_tracing::enter_span!(sp_tracing::Level::INFO, "Centrifuge - StartUp"); - let code = Self::PARACHAIN_CODE.unwrap(); + let code = Self::PARACHAIN_CODE.expect("ESSENTIAL: WASM is built."); let mut state = StateProvider::new(code); state.insert_storage( @@ -203,14 +203,14 @@ pub trait FudgeHandle { code: code.to_vec(), } .build_storage::() - .unwrap(), + .expect("ESSENTIAL: GenesisBuild must not fail at this stage."), ); state.insert_storage( pallet_aura::GenesisConfig:: { authorities: vec![AuraId::from(sp_core::sr25519::Public([0u8; 32]))], } .build_storage() - .unwrap(), + .expect("ESSENTIAL: GenesisBuild must not fail at this stage."), ); state.insert_storage(storage); From ef4d158536711229d5ba9d1d1a96dcfe5d001667 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Tue, 17 Oct 2023 07:42:15 +0200 Subject: [PATCH 19/27] loan testing in progress --- .../src/generic/cases/issue.rs | 23 ++++++ .../src/generic/cases/loans.rs | 18 ++++- runtime/integration-tests/src/generic/mod.rs | 1 + .../src/generic/utils/genesis.rs | 8 +- .../src/generic/utils/mod.rs | 81 ++++++++++++++++++- 5 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 runtime/integration-tests/src/generic/cases/issue.rs diff --git a/runtime/integration-tests/src/generic/cases/issue.rs b/runtime/integration-tests/src/generic/cases/issue.rs new file mode 100644 index 0000000000..1c4e97792b --- /dev/null +++ b/runtime/integration-tests/src/generic/cases/issue.rs @@ -0,0 +1,23 @@ +use crate::generic::{ + environment::Env, + envs::{ + fudge_env::{FudgeEnv, FudgeSupport}, + runtime_env::RuntimeEnv, + }, + runtime::Runtime, + utils::genesis::{self, Genesis, MUSD_CURRENCY_ID}, +}; + +fn what() { + let env = RuntimeEnv::::from_storage( + Genesis::::default() + .add(genesis::assets(vec![MUSD_CURRENCY_ID])) + .storage(), + ); + + env.state(|| { + orml_asset_registry::Pallet::::metadata(MUSD_CURRENCY_ID).unwrap(); + }); +} + +crate::test_for_runtimes!(all, what); diff --git a/runtime/integration-tests/src/generic/cases/loans.rs b/runtime/integration-tests/src/generic/cases/loans.rs index f529727774..0a28547f93 100644 --- a/runtime/integration-tests/src/generic/cases/loans.rs +++ b/runtime/integration-tests/src/generic/cases/loans.rs @@ -40,16 +40,30 @@ fn borrow() { ); env.state_mut(|| { - utils::give_balance_to::(POOL_ADMIN.id(), T::PoolDeposit::get()); - utils::give_nft_to::(BORROWER.id(), NFT_A); + // Creating a pool + + /* + orml_asset_registry::Pallet::::metadata( + &MUSD_CURRENCY_ID + ); + */ + + //utils::give_balance_to::(POOL_ADMIN.id(), T::PoolDeposit::get()); + //utils::create_empty_pool::(POOL_ADMIN.id(), POOL_A, + // MUSD_CURRENCY_ID); + + // Funding a pool + // utils::give_nft_to::(BORROWER.id(), NFT_A); }); + /* env.state(|| { assert_eq!( pallet_uniques::Pallet::::owner(NFT_A.0, NFT_A.1).unwrap(), BORROWER.id(), ) }); + */ } crate::test_for_runtimes!(all, borrow); diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index bdfb516e04..a955709b07 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -14,6 +14,7 @@ pub mod utils; // Test cases mod cases { mod example; + mod issue; mod loans; } diff --git a/runtime/integration-tests/src/generic/utils/genesis.rs b/runtime/integration-tests/src/generic/utils/genesis.rs index aca4254d8e..6c7c76821c 100644 --- a/runtime/integration-tests/src/generic/utils/genesis.rs +++ b/runtime/integration-tests/src/generic/utils/genesis.rs @@ -86,7 +86,7 @@ pub fn assets(currency_ids: Vec) -> impl GenesisBuild ( AUSD_CURRENCY_ID, AssetMetadata { - decimals: 12, + decimals: AUSD_DECIMALS, name: "Acala Dollar".as_bytes().to_vec(), symbol: "AUSD".as_bytes().to_vec(), existential_deposit: 0 as Balance, @@ -102,10 +102,10 @@ pub fn assets(currency_ids: Vec) -> impl GenesisBuild ]); orml_asset_registry::GenesisConfig:: { - assets: currency_ids + assets: dbg!(currency_ids .into_iter() .map(|id| (id, assets.get(&id).unwrap().clone())) - .collect(), - last_asset_id: Default::default(), // It seems deprecated + .collect()), + last_asset_id: AUSD_CURRENCY_ID, // It seems deprecated } } diff --git a/runtime/integration-tests/src/generic/utils/mod.rs b/runtime/integration-tests/src/generic/utils/mod.rs index d1365552b5..48fb92dc96 100644 --- a/runtime/integration-tests/src/generic/utils/mod.rs +++ b/runtime/integration-tests/src/generic/utils/mod.rs @@ -1,15 +1,21 @@ // Divide this utilties into files when it grows -use cfg_primitives::{AccountId, Balance, CollectionId, ItemId, PoolId}; +use cfg_primitives::{AccountId, Balance, CollectionId, ItemId, PoolId, TrancheId}; +use cfg_traits::investments::TrancheCurrency as _; use cfg_types::{ permissions::{PermissionScope, PoolRole, Role}, - tokens::CurrencyId, + tokens::{CurrencyId, TrancheCurrency}, }; use frame_system::RawOrigin; use sp_runtime::traits::StaticLookup; pub mod genesis; -use crate::generic::runtime::Runtime; +use cfg_types::pools::TrancheMetadata; +use frame_support::BoundedVec; +use pallet_pool_system::tranches::{TrancheInput, TrancheLoc, TrancheType}; +use sp_runtime::{traits::One, AccountId32, Perquintill}; + +use crate::generic::runtime::{Runtime, RuntimeKind}; pub fn give_nft_to(dest: AccountId, (collection_id, item_id): (CollectionId, ItemId)) { pallet_uniques::Pallet::::force_create( @@ -62,3 +68,72 @@ pub fn give_pool_role(dest: AccountId, pool_id: PoolId, role: PoolRo ) .unwrap(); } + +pub fn create_empty_pool(admin: AccountId32, pool_id: PoolId, currency_id: CurrencyId) { + pallet_pool_registry::Pallet::::register( + match T::KIND { + RuntimeKind::Development => RawOrigin::Signed(admin.clone()).into(), + _ => RawOrigin::Root.into(), + }, + admin, + pool_id, + vec![ + TrancheInput { + tranche_type: TrancheType::Residual, + seniority: None, + metadata: TrancheMetadata { + token_name: BoundedVec::default(), + token_symbol: BoundedVec::default(), + }, + }, + TrancheInput { + tranche_type: TrancheType::NonResidual { + interest_rate_per_sec: One::one(), + min_risk_buffer: Perquintill::from_percent(0), + }, + seniority: None, + metadata: TrancheMetadata { + token_name: BoundedVec::default(), + token_symbol: BoundedVec::default(), + }, + }, + ], + currency_id, + Balance::MAX, + None, + BoundedVec::default(), + ) + .unwrap(); +} + +pub fn close_pool_epoch(admin: AccountId32, pool_id: PoolId) { + pallet_pool_system::Pallet::::close_epoch(RawOrigin::Signed(admin.clone()).into(), pool_id) + .unwrap(); +} + +pub fn invest( + investor: AccountId32, + pool_id: PoolId, + tranche_id: TrancheId, + amount: Balance, +) { + pallet_investments::Pallet::::update_invest_order( + RawOrigin::Signed(investor).into(), + TrancheCurrency::generate(pool_id, tranche_id), + amount, + ) + .unwrap(); +} + +// Utilities that does not modify the state +pub mod get { + use super::*; + + pub fn default_tranche_id(pool_id: PoolId) -> TrancheId { + pallet_pool_system::Pool::::get(pool_id) + .unwrap() + .tranches + .tranche_id(TrancheLoc::Index(0)) + .unwrap() + } +} From ab7138b71267a8dded3837759fc5b597708da2f0 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Wed, 18 Oct 2023 13:23:22 +0200 Subject: [PATCH 20/27] fixed issue with asset_registry --- .../src/generic/cases/issue.rs | 23 -------------- .../src/generic/cases/loans.rs | 31 +++++-------------- runtime/integration-tests/src/generic/mod.rs | 1 - .../src/generic/utils/genesis.rs | 30 +++++++++--------- 4 files changed, 22 insertions(+), 63 deletions(-) delete mode 100644 runtime/integration-tests/src/generic/cases/issue.rs diff --git a/runtime/integration-tests/src/generic/cases/issue.rs b/runtime/integration-tests/src/generic/cases/issue.rs deleted file mode 100644 index 1c4e97792b..0000000000 --- a/runtime/integration-tests/src/generic/cases/issue.rs +++ /dev/null @@ -1,23 +0,0 @@ -use crate::generic::{ - environment::Env, - envs::{ - fudge_env::{FudgeEnv, FudgeSupport}, - runtime_env::RuntimeEnv, - }, - runtime::Runtime, - utils::genesis::{self, Genesis, MUSD_CURRENCY_ID}, -}; - -fn what() { - let env = RuntimeEnv::::from_storage( - Genesis::::default() - .add(genesis::assets(vec![MUSD_CURRENCY_ID])) - .storage(), - ); - - env.state(|| { - orml_asset_registry::Pallet::::metadata(MUSD_CURRENCY_ID).unwrap(); - }); -} - -crate::test_for_runtimes!(all, what); diff --git a/runtime/integration-tests/src/generic/cases/loans.rs b/runtime/integration-tests/src/generic/cases/loans.rs index 0a28547f93..a4a488da26 100644 --- a/runtime/integration-tests/src/generic/cases/loans.rs +++ b/runtime/integration-tests/src/generic/cases/loans.rs @@ -12,7 +12,7 @@ use crate::{ runtime::Runtime, utils::{ self, - genesis::{self, Genesis, MUSD_CURRENCY_ID}, + genesis::{self, Genesis, USD6_CURRENCY_ID}, }, }, utils::accounts::Keyring, @@ -31,39 +31,22 @@ fn borrow() { let mut env = RuntimeEnv::::from_storage( Genesis::::default() .add(genesis::balances(T::ExistentialDeposit::get() + FOR_FEES)) + .add(genesis::assets(vec![USD6_CURRENCY_ID])) .add(genesis::tokens(vec![( - MUSD_CURRENCY_ID, - T::ExistentialDeposits::get(&MUSD_CURRENCY_ID), + USD6_CURRENCY_ID, + T::ExistentialDeposits::get(&USD6_CURRENCY_ID), )])) - .add(genesis::assets(vec![MUSD_CURRENCY_ID])) .storage(), ); env.state_mut(|| { // Creating a pool - - /* - orml_asset_registry::Pallet::::metadata( - &MUSD_CURRENCY_ID - ); - */ - - //utils::give_balance_to::(POOL_ADMIN.id(), T::PoolDeposit::get()); - //utils::create_empty_pool::(POOL_ADMIN.id(), POOL_A, - // MUSD_CURRENCY_ID); + utils::give_balance_to::(POOL_ADMIN.id(), T::PoolDeposit::get()); + utils::create_empty_pool::(POOL_ADMIN.id(), POOL_A, USD6_CURRENCY_ID); // Funding a pool - // utils::give_nft_to::(BORROWER.id(), NFT_A); - }); - - /* - env.state(|| { - assert_eq!( - pallet_uniques::Pallet::::owner(NFT_A.0, NFT_A.1).unwrap(), - BORROWER.id(), - ) + utils::give_nft_to::(BORROWER.id(), NFT_A); }); - */ } crate::test_for_runtimes!(all, borrow); diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index a955709b07..bdfb516e04 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -14,7 +14,6 @@ pub mod utils; // Test cases mod cases { mod example; - mod issue; mod loans; } diff --git a/runtime/integration-tests/src/generic/utils/genesis.rs b/runtime/integration-tests/src/generic/utils/genesis.rs index 6c7c76821c..3e0965bc19 100644 --- a/runtime/integration-tests/src/generic/utils/genesis.rs +++ b/runtime/integration-tests/src/generic/utils/genesis.rs @@ -58,22 +58,22 @@ pub fn tokens(values: Vec<(CurrencyId, Balance)>) -> impl GenesisBui } } -pub const MUSD_DECIMALS: u32 = 6; -pub const MUSD_UNIT: Balance = 10u128.pow(MUSD_DECIMALS); -pub const MUSD_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(1); +pub const USD6_DECIMALS: u32 = 6; +pub const USD6_UNIT: Balance = 10u128.pow(USD6_DECIMALS); +pub const USD6_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(1); -pub const AUSD_DECIMALS: u32 = 12; -pub const AUSD_UNIT: Balance = 10u128.pow(AUSD_DECIMALS); -pub const AUSD_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(2); +pub const USD12_DECIMALS: u32 = 12; +pub const USD12_UNIT: Balance = 10u128.pow(USD12_DECIMALS); +pub const USD12_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(2); pub fn assets(currency_ids: Vec) -> impl GenesisBuild { let assets = BTreeMap::from([ ( - MUSD_CURRENCY_ID, + USD6_CURRENCY_ID, AssetMetadata { - decimals: MUSD_DECIMALS, - name: "Mock Dollar".as_bytes().to_vec(), - symbol: "MUSD".as_bytes().to_vec(), + decimals: USD6_DECIMALS, + name: "Mock Dollar with 6 decimals".as_bytes().to_vec(), + symbol: "USD6".as_bytes().to_vec(), existential_deposit: 0 as Balance, location: None, additional: CustomMetadata { @@ -84,11 +84,11 @@ pub fn assets(currency_ids: Vec) -> impl GenesisBuild .encode(), ), ( - AUSD_CURRENCY_ID, + USD12_CURRENCY_ID, AssetMetadata { - decimals: AUSD_DECIMALS, - name: "Acala Dollar".as_bytes().to_vec(), - symbol: "AUSD".as_bytes().to_vec(), + decimals: USD12_DECIMALS, + name: "Mock Dollar 12 with decimals".as_bytes().to_vec(), + symbol: "USD12".as_bytes().to_vec(), existential_deposit: 0 as Balance, location: None, additional: CustomMetadata { @@ -106,6 +106,6 @@ pub fn assets(currency_ids: Vec) -> impl GenesisBuild .into_iter() .map(|id| (id, assets.get(&id).unwrap().clone())) .collect()), - last_asset_id: AUSD_CURRENCY_ID, // It seems deprecated + last_asset_id: Default::default(), // It seems deprecated } } From 5e79525c15b9dde0e3f5f7a1579b65a36b5ca63b Mon Sep 17 00:00:00 2001 From: lemunozm Date: Wed, 18 Oct 2023 14:17:44 +0200 Subject: [PATCH 21/27] add CurrencyInfo genesis utility --- .../src/generic/cases/loans.rs | 16 +-- .../src/generic/utils/genesis.rs | 107 +++++++++++------- 2 files changed, 74 insertions(+), 49 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/loans.rs b/runtime/integration-tests/src/generic/cases/loans.rs index a4a488da26..2dab3c429f 100644 --- a/runtime/integration-tests/src/generic/cases/loans.rs +++ b/runtime/integration-tests/src/generic/cases/loans.rs @@ -1,6 +1,5 @@ use cfg_primitives::{Balance, CollectionId, ItemId, PoolId, CFG}; use frame_support::traits::Get; -use orml_traits::GetByKey; use crate::{ generic::{ @@ -12,7 +11,11 @@ use crate::{ runtime::Runtime, utils::{ self, - genesis::{self, Genesis, USD6_CURRENCY_ID}, + genesis::{ + self, + currency::{CurrencyInfo, Usd6}, + Genesis, + }, }, }, utils::accounts::Keyring, @@ -31,18 +34,15 @@ fn borrow() { let mut env = RuntimeEnv::::from_storage( Genesis::::default() .add(genesis::balances(T::ExistentialDeposit::get() + FOR_FEES)) - .add(genesis::assets(vec![USD6_CURRENCY_ID])) - .add(genesis::tokens(vec![( - USD6_CURRENCY_ID, - T::ExistentialDeposits::get(&USD6_CURRENCY_ID), - )])) + .add(genesis::assets(vec![Usd6::ID])) + .add(genesis::tokens(vec![(Usd6::ID, Usd6::ED)])) .storage(), ); env.state_mut(|| { // Creating a pool utils::give_balance_to::(POOL_ADMIN.id(), T::PoolDeposit::get()); - utils::create_empty_pool::(POOL_ADMIN.id(), POOL_A, USD6_CURRENCY_ID); + utils::create_empty_pool::(POOL_ADMIN.id(), POOL_A, Usd6::ID); // Funding a pool utils::give_nft_to::(BORROWER.id(), NFT_A); diff --git a/runtime/integration-tests/src/generic/utils/genesis.rs b/runtime/integration-tests/src/generic/utils/genesis.rs index 3e0965bc19..fe85e25485 100644 --- a/runtime/integration-tests/src/generic/utils/genesis.rs +++ b/runtime/integration-tests/src/generic/utils/genesis.rs @@ -1,7 +1,7 @@ -use std::{collections::BTreeMap, marker::PhantomData}; +use std::marker::PhantomData; use cfg_primitives::Balance; -use cfg_types::tokens::{AssetMetadata, CurrencyId, CustomMetadata}; +use cfg_types::tokens::{AssetMetadata, CrossChainTransferability, CurrencyId, CustomMetadata}; use codec::Encode; use frame_support::traits::GenesisBuild; use sp_runtime::Storage; @@ -58,54 +58,79 @@ pub fn tokens(values: Vec<(CurrencyId, Balance)>) -> impl GenesisBui } } -pub const USD6_DECIMALS: u32 = 6; -pub const USD6_UNIT: Balance = 10u128.pow(USD6_DECIMALS); -pub const USD6_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(1); +pub fn assets(currency_ids: Vec) -> impl GenesisBuild { + orml_asset_registry::GenesisConfig:: { + assets: currency_ids + .into_iter() + .map(|currency_id| (currency_id, currency::find_metadata(currency_id).encode())) + .collect(), + last_asset_id: Default::default(), // It seems deprecated + } +} -pub const USD12_DECIMALS: u32 = 12; -pub const USD12_UNIT: Balance = 10u128.pow(USD12_DECIMALS); -pub const USD12_CURRENCY_ID: CurrencyId = CurrencyId::ForeignAsset(2); +pub mod currency { + use super::*; -pub fn assets(currency_ids: Vec) -> impl GenesisBuild { - let assets = BTreeMap::from([ - ( - USD6_CURRENCY_ID, - AssetMetadata { - decimals: USD6_DECIMALS, - name: "Mock Dollar with 6 decimals".as_bytes().to_vec(), - symbol: "USD6".as_bytes().to_vec(), - existential_deposit: 0 as Balance, - location: None, - additional: CustomMetadata { - pool_currency: true, - ..Default::default() - }, - } - .encode(), - ), - ( - USD12_CURRENCY_ID, + pub trait CurrencyInfo { + const ID: CurrencyId; + const DECIMALS: u32; + const UNIT: Balance = 10u128.pow(Self::DECIMALS); + const SYMBOL: &'static str; + const NAME: &'static str = Self::SYMBOL; + const LOCATION: Option = None; + const CUSTOM: CustomMetadata; + const ED: Balance = 0; + + fn metadata() -> AssetMetadata { AssetMetadata { - decimals: USD12_DECIMALS, - name: "Mock Dollar 12 with decimals".as_bytes().to_vec(), - symbol: "USD12".as_bytes().to_vec(), - existential_deposit: 0 as Balance, + decimals: Self::DECIMALS, + name: Self::NAME.as_bytes().to_vec(), + symbol: Self::SYMBOL.as_bytes().to_vec(), + existential_deposit: Self::ED, location: None, additional: CustomMetadata { pool_currency: true, ..Default::default() }, } - .encode(), - ), - // Add new currencies here - ]); + } + } - orml_asset_registry::GenesisConfig:: { - assets: dbg!(currency_ids - .into_iter() - .map(|id| (id, assets.get(&id).unwrap().clone())) - .collect()), - last_asset_id: Default::default(), // It seems deprecated + pub struct Usd6; + impl CurrencyInfo for Usd6 { + const CUSTOM: CustomMetadata = CustomMetadata { + pool_currency: true, + ..CONST_DEFAULT_CUSTOM + }; + const DECIMALS: u32 = 6; + const ID: CurrencyId = CurrencyId::ForeignAsset(1); + const SYMBOL: &'static str = "USD6"; + } + + pub struct Usd12; + impl CurrencyInfo for Usd12 { + const CUSTOM: CustomMetadata = CustomMetadata { + pool_currency: true, + ..CONST_DEFAULT_CUSTOM + }; + const DECIMALS: u32 = 12; + const ID: CurrencyId = CurrencyId::ForeignAsset(2); + const SYMBOL: &'static str = "USD12"; + } + + /// Matches default() but for const support + const CONST_DEFAULT_CUSTOM: CustomMetadata = CustomMetadata { + transferability: CrossChainTransferability::None, + mintable: false, + permissioned: false, + pool_currency: false, + }; + + pub fn find_metadata(currency: CurrencyId) -> AssetMetadata { + match currency { + Usd6::ID => Usd6::metadata(), + Usd12::ID => Usd12::metadata(), + _ => panic!("Unsupported currency {currency:?}"), + } } } From 93a0dda202e3a0f6e93ad096a010b6cb46b4d10e Mon Sep 17 00:00:00 2001 From: lemunozm Date: Fri, 20 Oct 2023 09:53:01 +0200 Subject: [PATCH 22/27] extend loan tests, fix block by seconds --- .../src/generic/cases/loans.rs | 47 ++++++++++++++----- .../src/generic/environment.rs | 27 ++++++----- runtime/integration-tests/src/generic/mod.rs | 1 + .../integration-tests/src/generic/runtime.rs | 19 +++++++- .../src/generic/utils/genesis.rs | 14 +++++- .../src/generic/utils/mod.rs | 6 +-- 6 files changed, 84 insertions(+), 30 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/loans.rs b/runtime/integration-tests/src/generic/cases/loans.rs index 2dab3c429f..0a08e08233 100644 --- a/runtime/integration-tests/src/generic/cases/loans.rs +++ b/runtime/integration-tests/src/generic/cases/loans.rs @@ -1,19 +1,18 @@ -use cfg_primitives::{Balance, CollectionId, ItemId, PoolId, CFG}; +use cfg_primitives::{Balance, CollectionId, ItemId, PoolId}; +use cfg_traits::Seconds; +use cfg_types::permissions::PoolRole; use frame_support::traits::Get; use crate::{ generic::{ environment::{Blocks, Env}, - envs::{ - fudge_env::{FudgeEnv, FudgeSupport}, - runtime_env::RuntimeEnv, - }, + envs::runtime_env::RuntimeEnv, runtime::Runtime, utils::{ self, genesis::{ self, - currency::{CurrencyInfo, Usd6}, + currency::{cfg, usd6, CurrencyInfo, Usd6}, Genesis, }, }, @@ -25,13 +24,15 @@ const POOL_ADMIN: Keyring = Keyring::Admin; const INVESTOR: Keyring = Keyring::Alice; const BORROWER: Keyring = Keyring::Bob; -const FOR_FEES: Balance = 1 * CFG; +const FOR_FEES: Balance = cfg(1); const POOL_A: PoolId = 23; const NFT_A: (CollectionId, ItemId) = (1, ItemId(10)); -fn borrow() { - let mut env = RuntimeEnv::::from_storage( +const POOL_BALANCE: Balance = usd6(1_000_000); + +fn initialize_state_for_loans, T: Runtime>() -> Environment { + let mut env = Environment::from_storage( Genesis::::default() .add(genesis::balances(T::ExistentialDeposit::get() + FOR_FEES)) .add(genesis::assets(vec![Usd6::ID])) @@ -41,12 +42,36 @@ fn borrow() { env.state_mut(|| { // Creating a pool - utils::give_balance_to::(POOL_ADMIN.id(), T::PoolDeposit::get()); + utils::give_balance::(POOL_ADMIN.id(), T::PoolDeposit::get()); utils::create_empty_pool::(POOL_ADMIN.id(), POOL_A, Usd6::ID); // Funding a pool - utils::give_nft_to::(BORROWER.id(), NFT_A); + let tranche_id = T::tranche_id(POOL_A, 0).unwrap(); + let tranche_investor = PoolRole::TrancheInvestor(tranche_id, Seconds::MAX); + utils::give_pool_role::(INVESTOR.id(), POOL_A, tranche_investor); + utils::give_tokens::(INVESTOR.id(), Usd6::ID, POOL_BALANCE); + utils::invest::(INVESTOR.id(), POOL_A, tranche_id, POOL_BALANCE); }); + + env.pass(Blocks::BySeconds(T::DefaultMinEpochTime::get())); + + env.state_mut(|| { + // New epoch with the investor funds available + utils::close_pool_epoch::(POOL_ADMIN.id(), POOL_A); + + // Preparing borrower + utils::give_pool_role::(BORROWER.id(), POOL_A, PoolRole::Borrower); + utils::give_nft::(BORROWER.id(), NFT_A); + }); + + env +} + +fn borrow() { + let mut env = initialize_state_for_loans::, T>(); + + // Submit Loan::create() + // Submit Loan::borrow() } crate::test_for_runtimes!(all, borrow); diff --git a/runtime/integration-tests/src/generic/environment.rs b/runtime/integration-tests/src/generic/environment.rs index d56f233de9..b48df844c5 100644 --- a/runtime/integration-tests/src/generic/environment.rs +++ b/runtime/integration-tests/src/generic/environment.rs @@ -1,9 +1,9 @@ use cfg_primitives::{Address, Balance, BlockNumber, Index}; -use cfg_traits::Seconds; +use cfg_traits::{IntoSeconds, Seconds}; use codec::Encode; use sp_runtime::{ generic::{Era, SignedPayload}, - traits::{Block, Extrinsic}, + traits::{Block, Extrinsic, Get}, DispatchError, DispatchResult, MultiSignature, Storage, }; @@ -48,18 +48,19 @@ pub trait Env { let (next, end_block) = self.state(|| { let next = frame_system::Pallet::::block_number() + 1; - let end_block = match blocks { - Blocks::ByNumber(n) => next + n, - Blocks::BySeconds(secs) => { - let blocks = secs / pallet_aura::Pallet::::slot_duration(); - if blocks % pallet_aura::Pallet::::slot_duration() != 0 { - blocks as BlockNumber + 1 - } else { - blocks as BlockNumber + let end_block = next + + match blocks { + Blocks::ByNumber(n) => n, + Blocks::BySeconds(secs) => { + let n = secs / pallet_aura::Pallet::::slot_duration().into_seconds(); + if n % pallet_aura::Pallet::::slot_duration() != 0 { + n as BlockNumber + 1 + } else { + n as BlockNumber + } } - } - Blocks::UntilEvent { limit, .. } => limit, - }; + Blocks::UntilEvent { limit, .. } => limit, + }; (next, end_block) }); diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index bdfb516e04..14b5932e1b 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -76,6 +76,7 @@ macro_rules! impl_runtime { ($runtime_path:ident, $kind:ident) => { impl Runtime for $runtime_path::Runtime { type Block = $runtime_path::Block; + type MaxTranchesExt = $runtime_path::MaxTranches; type RuntimeCallExt = $runtime_path::RuntimeCall; type RuntimeEventExt = $runtime_path::RuntimeEvent; diff --git a/runtime/integration-tests/src/generic/runtime.rs b/runtime/integration-tests/src/generic/runtime.rs index 6fa8988204..7e2466ae15 100644 --- a/runtime/integration-tests/src/generic/runtime.rs +++ b/runtime/integration-tests/src/generic/runtime.rs @@ -6,6 +6,7 @@ use cfg_primitives::{ }; use cfg_traits::Millis; use cfg_types::{ + fixed_point::Quantity, permissions::{PermissionScope, Role}, tokens::{CurrencyId, CustomMetadata, TrancheCurrency}, }; @@ -21,7 +22,10 @@ use runtime_common::{ fees::{DealWithFees, WeightToFee}, }; use sp_core::H256; -use sp_runtime::traits::{AccountIdLookup, Block, Dispatchable, Member}; +use sp_runtime::{ + scale_info::TypeInfo, + traits::{AccountIdLookup, Block, Dispatchable, Get, Member}, +}; /// Kind of runtime to check in runtime time pub enum RuntimeKind { @@ -30,6 +34,8 @@ pub enum RuntimeKind { Centrifuge, } +use codec::Codec; + /// Runtime configuration pub trait Runtime: Send @@ -46,15 +52,18 @@ pub trait Runtime: Balance = Balance, PoolId = PoolId, TrancheId = TrancheId, + BalanceRatio = Quantity, + MaxTranches = Self::MaxTranchesExt, > + pallet_balances::Config - + pallet_investments::Config + pallet_pool_registry::Config< CurrencyId = CurrencyId, PoolId = PoolId, Balance = Balance, + MaxTranches = Self::MaxTranchesExt, ModifyPool = pallet_pool_system::Pallet, ModifyWriteOffPolicy = pallet_loans::Pallet, > + pallet_permissions::Config> + + pallet_investments::Config + pallet_loans::Config< Balance = Balance, PoolId = PoolId, @@ -88,6 +97,10 @@ pub trait Runtime: LoanId, pallet_loans::entities::loans::ActiveLoanInfo, > + + apis::runtime_decl_for_PoolsApi::PoolsApiV1< + Self::Block, + PoolId, TrancheId, Balance, CurrencyId, Quantity, Self::MaxTranchesExt, + > { /// Just the RuntimeCall type, but redefined with extra bounds. /// You can add `From` bounds in order to convert pallet calls to @@ -137,6 +150,8 @@ pub trait Runtime: >, >; + type MaxTranchesExt: Codec + Get + Member + PartialOrd + TypeInfo; + /// Value to differentiate the runtime in tests. const KIND: RuntimeKind; } diff --git a/runtime/integration-tests/src/generic/utils/genesis.rs b/runtime/integration-tests/src/generic/utils/genesis.rs index fe85e25485..e37fe3df17 100644 --- a/runtime/integration-tests/src/generic/utils/genesis.rs +++ b/runtime/integration-tests/src/generic/utils/genesis.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use cfg_primitives::Balance; +use cfg_primitives::{Balance, CFG}; use cfg_types::tokens::{AssetMetadata, CrossChainTransferability, CurrencyId, CustomMetadata}; use codec::Encode; use frame_support::traits::GenesisBuild; @@ -71,6 +71,10 @@ pub fn assets(currency_ids: Vec) -> impl GenesisBuild pub mod currency { use super::*; + pub const fn cfg(amount: Balance) -> Balance { + amount * CFG + } + pub trait CurrencyInfo { const ID: CurrencyId; const DECIMALS: u32; @@ -107,6 +111,10 @@ pub mod currency { const SYMBOL: &'static str = "USD6"; } + pub const fn usd6(amount: Balance) -> Balance { + amount * Usd6::UNIT + } + pub struct Usd12; impl CurrencyInfo for Usd12 { const CUSTOM: CustomMetadata = CustomMetadata { @@ -118,6 +126,10 @@ pub mod currency { const SYMBOL: &'static str = "USD12"; } + pub const fn usd12(amount: Balance) -> Balance { + amount * Usd12::UNIT + } + /// Matches default() but for const support const CONST_DEFAULT_CUSTOM: CustomMetadata = CustomMetadata { transferability: CrossChainTransferability::None, diff --git a/runtime/integration-tests/src/generic/utils/mod.rs b/runtime/integration-tests/src/generic/utils/mod.rs index 48fb92dc96..75e6a869c8 100644 --- a/runtime/integration-tests/src/generic/utils/mod.rs +++ b/runtime/integration-tests/src/generic/utils/mod.rs @@ -17,7 +17,7 @@ use sp_runtime::{traits::One, AccountId32, Perquintill}; use crate::generic::runtime::{Runtime, RuntimeKind}; -pub fn give_nft_to(dest: AccountId, (collection_id, item_id): (CollectionId, ItemId)) { +pub fn give_nft(dest: AccountId, (collection_id, item_id): (CollectionId, ItemId)) { pallet_uniques::Pallet::::force_create( RawOrigin::Root.into(), collection_id, @@ -35,7 +35,7 @@ pub fn give_nft_to(dest: AccountId, (collection_id, item_id): (Colle .unwrap() } -pub fn give_balance_to(dest: AccountId, amount: Balance) { +pub fn give_balance(dest: AccountId, amount: Balance) { let data = pallet_balances::Account::::get(dest.clone()); pallet_balances::Pallet::::set_balance( RawOrigin::Root.into(), @@ -46,7 +46,7 @@ pub fn give_balance_to(dest: AccountId, amount: Balance) { .unwrap(); } -pub fn give_token_to(dest: AccountId, currency_id: CurrencyId, amount: Balance) { +pub fn give_tokens(dest: AccountId, currency_id: CurrencyId, amount: Balance) { let data = orml_tokens::Accounts::::get(dest.clone(), currency_id); orml_tokens::Pallet::::set_balance( RawOrigin::Root.into(), From 6b29b2bb695f2c5dfbd9ff628b3f2f031fef6940 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Fri, 20 Oct 2023 10:18:29 +0200 Subject: [PATCH 23/27] Api from Runtime into an associated type for expliciteness --- .../src/generic/cases/example.rs | 13 +++-- .../src/generic/cases/loans.rs | 3 +- .../src/generic/environment.rs | 2 +- .../src/generic/envs/runtime_env.rs | 12 +++-- runtime/integration-tests/src/generic/mod.rs | 8 ++- .../integration-tests/src/generic/runtime.rs | 52 +++++++++++-------- 6 files changed, 54 insertions(+), 36 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/example.rs b/runtime/integration-tests/src/generic/cases/example.rs index e4e8fb7dac..61e32ef89d 100644 --- a/runtime/integration-tests/src/generic/cases/example.rs +++ b/runtime/integration-tests/src/generic/cases/example.rs @@ -1,5 +1,6 @@ use cfg_primitives::{Balance, CFG}; use frame_support::traits::Get; +use sp_api::runtime_decl_for_Core::CoreV4; use crate::{ generic::{ @@ -130,10 +131,12 @@ fn call_api() { let env = RuntimeEnv::::from_storage(Default::default()); env.state(|| { - // Call to Core::version() API. - // It's automatically implemented by the runtime T, so you can easily do: - // T::version() - assert_eq!(T::version(), ::Version::get()); + // If imported the trait: sp_api::runtime_decl_for_Core::CoreV4, + // you can easily do: T::Api::version() + assert_eq!( + T::Api::version(), + ::Version::get() + ); }) } @@ -148,7 +151,7 @@ fn fudge_call_api() { let result = api.version(&latest).unwrap(); - assert_eq!(result, T::version()); + assert_eq!(result, T::Api::version()); assert_eq!(result, ::Version::get()); }) } diff --git a/runtime/integration-tests/src/generic/cases/loans.rs b/runtime/integration-tests/src/generic/cases/loans.rs index 0a08e08233..de240ff00b 100644 --- a/runtime/integration-tests/src/generic/cases/loans.rs +++ b/runtime/integration-tests/src/generic/cases/loans.rs @@ -2,6 +2,7 @@ use cfg_primitives::{Balance, CollectionId, ItemId, PoolId}; use cfg_traits::Seconds; use cfg_types::permissions::PoolRole; use frame_support::traits::Get; +use runtime_common::apis::runtime_decl_for_PoolsApi::PoolsApiV1; use crate::{ generic::{ @@ -46,7 +47,7 @@ fn initialize_state_for_loans, T: Runtime>() -> Environment utils::create_empty_pool::(POOL_ADMIN.id(), POOL_A, Usd6::ID); // Funding a pool - let tranche_id = T::tranche_id(POOL_A, 0).unwrap(); + let tranche_id = T::Api::tranche_id(POOL_A, 0).unwrap(); let tranche_investor = PoolRole::TrancheInvestor(tranche_id, Seconds::MAX); utils::give_pool_role::(INVESTOR.id(), POOL_A, tranche_investor); utils::give_tokens::(INVESTOR.id(), Usd6::ID, POOL_BALANCE); diff --git a/runtime/integration-tests/src/generic/environment.rs b/runtime/integration-tests/src/generic/environment.rs index b48df844c5..77ee636071 100644 --- a/runtime/integration-tests/src/generic/environment.rs +++ b/runtime/integration-tests/src/generic/environment.rs @@ -3,7 +3,7 @@ use cfg_traits::{IntoSeconds, Seconds}; use codec::Encode; use sp_runtime::{ generic::{Era, SignedPayload}, - traits::{Block, Extrinsic, Get}, + traits::{Block, Extrinsic}, DispatchError, DispatchResult, MultiSignature, Storage, }; diff --git a/runtime/integration-tests/src/generic/envs/runtime_env.rs b/runtime/integration-tests/src/generic/envs/runtime_env.rs index 26c372a501..fca028b81c 100644 --- a/runtime/integration-tests/src/generic/envs/runtime_env.rs +++ b/runtime/integration-tests/src/generic/envs/runtime_env.rs @@ -9,6 +9,8 @@ use frame_support::{ inherent::{InherentData, ProvideInherent}, traits::GenesisBuild, }; +use sp_api::runtime_decl_for_Core::CoreV4; +use sp_block_builder::runtime_decl_for_BlockBuilder::BlockBuilderV6; use sp_consensus_aura::{Slot, AURA_ENGINE_ID}; use sp_core::{sr25519::Public, H256}; use sp_runtime::{traits::Extrinsic, Digest, DigestItem, DispatchError, DispatchResult, Storage}; @@ -60,7 +62,7 @@ impl Env for RuntimeEnv { utils::create_extrinsic::(who, call, nonce) }); - self.state_mut(|| T::apply_extrinsic(extrinsic).unwrap())?; + self.state_mut(|| T::Api::apply_extrinsic(extrinsic).unwrap())?; let fee = self .find_event(|e| match e { @@ -98,7 +100,7 @@ impl Env for RuntimeEnv { fn __priv_build_block(&mut self, i: BlockNumber) { self.process_pending_extrinsics(); self.state_mut(|| { - T::finalize_block(); + T::Api::finalize_block(); Self::prepare_block(i); }); } @@ -114,7 +116,7 @@ impl RuntimeEnv { utils::create_extrinsic::(who, call, nonce) }); - self.state_mut(|| T::apply_extrinsic(extrinsic).unwrap().unwrap()); + self.state_mut(|| T::Api::apply_extrinsic(extrinsic).unwrap().unwrap()); } } @@ -132,7 +134,7 @@ impl RuntimeEnv { parent_hash: H256::default(), }; - T::initialize_block(&header); + T::Api::initialize_block(&header); let timestamp = i as u64 * pallet_aura::Pallet::::slot_duration(); let inherent_extrinsics = vec![ @@ -141,7 +143,7 @@ impl RuntimeEnv { ]; for extrinsic in inherent_extrinsics { - T::apply_extrinsic(extrinsic).unwrap().unwrap(); + T::Api::apply_extrinsic(extrinsic).unwrap().unwrap(); } } diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index 14b5932e1b..45d1bbf9a0 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -17,7 +17,7 @@ mod cases { mod loans; } -use runtime::{Runtime, RuntimeKind}; +use runtime::{Api, Runtime, RuntimeKind}; /// Generate tests for the specified runtimes or all runtimes. /// Usage @@ -74,9 +74,13 @@ macro_rules! test_for_runtimes { /// Implements the `Runtime` trait for a runtime macro_rules! impl_runtime { ($runtime_path:ident, $kind:ident) => { + impl Api for $runtime_path::Runtime { + type MaxTranchesExt = $runtime_path::MaxTranches; + } + impl Runtime for $runtime_path::Runtime { + type Api = Self; type Block = $runtime_path::Block; - type MaxTranchesExt = $runtime_path::MaxTranches; type RuntimeCallExt = $runtime_path::RuntimeCall; type RuntimeEventExt = $runtime_path::RuntimeEvent; diff --git a/runtime/integration-tests/src/generic/runtime.rs b/runtime/integration-tests/src/generic/runtime.rs index 7e2466ae15..0e0bb2d9ce 100644 --- a/runtime/integration-tests/src/generic/runtime.rs +++ b/runtime/integration-tests/src/generic/runtime.rs @@ -10,6 +10,7 @@ use cfg_types::{ permissions::{PermissionScope, Role}, tokens::{CurrencyId, CustomMetadata, TrancheCurrency}, }; +use codec::Codec; use fp_self_contained::{SelfContainedCall, UncheckedExtrinsic}; use frame_support::{ dispatch::{DispatchInfo, GetDispatchInfo, PostDispatchInfo}, @@ -34,7 +35,26 @@ pub enum RuntimeKind { Centrifuge, } -use codec::Codec; +pub trait Api: + sp_api::runtime_decl_for_Core::CoreV4 + + sp_block_builder::runtime_decl_for_BlockBuilder::BlockBuilderV6 + + apis::runtime_decl_for_LoansApi::LoansApiV1< + T::Block, + PoolId, + LoanId, + pallet_loans::entities::loans::ActiveLoanInfo, + > + apis::runtime_decl_for_PoolsApi::PoolsApiV1< + T::Block, + PoolId, + TrancheId, + Balance, + CurrencyId, + Quantity, + Self::MaxTranchesExt, + > +{ + type MaxTranchesExt: Codec + Get + Member + PartialOrd + TypeInfo; +} /// Runtime configuration pub trait Runtime: @@ -52,14 +72,14 @@ pub trait Runtime: Balance = Balance, PoolId = PoolId, TrancheId = TrancheId, - BalanceRatio = Quantity, - MaxTranches = Self::MaxTranchesExt, + BalanceRatio = Quantity, + MaxTranches = >::MaxTranchesExt, > + pallet_balances::Config + pallet_pool_registry::Config< CurrencyId = CurrencyId, PoolId = PoolId, Balance = Balance, - MaxTranches = Self::MaxTranchesExt, + MaxTranches = >::MaxTranchesExt, ModifyPool = pallet_pool_system::Pallet, ModifyWriteOffPolicy = pallet_loans::Pallet, > + pallet_permissions::Config> @@ -80,27 +100,13 @@ pub trait Runtime: + pallet_authorship::Config + pallet_treasury::Config> + pallet_transaction_payment::Config< - AccountId = AccountId, + AccountId = AccountId, WeightToFee = WeightToFee, OnChargeTransaction = CurrencyAdapter, DealWithFees>, > + pallet_restricted_tokens::Config< Balance = Balance, NativeFungible = pallet_balances::Pallet, > + cumulus_pallet_parachain_system::Config - - // APIS: - + sp_api::runtime_decl_for_Core::CoreV4 - + sp_block_builder::runtime_decl_for_BlockBuilder::BlockBuilderV6 - + apis::runtime_decl_for_LoansApi::LoansApiV1< - Self::Block, - PoolId, - LoanId, - pallet_loans::entities::loans::ActiveLoanInfo, - > - + apis::runtime_decl_for_PoolsApi::PoolsApiV1< - Self::Block, - PoolId, TrancheId, Balance, CurrencyId, Quantity, Self::MaxTranchesExt, - > { /// Just the RuntimeCall type, but redefined with extra bounds. /// You can add `From` bounds in order to convert pallet calls to @@ -112,7 +118,9 @@ pub trait Runtime: + From> + From> + From> - + From> + Sync + Send; + + From> + + Sync + + Send; /// Just the RuntimeEvent type, but redefined with extra bounds. /// You can add `TryInto` and `From` bounds in order to convert pallet @@ -131,7 +139,7 @@ pub trait Runtime: /// Block used by the runtime type Block: Block< - Hash = H256, + Hash = H256, Header = Header, Extrinsic = UncheckedExtrinsic< Address, @@ -150,7 +158,7 @@ pub trait Runtime: >, >; - type MaxTranchesExt: Codec + Get + Member + PartialOrd + TypeInfo; + type Api: Api; /// Value to differentiate the runtime in tests. const KIND: RuntimeKind; From 83bd44cd5426c68048a8464d3bfc67640285a825 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Fri, 20 Oct 2023 10:55:49 +0200 Subject: [PATCH 24/27] minor changes --- .../src/generic/cases/loans.rs | 6 +-- runtime/integration-tests/src/generic/mod.rs | 7 +-- .../integration-tests/src/generic/runtime.rs | 52 +++++++++---------- .../src/generic/utils/mod.rs | 15 +----- 4 files changed, 31 insertions(+), 49 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/loans.rs b/runtime/integration-tests/src/generic/cases/loans.rs index de240ff00b..1de6e67cdf 100644 --- a/runtime/integration-tests/src/generic/cases/loans.rs +++ b/runtime/integration-tests/src/generic/cases/loans.rs @@ -30,7 +30,7 @@ const FOR_FEES: Balance = cfg(1); const POOL_A: PoolId = 23; const NFT_A: (CollectionId, ItemId) = (1, ItemId(10)); -const POOL_BALANCE: Balance = usd6(1_000_000); +const EXPECTED_POOL_BALANCE: Balance = usd6(1_000_000); fn initialize_state_for_loans, T: Runtime>() -> Environment { let mut env = Environment::from_storage( @@ -50,8 +50,8 @@ fn initialize_state_for_loans, T: Runtime>() -> Environment let tranche_id = T::Api::tranche_id(POOL_A, 0).unwrap(); let tranche_investor = PoolRole::TrancheInvestor(tranche_id, Seconds::MAX); utils::give_pool_role::(INVESTOR.id(), POOL_A, tranche_investor); - utils::give_tokens::(INVESTOR.id(), Usd6::ID, POOL_BALANCE); - utils::invest::(INVESTOR.id(), POOL_A, tranche_id, POOL_BALANCE); + utils::give_tokens::(INVESTOR.id(), Usd6::ID, EXPECTED_POOL_BALANCE); + utils::invest::(INVESTOR.id(), POOL_A, tranche_id, EXPECTED_POOL_BALANCE); }); env.pass(Blocks::BySeconds(T::DefaultMinEpochTime::get())); diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index 45d1bbf9a0..8d62d5ee0a 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -17,7 +17,7 @@ mod cases { mod loans; } -use runtime::{Api, Runtime, RuntimeKind}; +use runtime::{Runtime, RuntimeKind}; /// Generate tests for the specified runtimes or all runtimes. /// Usage @@ -74,13 +74,10 @@ macro_rules! test_for_runtimes { /// Implements the `Runtime` trait for a runtime macro_rules! impl_runtime { ($runtime_path:ident, $kind:ident) => { - impl Api for $runtime_path::Runtime { - type MaxTranchesExt = $runtime_path::MaxTranches; - } - impl Runtime for $runtime_path::Runtime { type Api = Self; type Block = $runtime_path::Block; + type MaxTranchesExt = $runtime_path::MaxTranches; type RuntimeCallExt = $runtime_path::RuntimeCall; type RuntimeEventExt = $runtime_path::RuntimeEvent; diff --git a/runtime/integration-tests/src/generic/runtime.rs b/runtime/integration-tests/src/generic/runtime.rs index 0e0bb2d9ce..d8e6889624 100644 --- a/runtime/integration-tests/src/generic/runtime.rs +++ b/runtime/integration-tests/src/generic/runtime.rs @@ -35,27 +35,6 @@ pub enum RuntimeKind { Centrifuge, } -pub trait Api: - sp_api::runtime_decl_for_Core::CoreV4 - + sp_block_builder::runtime_decl_for_BlockBuilder::BlockBuilderV6 - + apis::runtime_decl_for_LoansApi::LoansApiV1< - T::Block, - PoolId, - LoanId, - pallet_loans::entities::loans::ActiveLoanInfo, - > + apis::runtime_decl_for_PoolsApi::PoolsApiV1< - T::Block, - PoolId, - TrancheId, - Balance, - CurrencyId, - Quantity, - Self::MaxTranchesExt, - > -{ - type MaxTranchesExt: Codec + Get + Member + PartialOrd + TypeInfo; -} - /// Runtime configuration pub trait Runtime: Send @@ -73,13 +52,13 @@ pub trait Runtime: PoolId = PoolId, TrancheId = TrancheId, BalanceRatio = Quantity, - MaxTranches = >::MaxTranchesExt, + MaxTranches = Self::MaxTranchesExt, > + pallet_balances::Config + pallet_pool_registry::Config< CurrencyId = CurrencyId, PoolId = PoolId, Balance = Balance, - MaxTranches = >::MaxTranchesExt, + MaxTranches = Self::MaxTranchesExt, ModifyPool = pallet_pool_system::Pallet, ModifyWriteOffPolicy = pallet_loans::Pallet, > + pallet_permissions::Config> @@ -115,12 +94,13 @@ pub trait Runtime: + Dispatchable + GetDispatchInfo + SelfContainedCall + + Sync + + Send + From> + From> + From> - + From> - + Sync - + Send; + + From> + + From>; /// Just the RuntimeEvent type, but redefined with extra bounds. /// You can add `TryInto` and `From` bounds in order to convert pallet @@ -158,7 +138,25 @@ pub trait Runtime: >, >; - type Api: Api; + /// You can extend this bounds to give extra API support + type Api: sp_api::runtime_decl_for_Core::CoreV4 + + sp_block_builder::runtime_decl_for_BlockBuilder::BlockBuilderV6 + + apis::runtime_decl_for_LoansApi::LoansApiV1< + Self::Block, + PoolId, + LoanId, + pallet_loans::entities::loans::ActiveLoanInfo, + > + apis::runtime_decl_for_PoolsApi::PoolsApiV1< + Self::Block, + PoolId, + TrancheId, + Balance, + CurrencyId, + Quantity, + Self::MaxTranchesExt, + >; + + type MaxTranchesExt: Codec + Get + Member + PartialOrd + TypeInfo; /// Value to differentiate the runtime in tests. const KIND: RuntimeKind; diff --git a/runtime/integration-tests/src/generic/utils/mod.rs b/runtime/integration-tests/src/generic/utils/mod.rs index 75e6a869c8..5fadaea642 100644 --- a/runtime/integration-tests/src/generic/utils/mod.rs +++ b/runtime/integration-tests/src/generic/utils/mod.rs @@ -12,7 +12,7 @@ pub mod genesis; use cfg_types::pools::TrancheMetadata; use frame_support::BoundedVec; -use pallet_pool_system::tranches::{TrancheInput, TrancheLoc, TrancheType}; +use pallet_pool_system::tranches::{TrancheInput, TrancheType}; use sp_runtime::{traits::One, AccountId32, Perquintill}; use crate::generic::runtime::{Runtime, RuntimeKind}; @@ -124,16 +124,3 @@ pub fn invest( ) .unwrap(); } - -// Utilities that does not modify the state -pub mod get { - use super::*; - - pub fn default_tranche_id(pool_id: PoolId) -> TrancheId { - pallet_pool_system::Pool::::get(pool_id) - .unwrap() - .tranches - .tranche_id(TrancheLoc::Index(0)) - .unwrap() - } -} From ed92aab5c2ebf9abf10ff481b32ca2db554e9689 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Fri, 20 Oct 2023 16:54:10 +0200 Subject: [PATCH 25/27] fix and extend loan testing --- .../src/generic/cases/loans.rs | 67 +++++++++++++++++-- .../integration-tests/src/generic/runtime.rs | 4 +- .../src/generic/utils/mod.rs | 20 ++++-- 3 files changed, 79 insertions(+), 12 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/loans.rs b/runtime/integration-tests/src/generic/cases/loans.rs index 1de6e67cdf..fc5f4024c6 100644 --- a/runtime/integration-tests/src/generic/cases/loans.rs +++ b/runtime/integration-tests/src/generic/cases/loans.rs @@ -1,7 +1,23 @@ -use cfg_primitives::{Balance, CollectionId, ItemId, PoolId}; -use cfg_traits::Seconds; +use cfg_primitives::{Balance, CollectionId, ItemId, PoolId, SECONDS_PER_YEAR}; +use cfg_traits::{ + interest::{CompoundingSchedule, InterestRate}, + Seconds, TimeAsSecs, +}; use cfg_types::permissions::PoolRole; use frame_support::traits::Get; +use pallet_loans::{ + entities::{ + loans::LoanInfo, + pricing::{ + internal::{InternalPricing, MaxBorrowAmount as IntMaxBorrowAmount}, + Pricing, + }, + }, + types::{ + valuation::ValuationMethod, BorrowRestrictions, InterestPayments, LoanRestrictions, + Maturity, PayDownSchedule, RepayRestrictions, RepaymentSchedule, + }, +}; use runtime_common::apis::runtime_decl_for_PoolsApi::PoolsApiV1; use crate::{ @@ -16,20 +32,20 @@ use crate::{ currency::{cfg, usd6, CurrencyInfo, Usd6}, Genesis, }, + POOL_MIN_EPOCH_TIME, }, }, - utils::accounts::Keyring, + utils::{accounts::Keyring, tokens::rate_from_percent}, }; const POOL_ADMIN: Keyring = Keyring::Admin; const INVESTOR: Keyring = Keyring::Alice; const BORROWER: Keyring = Keyring::Bob; -const FOR_FEES: Balance = cfg(1); - const POOL_A: PoolId = 23; const NFT_A: (CollectionId, ItemId) = (1, ItemId(10)); +const FOR_FEES: Balance = cfg(1); const EXPECTED_POOL_BALANCE: Balance = usd6(1_000_000); fn initialize_state_for_loans, T: Runtime>() -> Environment { @@ -54,7 +70,7 @@ fn initialize_state_for_loans, T: Runtime>() -> Environment utils::invest::(INVESTOR.id(), POOL_A, tranche_id, EXPECTED_POOL_BALANCE); }); - env.pass(Blocks::BySeconds(T::DefaultMinEpochTime::get())); + env.pass(Blocks::BySeconds(POOL_MIN_EPOCH_TIME)); env.state_mut(|| { // New epoch with the investor funds available @@ -71,6 +87,45 @@ fn initialize_state_for_loans, T: Runtime>() -> Environment fn borrow() { let mut env = initialize_state_for_loans::, T>(); + let info = env.state(|| { + let now = as TimeAsSecs>::now(); + LoanInfo { + schedule: RepaymentSchedule { + maturity: Maturity::Fixed { + date: now + SECONDS_PER_YEAR, + extension: SECONDS_PER_YEAR / 2, + }, + interest_payments: InterestPayments::None, + pay_down_schedule: PayDownSchedule::None, + }, + interest_rate: InterestRate::Fixed { + rate_per_year: rate_from_percent(20), + compounding: CompoundingSchedule::Secondly, + }, + collateral: NFT_A, + pricing: Pricing::Internal(InternalPricing { + collateral_value: 100_000, + max_borrow_amount: IntMaxBorrowAmount::UpToTotalBorrowed { + advance_rate: rate_from_percent(100), + }, + valuation_method: ValuationMethod::OutstandingDebt, + }), + restrictions: LoanRestrictions { + borrows: BorrowRestrictions::NotWrittenOff, + repayments: RepayRestrictions::None, + }, + } + }); + + env.submit_now( + BORROWER, + pallet_loans::Call::create { + pool_id: POOL_A, + info: info, + }, + ) + .unwrap(); + // Submit Loan::create() // Submit Loan::borrow() } diff --git a/runtime/integration-tests/src/generic/runtime.rs b/runtime/integration-tests/src/generic/runtime.rs index d8e6889624..7ca7b820ed 100644 --- a/runtime/integration-tests/src/generic/runtime.rs +++ b/runtime/integration-tests/src/generic/runtime.rs @@ -6,7 +6,7 @@ use cfg_primitives::{ }; use cfg_traits::Millis; use cfg_types::{ - fixed_point::Quantity, + fixed_point::{Quantity, Rate}, permissions::{PermissionScope, Role}, tokens::{CurrencyId, CustomMetadata, TrancheCurrency}, }; @@ -68,6 +68,7 @@ pub trait Runtime: PoolId = PoolId, CollectionId = CollectionId, ItemId = ItemId, + Rate = Rate, > + orml_tokens::Config + orml_asset_registry::Config< AssetId = CurrencyId, @@ -100,6 +101,7 @@ pub trait Runtime: + From> + From> + From> + + From> + From>; /// Just the RuntimeEvent type, but redefined with extra bounds. diff --git a/runtime/integration-tests/src/generic/utils/mod.rs b/runtime/integration-tests/src/generic/utils/mod.rs index 5fadaea642..8bbd9c6920 100644 --- a/runtime/integration-tests/src/generic/utils/mod.rs +++ b/runtime/integration-tests/src/generic/utils/mod.rs @@ -1,7 +1,7 @@ // Divide this utilties into files when it grows use cfg_primitives::{AccountId, Balance, CollectionId, ItemId, PoolId, TrancheId}; -use cfg_traits::investments::TrancheCurrency as _; +use cfg_traits::{investments::TrancheCurrency as _, Seconds}; use cfg_types::{ permissions::{PermissionScope, PoolRole, Role}, tokens::{CurrencyId, TrancheCurrency}, @@ -13,10 +13,12 @@ pub mod genesis; use cfg_types::pools::TrancheMetadata; use frame_support::BoundedVec; use pallet_pool_system::tranches::{TrancheInput, TrancheType}; -use sp_runtime::{traits::One, AccountId32, Perquintill}; +use sp_runtime::{traits::One, Perquintill}; use crate::generic::runtime::{Runtime, RuntimeKind}; +pub const POOL_MIN_EPOCH_TIME: Seconds = 24; + pub fn give_nft(dest: AccountId, (collection_id, item_id): (CollectionId, ItemId)) { pallet_uniques::Pallet::::force_create( RawOrigin::Root.into(), @@ -69,7 +71,7 @@ pub fn give_pool_role(dest: AccountId, pool_id: PoolId, role: PoolRo .unwrap(); } -pub fn create_empty_pool(admin: AccountId32, pool_id: PoolId, currency_id: CurrencyId) { +pub fn create_empty_pool(admin: AccountId, pool_id: PoolId, currency_id: CurrencyId) { pallet_pool_registry::Pallet::::register( match T::KIND { RuntimeKind::Development => RawOrigin::Signed(admin.clone()).into(), @@ -104,15 +106,23 @@ pub fn create_empty_pool(admin: AccountId32, pool_id: PoolId, curren BoundedVec::default(), ) .unwrap(); + + // In order to later close the epoch fastly, + // we mofify here that requirement to significalty reduce the testing time. + // The only way to do it is breaking the integration tests rules mutating + // this state directly. + pallet_pool_system::Pool::::mutate(pool_id, |pool| { + pool.as_mut().unwrap().parameters.min_epoch_time = POOL_MIN_EPOCH_TIME; + }); } -pub fn close_pool_epoch(admin: AccountId32, pool_id: PoolId) { +pub fn close_pool_epoch(admin: AccountId, pool_id: PoolId) { pallet_pool_system::Pallet::::close_epoch(RawOrigin::Signed(admin.clone()).into(), pool_id) .unwrap(); } pub fn invest( - investor: AccountId32, + investor: AccountId, pool_id: PoolId, tranche_id: TrancheId, amount: Balance, From a496e35833f25c50fedacb548df51905da6b66c3 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Fri, 20 Oct 2023 17:12:15 +0200 Subject: [PATCH 26/27] fix and extend loan testing --- .../src/generic/cases/loans.rs | 78 ++++++++++++------- .../integration-tests/src/generic/runtime.rs | 5 +- 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/runtime/integration-tests/src/generic/cases/loans.rs b/runtime/integration-tests/src/generic/cases/loans.rs index fc5f4024c6..82fcf4b749 100644 --- a/runtime/integration-tests/src/generic/cases/loans.rs +++ b/runtime/integration-tests/src/generic/cases/loans.rs @@ -7,6 +7,7 @@ use cfg_types::permissions::PoolRole; use frame_support::traits::Get; use pallet_loans::{ entities::{ + input::PrincipalInput, loans::LoanInfo, pricing::{ internal::{InternalPricing, MaxBorrowAmount as IntMaxBorrowAmount}, @@ -47,6 +48,7 @@ const NFT_A: (CollectionId, ItemId) = (1, ItemId(10)); const FOR_FEES: Balance = cfg(1); const EXPECTED_POOL_BALANCE: Balance = usd6(1_000_000); +const COLLATERAL_VALUE: Balance = usd6(100_000); fn initialize_state_for_loans, T: Runtime>() -> Environment { let mut env = Environment::from_storage( @@ -84,50 +86,68 @@ fn initialize_state_for_loans, T: Runtime>() -> Environment env } +fn internal_priced_loan(now: Seconds) -> LoanInfo { + LoanInfo { + schedule: RepaymentSchedule { + maturity: Maturity::Fixed { + date: now + SECONDS_PER_YEAR, + extension: SECONDS_PER_YEAR / 2, + }, + interest_payments: InterestPayments::None, + pay_down_schedule: PayDownSchedule::None, + }, + interest_rate: InterestRate::Fixed { + rate_per_year: rate_from_percent(20), + compounding: CompoundingSchedule::Secondly, + }, + collateral: NFT_A, + pricing: Pricing::Internal(InternalPricing { + collateral_value: COLLATERAL_VALUE, + max_borrow_amount: IntMaxBorrowAmount::UpToTotalBorrowed { + advance_rate: rate_from_percent(100), + }, + valuation_method: ValuationMethod::OutstandingDebt, + }), + restrictions: LoanRestrictions { + borrows: BorrowRestrictions::NotWrittenOff, + repayments: RepayRestrictions::None, + }, + } +} + fn borrow() { let mut env = initialize_state_for_loans::, T>(); let info = env.state(|| { let now = as TimeAsSecs>::now(); - LoanInfo { - schedule: RepaymentSchedule { - maturity: Maturity::Fixed { - date: now + SECONDS_PER_YEAR, - extension: SECONDS_PER_YEAR / 2, - }, - interest_payments: InterestPayments::None, - pay_down_schedule: PayDownSchedule::None, - }, - interest_rate: InterestRate::Fixed { - rate_per_year: rate_from_percent(20), - compounding: CompoundingSchedule::Secondly, - }, - collateral: NFT_A, - pricing: Pricing::Internal(InternalPricing { - collateral_value: 100_000, - max_borrow_amount: IntMaxBorrowAmount::UpToTotalBorrowed { - advance_rate: rate_from_percent(100), - }, - valuation_method: ValuationMethod::OutstandingDebt, - }), - restrictions: LoanRestrictions { - borrows: BorrowRestrictions::NotWrittenOff, - repayments: RepayRestrictions::None, - }, - } + internal_priced_loan::(now) }); env.submit_now( BORROWER, pallet_loans::Call::create { pool_id: POOL_A, - info: info, + info, }, ) .unwrap(); - // Submit Loan::create() - // Submit Loan::borrow() + let loan_id = env + .find_event(|e| match e { + pallet_loans::Event::::Created { loan_id, .. } => Some(loan_id), + _ => None, + }) + .unwrap(); + + env.submit_now( + BORROWER, + pallet_loans::Call::borrow { + pool_id: POOL_A, + loan_id, + amount: PrincipalInput::Internal(COLLATERAL_VALUE / 2), + }, + ) + .unwrap(); } crate::test_for_runtimes!(all, borrow); diff --git a/runtime/integration-tests/src/generic/runtime.rs b/runtime/integration-tests/src/generic/runtime.rs index 7ca7b820ed..1ef6afbd35 100644 --- a/runtime/integration-tests/src/generic/runtime.rs +++ b/runtime/integration-tests/src/generic/runtime.rs @@ -66,6 +66,7 @@ pub trait Runtime: + pallet_loans::Config< Balance = Balance, PoolId = PoolId, + LoanId = LoanId, CollectionId = CollectionId, ItemId = ItemId, Rate = Rate, @@ -115,9 +116,11 @@ pub trait Runtime: + TryInto> + TryInto> + TryInto> + + TryInto> + From> + From> - + From>; + + From> + + From>; /// Block used by the runtime type Block: Block< From 744f59fda2264b5189e5488d613cebd678ff58c5 Mon Sep 17 00:00:00 2001 From: lemunozm Date: Fri, 20 Oct 2023 17:50:40 +0200 Subject: [PATCH 27/27] remove unused pallet sudo addition --- Cargo.lock | 1 - runtime/integration-tests/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2bc714ba46..663175b873 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11112,7 +11112,6 @@ dependencies = [ "pallet-restricted-tokens", "pallet-rewards", "pallet-session", - "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", "pallet-treasury", diff --git a/runtime/integration-tests/Cargo.toml b/runtime/integration-tests/Cargo.toml index 3cf3662520..320bb2b3d6 100644 --- a/runtime/integration-tests/Cargo.toml +++ b/runtime/integration-tests/Cargo.toml @@ -30,7 +30,6 @@ pallet-uniques = { git = "https://github.com/paritytech/substrate", default-feat pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } -pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" } ## Substrate-Primitives sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.38" }