diff --git a/flow/src/benchmarking.rs b/flow/src/benchmarking.rs index 3718d1ef9..7fcdbd362 100644 --- a/flow/src/benchmarking.rs +++ b/flow/src/benchmarking.rs @@ -5,45 +5,61 @@ use crate::Pallet as Flow; use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; use frame_system::RawOrigin; use frame_support::traits::Hooks; -use sp_runtime::{DispatchError, traits::{Saturating}}; -use sp_std::{vec}; +use sp_runtime::{DispatchError, traits::{Saturating, SaturatedConversion}}; +use sp_std::vec; -fn fund_account(account_id: &T::AccountId, multiplier: Option) -> Result<(), DispatchError> { - let amount = T::MinContribution::get().saturating_mul(multiplier.unwrap_or(10).into()); - T::Currency::deposit(T::ProtocolTokenId::get(), account_id, amount)?; - T::Currency::deposit(T::PaymentTokenId::get(), account_id, amount)?; +const SEED: u32 = 0; +const DEPOSIT_AMOUNT: u128 = 10000000000000000000; + + +/// Fund account with tokens, needed for org and campaign interactions +fn fund_account(account_id: &T::AccountId) -> Result<(), DispatchError> { + let balance_amount: T::Balance = DEPOSIT_AMOUNT.saturated_into(); + T::Currency::deposit(T::ProtocolTokenId::get(), account_id, balance_amount)?; + T::Currency::deposit(T::PaymentTokenId::get(), account_id, balance_amount)?; Ok(()) } -/// Fund accounts with tokens, needed for org interactions -fn fund_accounts(account_ids: &Vec, multiplier: Option) -> Result<(), DispatchError> { +fn fund_accounts(account_ids: &Vec) -> Result<(), DispatchError> { for account_id in account_ids { - fund_account::(&account_id, multiplier)?; + fund_account::(&account_id)?; } Ok(()) } +/// Switch to next block number +fn next_block() { + let current_block = frame_system::Pallet::::block_number(); + frame_system::Pallet::::set_block_number(current_block.saturating_add(1_u32.into())); +} + +/// Execute `create_campaign` extrinsic and return id of created campaign object fn create_campaign_call(caller: T::AccountId, org_id: T::Hash) -> Result { let name: Vec = vec![0; T::MaxNameLength::get() as usize]; let cid: Vec = vec![0; T::MaxNameLength::get() as usize]; let token_symbol: Vec = vec![0; 5]; let token_name: Vec = vec![0; 32]; + let target: T::Balance = T::MinContribution::get(); + let deposit: T::Balance = T::MinContribution::get(); + let expiry: T::BlockNumber = frame_system::Pallet::::block_number() + 200_u32.into(); + let protocol: FlowProtocol = FlowProtocol::default(); + let governance: FlowGovernance = FlowGovernance::default(); + let nonce = Nonce::::get(); Flow::::create_campaign( RawOrigin::Signed(caller.clone()).into(), org_id, caller.clone(), name, - T::MinContribution::get(), - T::MinContribution::get(), - frame_system::Pallet::::block_number() + 200_u32.into(), - Default::default(), - Default::default(), + target, + deposit, + expiry, + protocol, + governance, cid, token_name, token_symbol )?; - let nonce = Nonce::::get() - 1u128; Ok(T::Hashing::hash_of(&nonce)) } @@ -51,18 +67,27 @@ fn create_campaign_call(caller: T::AccountId, org_id: T::Hash) -> Res benchmarks! { create_campaign { - let b in 0 .. T::MaxCampaignsPerBlock::get()-1; // already created campaigns at current block + let b in 0 .. T::MaxCampaignsPerOrg::get()-1; // limit to total campaigns per organization let caller: T::AccountId = whitelisted_caller(); - fund_account::(&caller, None)?; + fund_account::(&caller)?; + + // Prepare organization and treasury + let per_block_cnt = T::MaxCampaignsPerBlock::get(); let org_id = T::Control::create_org(caller.clone().into())?; let treasury_id = T::Control::org_treasury_account(&org_id); - fund_account::(&treasury_id, None)?; - for i in 0..b { - create_campaign_call::(caller.clone(), org_id.clone())?; + fund_account::(&treasury_id)?; + + // Create some campaigns, respecting per block limitation + for i in 0 .. b { + create_campaign_call::(caller.clone(), org_id)?; + if i % per_block_cnt == 0 { + next_block::(); + } } - let count_before = CampaignsCount::::get(); + // Save number of existing campaigns to compare to new count after extrinsic called + let count_before = CampaignsCount::::get(); }: _( RawOrigin::Signed(caller.clone()), org_id, @@ -70,7 +95,7 @@ benchmarks! { vec![0; T::MaxNameLength::get() as usize], T::MinContribution::get(), T::MinContribution::get(), - 200_u32.into(), + frame_system::Pallet::::block_number() + 200_u32.into(), Default::default(), Default::default(), vec![0; T::MaxNameLength::get() as usize], @@ -82,12 +107,27 @@ benchmarks! { } update_state { + let b in 1 .. T::MaxCampaignsPerOrg::get(); // limit to campaigns per organization + let caller: T::AccountId = whitelisted_caller(); - fund_account::(&caller, None)?; + fund_account::(&caller)?; + + // Prepare organization and treasury + let per_block_cnt = T::MaxCampaignsPerBlock::get(); let org_id = T::Control::create_org(caller.clone().into())?; let treasury_id = T::Control::org_treasury_account(&org_id); - fund_account::(&treasury_id, None)?; - let campaign_id = create_campaign_call::(caller.clone(), org_id.clone())?; + fund_account::(&treasury_id)?; + + // Create some campaigns, respecting per block limitation + for i in 0 .. b { + create_campaign_call::(caller.clone(), org_id)?; + if i % per_block_cnt == 0 { + next_block::(); + } + } + + // Use last campaign to call extrinsic with + let campaign_id = T::Hashing::hash_of(&Nonce::::get().saturating_sub(1_u128)); let new_state = FlowState::Paused; }: _( RawOrigin::Signed(caller.clone()), @@ -99,12 +139,18 @@ benchmarks! { } contribute { + + // Prepare owner and contributor accounts let owner: T::AccountId = whitelisted_caller(); - let contributor: T::AccountId = account("contributor", 0, 0); - fund_accounts::(&vec![owner.clone(), contributor.clone()], None)?; + let contributor: T::AccountId = account("contributor", 0, SEED); + fund_accounts::(&vec![owner.clone(), contributor.clone()])?; + + // Prepare organization and treasury let org_id = T::Control::create_org(owner.clone().into())?; let treasury_id = T::Control::org_treasury_account(&org_id); - fund_account::(&treasury_id, None)?; + fund_account::(&treasury_id)?; + + // Create campaign to use for contributions let campaign_id = create_campaign_call::(owner, org_id)?; }: _( RawOrigin::Signed(contributor.clone()), @@ -116,26 +162,26 @@ benchmarks! { } on_initialize { - let b in 0 .. T::MaxContributorsProcessing::get(); // number of contributions in current block - let c in 0 .. T::MaxCampaignsPerBlock::get(); // number of campaigns in current block + let c in 1 .. T::MaxContributorsProcessing::get(); // number of contributions in current block let owner: T::AccountId = whitelisted_caller(); - fund_account::(&owner, None)?; + fund_account::(&owner)?; + + // Prepare organization and treasury let org_id = T::Control::create_org(owner.clone().into())?; let treasury_id = T::Control::org_treasury_account(&org_id); - fund_account::(&treasury_id, None)?; - for _ in 0..c { - let campaign_id = create_campaign_call::(owner.clone(), org_id.clone())?; - for i in 0..b { - let account: T::AccountId = account("contributor", i, 0); - fund_account::(&account, None)?; - Pallet::::contribute(RawOrigin::Signed(account).into(), campaign_id.clone(), T::MinContribution::get())?; - } + fund_account::(&treasury_id)?; + + // Create campaign and add some contributions + let campaign_id = create_campaign_call::(owner.clone(), org_id.clone())?; + for i in 0 .. c { + let account: T::AccountId = account("contributor", i, SEED); + fund_account::(&account)?; + Pallet::::contribute(RawOrigin::Signed(account).into(), campaign_id.clone(), T::MinContribution::get())?; } - let nonce = Nonce::::get().saturating_sub(1_u128); - let campaign_id = T::Hashing::hash_of(&nonce); - let campaign = Campaigns::::get(&campaign_id); - let mut block_number = campaign.expiry; + + // Trigger on_finalize to prepare object to be used in initialize hook + let mut block_number = Campaigns::::get(&campaign_id).expiry; frame_system::Pallet::::set_block_number(block_number.clone()); Pallet::::on_finalize(block_number.clone()); block_number = block_number.saturating_add(1_u32.into()); diff --git a/flow/src/lib.rs b/flow/src/lib.rs index 342053bc8..dc0f5ecf6 100644 --- a/flow/src/lib.rs +++ b/flow/src/lib.rs @@ -42,19 +42,17 @@ pub use types::*; mod mock; mod tests; +mod migration; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; pub mod weights; -// TODO: weights -// mod default_weights; - // TODO: externalise error messages - Enum: number and text description // mod errors; use frame_support::{ dispatch::{DispatchResult, DispatchResultWithPostInfo}, - traits::{Get, UnixTime, BalanceStatus}, + traits::{Get, BalanceStatus, StorageVersion, UnixTime}, transactional, weights::Weight }; @@ -81,8 +79,12 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; + /// The current storage version. + const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); + #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(_); #[pallet::config] @@ -137,6 +139,9 @@ pub mod pallet { #[pallet::constant] type MaxCampaignsPerAddress: Get; + + #[pallet::constant] + type MaxCampaignsPerOrg: Get; /// The max number of campaigns per one block. #[pallet::constant] @@ -215,12 +220,12 @@ pub mod pallet { pub(super) type CampaignState = StorageMap<_, Blake2_128Concat, T::Hash, FlowState, ValueQuery, GetDefault>; - /// List of campaign by certain campaign state. + /// List of campaign by certain campaign state and org. /// 0 init, 1 active, 2 paused, 3 complete success, 4 complete failed, 5 authority lock /// - /// CampaignsByState: map FlowState => Vec + /// CampaignsByState: double_map FlowState, Hash => Vec #[pallet::storage] - pub(super) type CampaignsByState = StorageMap<_, Blake2_128Concat, FlowState, Vec, ValueQuery>; + pub(super) type CampaignsByState = StorageDoubleMap<_, Blake2_128Concat, FlowState, Blake2_128Concat, T::Hash, Vec, ValueQuery>; /// Campaigns ending in block x. /// @@ -447,6 +452,8 @@ pub mod pallet { EndTooLate, /// Max campaigns per block exceeded. CampaignsPerBlockExceeded, + /// Max campaigns per org exceeded. + CampaignsPerOrgExceeded, /// Name too long. NameTooLong, /// Name too short. @@ -489,16 +496,18 @@ pub mod pallet { fn on_initialize(block_number: T::BlockNumber) -> Weight { let mut contributors: u32 = 0; - let mut campaigns: u32 = Self::process_campaigns(&block_number, FlowState::Finalizing, &mut contributors); - campaigns = campaigns.saturating_add( - Self::process_campaigns(&block_number, FlowState::Reverting, &mut contributors) - ); - T::WeightInfo::on_initialize(contributors, campaigns) + Self::process_campaigns(&block_number, FlowState::Finalizing, &mut contributors); + Self::process_campaigns(&block_number, FlowState::Reverting, &mut contributors); + T::WeightInfo::on_initialize(contributors) } fn on_finalize(block_number: T::BlockNumber) { Self::schedule_campaign_settlements(block_number) } + + fn on_runtime_upgrade() -> Weight { + migration::migrate::() + } } #[pallet::call] @@ -520,9 +529,9 @@ pub mod pallet { /// /// Emits `CampaignCreated` event when successful. /// - /// Weight: `O(1)` + /// Weight: `O(log n)` #[pallet::weight(T::WeightInfo::create_campaign( - T::MaxCampaignsPerBlock::get() + T::MaxCampaignsPerOrg::get() ))] #[transactional] pub fn create_campaign( @@ -576,12 +585,18 @@ pub mod pallet { // for collision // check contribution limit per block - let campaigns = CampaignsByBlock::::get(expiry); + let block_campaigns_cnt = CampaignsByBlock::::get(expiry).len() as u32; ensure!( - (campaigns.len() as u32) < T::MaxCampaignsPerBlock::get(), + block_campaigns_cnt < T::MaxCampaignsPerBlock::get(), Error::::CampaignsPerBlockExceeded ); + let org_campaigns_cnt = CampaignsByOrg::::get(&org_id).len() as u32; + ensure!( + org_campaigns_cnt < T::MaxCampaignsPerOrg::get(), + Error::::CampaignsPerOrgExceeded + ); + let campaign = Campaign { id: id.clone(), org: org_id.clone(), @@ -604,7 +619,7 @@ pub mod pallet { // 0 init, 1 active, 2 paused, 3 complete success, 4 complete failed, 5 // authority lock - Self::set_state(id.clone(), FlowState::Active); + Self::set_state(id.clone(), FlowState::Active, &org_id); // deposit the event Self::deposit_event(Event::CampaignCreated { @@ -616,7 +631,7 @@ pub mod pallet { expiry, name, }); - Ok(Some(T::WeightInfo::create_campaign(campaigns.len() as u32)).into()) + Ok(Some(T::WeightInfo::create_campaign(org_campaigns_cnt)).into()) // No fees are paid here if we need to create this account; // that's why we don't just use the stock `transfer`. @@ -631,9 +646,11 @@ pub mod pallet { /// /// Emits `CampaignUpdated` event when successful. /// - /// Weight: O(1) - #[pallet::weight(T::WeightInfo::update_state())] - pub fn update_state(origin: OriginFor, campaign_id: T::Hash, state: FlowState) -> DispatchResult { + /// Weight: O(log n) + #[pallet::weight(T::WeightInfo::update_state( + T::MaxCampaignsPerOrg::get() + ))] + pub fn update_state(origin: OriginFor, campaign_id: T::Hash, state: FlowState) -> DispatchResultWithPostInfo { // access control let sender = ensure_signed(origin)?; @@ -647,10 +664,12 @@ pub mod pallet { ensure!(current_block < campaign.expiry, Error::::CampaignExpired); // not finished or locked? - let current_state = CampaignState::::get(campaign_id); + let org_id = CampaignOrg::::get(&campaign_id); + let org_campaigns_cnt = CampaignsByOrg::::get(&org_id).len() as u32; + let current_state = CampaignState::::get(&campaign_id); ensure!(current_state < FlowState::Success, Error::::CampaignExpired); - Self::set_state(campaign_id.clone(), state.clone()); + Self::set_state(campaign_id.clone(), state.clone(), &org_id); // dispatch status update event Self::deposit_event(Event::CampaignUpdated { @@ -659,7 +678,7 @@ pub mod pallet { block_number: current_block, }); - Ok(()) + Ok(Some(T::WeightInfo::update_state(org_campaigns_cnt)).into()) } /// Contribute to project @@ -710,22 +729,22 @@ pub mod pallet { } impl Pallet { - fn set_state(campaign_id: T::Hash, state: FlowState) { + fn set_state(campaign_id: T::Hash, state: FlowState, org_id: &T::Hash) { let current_state = CampaignState::::get(&campaign_id); // remove - let mut current_state_members = CampaignsByState::::get(¤t_state); + let mut current_state_members = CampaignsByState::::get(¤t_state, org_id); match current_state_members.binary_search(&campaign_id) { Ok(index) => { current_state_members.remove(index); - CampaignsByState::::insert(¤t_state, current_state_members); + CampaignsByState::::insert(¤t_state, org_id, current_state_members); } Err(_) => (), //(Error::::IdUnknown) } // add - CampaignsByState::::mutate(&state, |campaigns| campaigns.push(campaign_id.clone())); + CampaignsByState::::mutate(&state, org_id, |campaigns| campaigns.push(campaign_id.clone())); CampaignState::::insert(campaign_id, state); } @@ -840,7 +859,7 @@ impl Pallet { // Campaign cap reached: Finalizing if campaign_balance >= campaign.cap { - Self::set_state(campaign.id, FlowState::Finalizing); + Self::set_state(campaign.id, FlowState::Finalizing, &campaign.org); Self::deposit_event(Event::CampaignFinalising { campaign_id: *campaign_id, @@ -850,7 +869,7 @@ impl Pallet { // Campaign cap not reached: Reverting } else { - Self::set_state(campaign.id, FlowState::Reverting); + Self::set_state(campaign.id, FlowState::Reverting, &campaign.org); Self::deposit_event(Event::CampaignReverting { campaign_id: *campaign_id, @@ -863,24 +882,25 @@ impl Pallet { fn process_campaigns(block_number: &T::BlockNumber, state: FlowState, processed: &mut u32) -> u32 { let mut campaigns_processed: u32 = 0; - let campaign_ids = CampaignsByState::::get(&state); - for campaign_id in campaign_ids { - let campaign = Campaigns::::get(campaign_id); - let campaign_balance = CampaignBalance::::get(campaign_id); - let org = CampaignOrg::::get(&campaign_id); - let org_treasury = T::Control::org_treasury_account(&org); - let contributors = CampaignContributors::::get(campaign_id); - - if state == FlowState::Finalizing { - if let Some(owner) = CampaignOwner::::get(campaign.id) { - Self::finalize_campaign(&block_number, processed, &campaign, &campaign_balance, &org, &org_treasury, &contributors, &owner); - } else { - // TODO: If no campaign owner: revert the campaign or leave it as is? + let campaign_ids_by_org: Vec<(T::Hash, Vec)> = CampaignsByState::::iter_prefix(&state).collect(); + for (_org_id, campaign_ids) in campaign_ids_by_org { + for campaign_id in campaign_ids { + let campaign = Campaigns::::get(campaign_id); + let campaign_balance = CampaignBalance::::get(&campaign_id); + let org_treasury = T::Control::org_treasury_account(&campaign.org); + let contributors = CampaignContributors::::get(&campaign_id); + + if state == FlowState::Finalizing { + if let Some(owner) = CampaignOwner::::get(campaign.id) { + Self::finalize_campaign(&block_number, processed, &campaign, &campaign_balance, &org_treasury, &contributors, &owner); + } else { + // TODO: If no campaign owner: revert the campaign or leave it as is? + } + } else if state == FlowState::Reverting { + Self::revert_campaign(&block_number, processed, &campaign, &campaign_balance, &org_treasury, &contributors); } - } else if state == FlowState::Reverting { - Self::revert_campaign(&block_number, processed, &campaign, &campaign_balance, &org, &org_treasury, &contributors); + campaigns_processed = campaigns_processed.saturating_add(1); } - campaigns_processed = campaigns_processed.saturating_add(1); } campaigns_processed } @@ -888,10 +908,9 @@ impl Pallet { fn finalize_campaign( block_number: &T::BlockNumber, processed: &mut u32, campaign: &Campaign, - campaign_balance: &T::Balance, org: &T::Hash, org_treasury: &T::AccountId, + campaign_balance: &T::Balance, org_treasury: &T::AccountId, contributors: &Vec, owner: &T::AccountId ) { - let contributors = CampaignContributors::::get(campaign.id); let processed_offset = ContributorsFinalized::::get(campaign.id); let offset: usize = usize::try_from(processed_offset).unwrap(); for contributor in &contributors[offset..] { @@ -919,15 +938,13 @@ impl Pallet { *processed += 1; if *processed >= T::MaxContributorsProcessing::get() { ContributorsFinalized::::insert(campaign.id, processed_offset + *processed); - // TODO: return T::WeightInfo::finalize_campaign(processed) return } } ContributorsFinalized::::insert(campaign.id, processed_offset + *processed); // TODO: This doesn't make sense without "transfer_amount" error handling if *campaign_balance < campaign.cap { - Self::set_state(campaign.id, FlowState::Reverting); - // TODO: return T::WeightInfo::finalize_campaign(processed) + Self::set_state(campaign.id, FlowState::Reverting, &campaign.org); return } let commission = T::CampaignFee::get().mul_floor(campaign_balance.clone()); @@ -943,7 +960,7 @@ impl Pallet { let updated_balance = *campaign_balance - commission; CampaignBalance::::insert(campaign.id, updated_balance); - Self::set_state(campaign.id, FlowState::Success); + Self::set_state(campaign.id, FlowState::Success, &campaign.org); Self::deposit_event(Event::CampaignFinalized { campaign_id: campaign.id, @@ -951,14 +968,12 @@ impl Pallet { block_number: *block_number, success: true, }); - - // TODO: return T::WeightInfo::finalize_campaign(processed) } fn revert_campaign( block_number: &T::BlockNumber, processed: &mut u32, campaign: &Campaign, - campaign_balance: &T::Balance, org: &T::Hash, org_treasury: &T::AccountId, + campaign_balance: &T::Balance, org_treasury: &T::AccountId, contributors: &Vec ) { let processed_offset = ContributorsReverted::::get(campaign.id); @@ -977,7 +992,7 @@ impl Pallet { // Unreserve Initial deposit T::Currency::unreserve(T::ProtocolTokenId::get(), &org_treasury, campaign.deposit); - Self::set_state(campaign.id, FlowState::Failed); + Self::set_state(campaign.id, FlowState::Failed, &campaign.org); Self::deposit_event(Event::CampaignFailed { campaign_id: campaign.id, campaign_balance: *campaign_balance, diff --git a/flow/src/migration.rs b/flow/src/migration.rs new file mode 100644 index 000000000..a7d9a498b --- /dev/null +++ b/flow/src/migration.rs @@ -0,0 +1,53 @@ +use frame_support::{ + generate_storage_alias, + traits::Get, + Twox64Concat, +}; +use sp_std::prelude::*; +use crate::{ + CampaignsByState as CampaignsByStateNew, + CampaignOrg, + Config, + FlowState, + Pallet, + Weight +}; + + +pub fn migrate() -> Weight { + use frame_support::traits::StorageVersion; + + let version = StorageVersion::get::>(); + let mut weight: Weight = 0; + + if version < 1 { + weight = weight.saturating_add(v1::migrate::()); + StorageVersion::new(1).put::>(); + } + + weight +} + +mod v1 { + use super::*; + + generate_storage_alias!( + Flow, + CampaignsByState => Map<(Twox64Concat, FlowState), Vec> + ); + + pub fn migrate() -> Weight { + let mut weight: Weight = 0; + + let old_records: Vec<(FlowState, Vec)> = CampaignsByState::::drain().collect(); + for (state, campaign_ids) in old_records { + for campaign_id in campaign_ids { + let org_id = CampaignOrg::::get(&campaign_id); + CampaignsByStateNew::::mutate(&state, &org_id, |campaigns| campaigns.push(campaign_id)); + weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); + } + } + + weight + } +} diff --git a/flow/src/mock.rs b/flow/src/mock.rs index 197b364ed..6d8179835 100644 --- a/flow/src/mock.rs +++ b/flow/src/mock.rs @@ -5,7 +5,6 @@ use frame_support::{ construct_runtime, parameter_types, PalletId, traits::{Everything, GenesisBuild, Nothing}, }; -use frame_system::EnsureRoot; use sp_core::H256; use sp_runtime::{traits::IdentityLookup, Permill}; @@ -195,6 +194,7 @@ parameter_types! { pub const MaxNameLength: u32 = 4; pub const MaxCampaignsPerAddress: u32 = 3; pub const MaxCampaignsPerBlock: u32 = 1; + pub const MaxCampaignsPerOrg: u32 = 64; pub const MaxContributionsPerBlock: u32 = 3; pub const MaxContributorsProcessing: u32 = 4; pub const MinCampaignDuration: BlockNumber = 1 * DAYS; @@ -223,6 +223,7 @@ impl Config for Test { type MaxNameLength = MaxNameLength; type MaxCampaignsPerAddress = MaxCampaignsPerAddress; type MaxCampaignsPerBlock = MaxCampaignsPerBlock; + type MaxCampaignsPerOrg = MaxCampaignsPerOrg; type MaxContributionsPerBlock = MaxContributionsPerBlock; type MinCampaignDuration = MinCampaignDuration; type MaxCampaignDuration = MaxCampaignDuration; diff --git a/flow/src/tests.rs b/flow/src/tests.rs index 947fdc720..d6adc0873 100644 --- a/flow/src/tests.rs +++ b/flow/src/tests.rs @@ -1,11 +1,10 @@ #![cfg(test)] use super::*; -use codec::Encode; +use mock::{Event, *}; use frame_support::traits::Hooks; use frame_support::{assert_noop, assert_ok}; -use frame_system::{EventRecord, Phase, RawOrigin}; -use mock::{Event, Moment, *}; +use frame_system::RawOrigin; use sp_core::H256; use sp_runtime::traits::{Hash, AccountIdConversion}; @@ -125,7 +124,7 @@ fn flow_create_errors() { #[test] fn flow_create_success() { new_test_ext().execute_with(|| { - let (org, treasury, _) = create_org_treasury(); + let (org, _treasury, _) = create_org_treasury(); let current_block = 3; System::set_block_number(current_block); @@ -154,7 +153,7 @@ fn flow_create_success() { assert_eq!(CampaignsOwnedCount::::get(org), 1); assert_eq!(CampaignsOwnedIndex::::get((org, id)), 0); assert_eq!(Nonce::::get(), 1); - assert_eq!(CampaignsByState::::get(FlowState::Active), vec![id]); + assert_eq!(CampaignsByState::::get(FlowState::Active, &org), vec![id]); assert_eq!(CampaignState::::get(id), FlowState::Active); System::assert_has_event(Event::Flow(crate::Event::CampaignCreated { @@ -230,9 +229,11 @@ fn flow_update_state_success() { Campaigns::::insert(&campaign_id, &campaign); CampaignOwner::::insert(campaign_id, BOB); CampaignAdmin::::insert(campaign_id, BOB); + CampaignOrg::::insert(campaign_id, campaign.org); + CampaignsByOrg::::insert(campaign.org, vec![campaign_id]); assert_ok!(Flow::update_state(Origin::signed(BOB), campaign_id, FlowState::Paused)); - assert_eq!(CampaignsByState::::get(FlowState::Paused), vec![campaign_id]); + assert_eq!(CampaignsByState::::get(FlowState::Paused, &campaign.org), vec![campaign_id]); assert_eq!(CampaignState::::get(campaign_id), FlowState::Paused); }); } @@ -340,7 +341,7 @@ fn flow_on_finalize_campaign_succeess() { let nonce = Nonce::::get(); let campaign_id: H256 = ::Hashing::hash_of(&nonce); assert_ok!(Flow::create_campaign( - Origin::signed(BOB), org, BOB, vec![1, 2], target, deposit, expiry, + Origin::signed(BOB), org.clone(), BOB, vec![1, 2], target, deposit, expiry, FlowProtocol::Raise, FlowGovernance::No, vec![1, 2], vec![], vec![] )); @@ -369,7 +370,7 @@ fn flow_on_finalize_campaign_succeess() { })); // Ensure that campaign was scheduled to be finalized - assert_eq!(CampaignsByState::::get(&FlowState::Finalizing), vec![campaign_id]); + assert_eq!(CampaignsByState::::get(&FlowState::Finalizing, &org), vec![campaign_id]); // Ensure that campaign will be finalize in 3 blocks: 4 + 4 + 2 let batch_size: u128 = 4; assert_eq!(MaxContributorsProcessing::get(), batch_size as u32); @@ -427,7 +428,7 @@ fn flow_on_finalize_campaign_succeess() { tbalance - deposit ); // Ensure that campaign succeeded - assert_eq!(CampaignsByState::::get(&FlowState::Success), vec![campaign_id]); + assert_eq!(CampaignsByState::::get(&FlowState::Success, &org), vec![campaign_id]); System::assert_has_event(Event::Flow(crate::Event::CampaignFinalized { campaign_id, campaign_balance: CampaignBalance::::get(campaign_id), @@ -455,7 +456,7 @@ fn flow_on_finalize_campaign_failed() { let nonce = Nonce::::get(); let campaign_id: H256 = ::Hashing::hash_of(&nonce); assert_ok!(Flow::create_campaign( - Origin::signed(BOB), org, BOB, vec![1, 2], target, deposit, expiry, + Origin::signed(BOB), org.clone(), BOB, vec![1, 2], target, deposit, expiry, FlowProtocol::Raise, FlowGovernance::No, vec![1, 2], vec![], vec![] )); @@ -484,7 +485,7 @@ fn flow_on_finalize_campaign_failed() { })); // Ensure that campaign was scheduled to be reverted - assert_eq!(CampaignsByState::::get(&FlowState::Reverting), vec![campaign_id]); + assert_eq!(CampaignsByState::::get(&FlowState::Reverting, &org), vec![campaign_id]); // Ensure that campaign will be reverted in 3 blocks: 4 + 4 + 2 let batch_size: u128 = 4; assert_eq!(MaxContributorsProcessing::get(), batch_size as u32); @@ -543,7 +544,7 @@ fn flow_on_finalize_campaign_failed() { tbalance ); // Ensure that campaign failed - assert_eq!(CampaignsByState::::get(&FlowState::Failed), vec![campaign_id]); + assert_eq!(CampaignsByState::::get(&FlowState::Failed, &org), vec![campaign_id]); System::assert_has_event(Event::Flow(crate::Event::CampaignFailed { campaign_id, diff --git a/flow/src/weights.rs b/flow/src/weights.rs index eb3841023..9dd841443 100644 --- a/flow/src/weights.rs +++ b/flow/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for gamedao_flow //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-06-17, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2022-06-21, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128 // Executed Command: @@ -41,9 +41,9 @@ use sp_std::marker::PhantomData; /// Weight functions needed for gamedao_flow. pub trait WeightInfo { fn create_campaign(b: u32, ) -> Weight; - fn update_state() -> Weight; + fn update_state(b: u32, ) -> Weight; fn contribute() -> Weight; - fn on_initialize(b: u32, c: u32, ) -> Weight; + fn on_initialize(c: u32, ) -> Weight; } /// Weights for gamedao_flow using the Substrate node and recommended hardware. @@ -54,8 +54,8 @@ impl WeightInfo for SubstrateWeight { // Storage: Tokens Accounts (r:1 w:1) // Storage: Flow Nonce (r:1 w:1) // Storage: Flow CampaignsByBlock (r:1 w:1) - // Storage: Timestamp Now (r:1 w:0) // Storage: Flow CampaignsByOrg (r:1 w:1) + // Storage: Timestamp Now (r:1 w:0) // Storage: Flow CampaignsCount (r:1 w:1) // Storage: Flow CampaignsOwnedCount (r:1 w:1) // Storage: Flow CampaignState (r:1 w:1) @@ -68,20 +68,26 @@ impl WeightInfo for SubstrateWeight { // Storage: Flow Campaigns (r:0 w:1) // Storage: Flow CampaignOrg (r:0 w:1) // Storage: Flow CampaignsIndex (r:0 w:1) - fn create_campaign(_b: u32, ) -> Weight { - (92_468_000 as Weight) + fn create_campaign(b: u32, ) -> Weight { + (94_410_000 as Weight) + // Standard Error: 19_000 + .saturating_add((791_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(12 as Weight)) .saturating_add(T::DbWeight::get().writes(16 as Weight)) } // Storage: Flow CampaignOwner (r:1 w:0) // Storage: Flow CampaignAdmin (r:1 w:0) // Storage: Flow Campaigns (r:1 w:0) + // Storage: Flow CampaignOrg (r:1 w:0) + // Storage: Flow CampaignsByOrg (r:1 w:0) // Storage: Flow CampaignState (r:1 w:1) // Storage: Flow CampaignsByState (r:2 w:2) - fn update_state() -> Weight { - (36_185_000 as Weight) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + fn update_state(b: u32, ) -> Weight { + (56_185_000 as Weight) + // Standard Error: 22_000 + .saturating_add((490_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } // Storage: Tokens Accounts (r:1 w:1) // Storage: Flow CampaignOwner (r:1 w:0) @@ -96,33 +102,29 @@ impl WeightInfo for SubstrateWeight { // Storage: Flow CampaignsContributedIndex (r:0 w:1) // Storage: Flow CampaignsContributedArray (r:0 w:1) fn contribute() -> Weight { - (55_395_000 as Weight) + (53_779_000 as Weight) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(9 as Weight)) } - // Storage: Flow CampaignsByState (r:3 w:2) - // Storage: Flow Campaigns (r:3 w:0) - // Storage: Flow CampaignBalance (r:3 w:0) - // Storage: Flow CampaignOrg (r:3 w:0) + // Storage: Flow CampaignsByState (r:4 w:2) + // Storage: Flow Campaigns (r:1 w:0) + // Storage: Flow CampaignBalance (r:1 w:1) // Storage: Control OrgTreasury (r:1 w:0) - // Storage: Flow CampaignContributors (r:3 w:0) - // Storage: Flow ContributorsReverted (r:3 w:3) - // Storage: Tokens Accounts (r:1 w:1) - // Storage: Flow CampaignState (r:3 w:3) - // Storage: Flow CampaignOwner (r:3 w:0) - // Storage: Flow ContributorsFinalized (r:3 w:3) - // Storage: Flow CampaignContribution (r:3 w:0) + // Storage: Flow CampaignContributors (r:1 w:0) + // Storage: Flow CampaignOwner (r:1 w:0) + // Storage: Flow ContributorsFinalized (r:1 w:1) + // Storage: Flow CampaignContribution (r:1 w:0) + // Storage: Tokens Accounts (r:3 w:3) // Storage: System Account (r:1 w:1) - fn on_initialize(b: u32, c: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 579_000 - .saturating_add((11_769_000 as Weight).saturating_mul(b as Weight)) - // Standard Error: 5_383_000 - .saturating_add((120_226_000 as Weight).saturating_mul(c as Weight)) - .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(b as Weight))) - .saturating_add(T::DbWeight::get().reads((19 as Weight).saturating_mul(c as Weight))) - .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(b as Weight))) - .saturating_add(T::DbWeight::get().writes((7 as Weight).saturating_mul(c as Weight))) + // Storage: Flow CampaignState (r:1 w:1) + fn on_initialize(c: u32, ) -> Weight { + (91_286_000 as Weight) + // Standard Error: 214_000 + .saturating_add((10_321_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(T::DbWeight::get().reads(14 as Weight)) + .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) + .saturating_add(T::DbWeight::get().writes(9 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(c as Weight))) } } @@ -133,8 +135,8 @@ impl WeightInfo for () { // Storage: Tokens Accounts (r:1 w:1) // Storage: Flow Nonce (r:1 w:1) // Storage: Flow CampaignsByBlock (r:1 w:1) - // Storage: Timestamp Now (r:1 w:0) // Storage: Flow CampaignsByOrg (r:1 w:1) + // Storage: Timestamp Now (r:1 w:0) // Storage: Flow CampaignsCount (r:1 w:1) // Storage: Flow CampaignsOwnedCount (r:1 w:1) // Storage: Flow CampaignState (r:1 w:1) @@ -147,20 +149,26 @@ impl WeightInfo for () { // Storage: Flow Campaigns (r:0 w:1) // Storage: Flow CampaignOrg (r:0 w:1) // Storage: Flow CampaignsIndex (r:0 w:1) - fn create_campaign(_b: u32, ) -> Weight { - (92_468_000 as Weight) + fn create_campaign(b: u32, ) -> Weight { + (94_410_000 as Weight) + // Standard Error: 19_000 + .saturating_add((791_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(16 as Weight)) } // Storage: Flow CampaignOwner (r:1 w:0) // Storage: Flow CampaignAdmin (r:1 w:0) // Storage: Flow Campaigns (r:1 w:0) + // Storage: Flow CampaignOrg (r:1 w:0) + // Storage: Flow CampaignsByOrg (r:1 w:0) // Storage: Flow CampaignState (r:1 w:1) // Storage: Flow CampaignsByState (r:2 w:2) - fn update_state() -> Weight { - (36_185_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + fn update_state(b: u32, ) -> Weight { + (56_185_000 as Weight) + // Standard Error: 22_000 + .saturating_add((490_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(RocksDbWeight::get().reads(8 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } // Storage: Tokens Accounts (r:1 w:1) // Storage: Flow CampaignOwner (r:1 w:0) @@ -175,32 +183,28 @@ impl WeightInfo for () { // Storage: Flow CampaignsContributedIndex (r:0 w:1) // Storage: Flow CampaignsContributedArray (r:0 w:1) fn contribute() -> Weight { - (55_395_000 as Weight) + (53_779_000 as Weight) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().writes(9 as Weight)) } - // Storage: Flow CampaignsByState (r:3 w:2) - // Storage: Flow Campaigns (r:3 w:0) - // Storage: Flow CampaignBalance (r:3 w:0) - // Storage: Flow CampaignOrg (r:3 w:0) + // Storage: Flow CampaignsByState (r:4 w:2) + // Storage: Flow Campaigns (r:1 w:0) + // Storage: Flow CampaignBalance (r:1 w:1) // Storage: Control OrgTreasury (r:1 w:0) - // Storage: Flow CampaignContributors (r:3 w:0) - // Storage: Flow ContributorsReverted (r:3 w:3) - // Storage: Tokens Accounts (r:1 w:1) - // Storage: Flow CampaignState (r:3 w:3) - // Storage: Flow CampaignOwner (r:3 w:0) - // Storage: Flow ContributorsFinalized (r:3 w:3) - // Storage: Flow CampaignContribution (r:3 w:0) + // Storage: Flow CampaignContributors (r:1 w:0) + // Storage: Flow CampaignOwner (r:1 w:0) + // Storage: Flow ContributorsFinalized (r:1 w:1) + // Storage: Flow CampaignContribution (r:1 w:0) + // Storage: Tokens Accounts (r:3 w:3) // Storage: System Account (r:1 w:1) - fn on_initialize(b: u32, c: u32, ) -> Weight { - (0 as Weight) - // Standard Error: 579_000 - .saturating_add((11_769_000 as Weight).saturating_mul(b as Weight)) - // Standard Error: 5_383_000 - .saturating_add((120_226_000 as Weight).saturating_mul(c as Weight)) - .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(b as Weight))) - .saturating_add(RocksDbWeight::get().reads((19 as Weight).saturating_mul(c as Weight))) - .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(b as Weight))) - .saturating_add(RocksDbWeight::get().writes((7 as Weight).saturating_mul(c as Weight))) + // Storage: Flow CampaignState (r:1 w:1) + fn on_initialize(c: u32, ) -> Weight { + (91_286_000 as Weight) + // Standard Error: 214_000 + .saturating_add((10_321_000 as Weight).saturating_mul(c as Weight)) + .saturating_add(RocksDbWeight::get().reads(14 as Weight)) + .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(c as Weight))) + .saturating_add(RocksDbWeight::get().writes(9 as Weight)) + .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(c as Weight))) } }