From 100620de970c4c6f64b8e9beb3d0ef189090d084 Mon Sep 17 00:00:00 2001 From: Volodymyr Brazhnyk <16227101+vovacha@users.noreply.github.com> Date: Tue, 12 Jul 2022 12:38:05 +0200 Subject: [PATCH] Upgrade substrate to v0.9.25 (#52) * Update Sense pallet * Draft update Flow, Control, Traits * Updated Control pallet * Updated Flow pallet * Updated Signal pallet * Updated tests and benchmarks for all GameDAO pallets * Add missing types * Change error for missing owner of the campaign * Updated benchmarks Co-authored-by: vasylenko-yevhen --- control/Cargo.toml | 34 ++++--- control/src/benchmarking.rs | 15 ++-- control/src/lib.rs | 115 +++++++++++++++--------- control/src/mock.rs | 55 ++++++++---- control/src/tests.rs | 12 +-- control/src/types.rs | 21 ++--- control/src/weights.rs | 45 +++++----- flow/Cargo.toml | 24 ++--- flow/src/benchmarking.rs | 18 ++-- flow/src/lib.rs | 172 ++++++++++++++++++++++-------------- flow/src/migration.rs | 36 +++++--- flow/src/mock.rs | 57 ++++++++---- flow/src/tests.rs | 109 +++++++++++++++-------- flow/src/types.rs | 19 ++-- flow/src/weights.rs | 45 +++++----- sense/Cargo.toml | 20 ++--- sense/src/benchmarking.rs | 8 +- sense/src/lib.rs | 46 +++++----- sense/src/mock.rs | 18 ++-- sense/src/tests.rs | 39 ++++---- sense/src/weights.rs | 67 ++++++++------ signal/Cargo.toml | 28 +++--- signal/src/benchmarking.rs | 30 +++---- signal/src/lib.rs | 90 +++++++++++++------ signal/src/migration.rs | 4 +- signal/src/mock.rs | 62 ++++++++++--- signal/src/tests.rs | 169 ++++++++++++++++++----------------- signal/src/types.rs | 21 ++--- signal/src/weights.rs | 53 +++++------ traits/Cargo.toml | 10 +-- traits/src/lib.rs | 10 ++- 31 files changed, 858 insertions(+), 594 deletions(-) diff --git a/control/Cargo.toml b/control/Cargo.toml index 8eac62c71..3a70e9d45 100755 --- a/control/Cargo.toml +++ b/control/Cargo.toml @@ -13,24 +13,23 @@ license = "GPL-3.0-or-later" description = "DAO Factory" [dependencies] -hex-literal = "0.3.1" +hex-literal = "0.3.4" num_enum = { version = "0.5.1", default-features = false } serde = { version = "1.0.124", optional = true } -codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -sp-storage = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +sp-storage = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false, optional = true } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false, optional = true } -pallet-assets = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } +pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } orml-traits = { path = "../../orml/traits", default-features = false } gamedao-traits = { package = "gamedao-traits", path = "../traits", default-features = false } @@ -38,11 +37,11 @@ gamedao-traits = { package = "gamedao-traits", path = "../traits", default-featu # tangram = { package = "module-tangram", path = "../../zero/tangram", default-features = false } [dev-dependencies] -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.13" } -frame-support-test = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.13" } -pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.25" } +frame-support-test = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.25" } +pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } orml-tokens = { path = "../../orml/tokens", default-features = false } orml-currencies = { path = "../../orml/currencies", default-features = false } @@ -58,7 +57,6 @@ std = [ "scale-info/std", "num_enum/std", - # "pallet-assets/std", # "pallet-balances/std", "frame-support/std", "frame-system/std", diff --git a/control/src/benchmarking.rs b/control/src/benchmarking.rs index c37dc35ce..e45c87abd 100644 --- a/control/src/benchmarking.rs +++ b/control/src/benchmarking.rs @@ -36,8 +36,8 @@ benchmarks! { }: _( RawOrigin::Signed(caller.clone()), caller.clone().into(), - (0..255).collect(), - (0..255).collect(), + BoundedVec::truncate_from((0..255).collect()), + BoundedVec::truncate_from((0..255).collect()), OrgType::Individual, AccessModel::Open, FeeModel::NoFees, @@ -77,7 +77,7 @@ benchmarks! { } add_member { - let r in 1 .. T::MaxMembersPerDAO::get()-1; // Limit members per org + let r in 1 .. T::MaxMembersPerOrg::get()-1; // Limit members per org // Prepare org creator and members let creator: T::AccountId = whitelisted_caller(); @@ -92,7 +92,7 @@ benchmarks! { // Create org and fill with members let org_id = as ControlBenchmarkingTrait>::create_org(creator.clone()).unwrap(); - Pallet::::fill_org_with_members(&org_id, &accounts)?; + Pallet::::fill_org_with_members(&org_id, accounts)?; }: _( RawOrigin::Signed(creator), org_id, @@ -103,7 +103,7 @@ benchmarks! { } remove_member { - let r in 1 .. T::MaxMembersPerDAO::get(); // Limit members per org + let r in 1 .. T::MaxMembersPerOrg::get(); // Limit members per org // Prepare org creator and members let creator: T::AccountId = whitelisted_caller(); @@ -117,7 +117,7 @@ benchmarks! { fund_accounts::(&accounts)?; // Add members to org - Pallet::::fill_org_with_members(&org_id, &accounts)?; + Pallet::::fill_org_with_members(&org_id, accounts.clone())?; }: _( RawOrigin::Signed(creator), org_id, @@ -137,6 +137,5 @@ benchmarks! { caller.clone() ) + impl_benchmark_test_suite!(Control, crate::mock::new_test_ext(), crate::mock::Test); } - -impl_benchmark_test_suite!(Control, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/control/src/lib.rs b/control/src/lib.rs index 5e55cfc11..3e7b86875 100755 --- a/control/src/lib.rs +++ b/control/src/lib.rs @@ -17,7 +17,6 @@ pub use types::*; mod mock; mod tests; -#[cfg(feature = "runtime-benchmarks")] mod benchmarking; pub mod weights; @@ -26,12 +25,13 @@ use frame_support::{ dispatch::{DispatchResult, DispatchError}, ensure, PalletId, traits::{Get}, + BoundedVec }; use gamedao_traits::{ControlTrait, ControlBenchmarkingTrait}; use orml_traits::{MultiCurrency, MultiReservableCurrency}; use scale_info::TypeInfo; use sp_runtime::traits::{AccountIdConversion, AtLeast32BitUnsigned, Hash}; -use sp_std::{fmt::Debug, vec, vec::Vec}; +use sp_std::{fmt::Debug, convert::TryInto, vec, vec::{Vec}}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; @@ -41,7 +41,7 @@ pub use weights::WeightInfo; #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::{pallet_prelude::*, transactional}; + use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; #[pallet::pallet] @@ -92,13 +92,21 @@ pub mod pallet { #[pallet::constant] type GameDAOTreasury: Get; - /// The max number of DAOs created per one account. + /// The max number of orgs per one account. #[pallet::constant] - type MaxDAOsPerAccount: Get; + type MaxOrgsPerAccount: Get; - /// The max number of members per one DAO. + /// The max number of orgs account can create. #[pallet::constant] - type MaxMembersPerDAO: Get; + type MaxCreationsPerAccount: Get; + + /// The max number of members per one org. + #[pallet::constant] + type MaxMembersPerOrg: Get; + + /// The max orgs which controller may own. + #[pallet::constant] + type MaxOrgsPerController: Get; #[pallet::constant] type MaxCreationsPerBlock: Get; @@ -114,6 +122,10 @@ pub mod pallet { /// The min amount of the deposit which is locked during Org creation (in Protocol tokens). #[pallet::constant] type MinimumDeposit: Get; + + /// The maximum length of a name or cid stored on-chain. + #[pallet::constant] + type StringLimit: Get; } /// Org by its id. @@ -121,7 +133,8 @@ pub mod pallet { /// Org: map Hash => Org #[pallet::storage] pub(super) type Orgs = - StorageMap<_, Blake2_128Concat, T::Hash, Org, ValueQuery>; + StorageMap<_, Blake2_128Concat, T::Hash, + Org>, OptionQuery>; /// Org id by its nonce. /// @@ -153,7 +166,8 @@ pub mod pallet { /// /// OrgMembers: map Hash => Vec #[pallet::storage] - pub(super) type OrgMembers = StorageMap<_, Blake2_128Concat, T::Hash, Vec, ValueQuery>; + pub(super) type OrgMembers = StorageMap<_, Blake2_128Concat, T::Hash, + BoundedVec, ValueQuery>; /// Org members count by org id. /// @@ -172,31 +186,33 @@ pub mod pallet { /// /// Memberships: map AccountId => Vec #[pallet::storage] - pub(super) type Memberships = StorageMap<_, Blake2_128Concat, T::AccountId, Vec, ValueQuery>; + pub(super) type Memberships = StorageMap<_, Blake2_128Concat, T::AccountId, + BoundedVec, ValueQuery>; /// Creator account of an Org. /// /// OrgCreator: map Hash => AccountId #[pallet::storage] - pub(super) type OrgCreator = StorageMap<_, Blake2_128Concat, T::Hash, T::AccountId, ValueQuery>; + pub(super) type OrgCreator = StorageMap<_, Blake2_128Concat, T::Hash, T::AccountId, OptionQuery>; /// Controller account of an Org. /// /// OrgController: map Hash => AccountId #[pallet::storage] - pub(super) type OrgController = StorageMap<_, Blake2_128Concat, T::Hash, T::AccountId, ValueQuery>; + pub(super) type OrgController = StorageMap<_, Blake2_128Concat, T::Hash, T::AccountId, OptionQuery>; /// Treasury account of an Org. /// /// OrgTreasury: map Hash => AccountId #[pallet::storage] - pub(super) type OrgTreasury = StorageMap<_, Blake2_128Concat, T::Hash, T::AccountId, ValueQuery>; + pub(super) type OrgTreasury = StorageMap<_, Blake2_128Concat, T::Hash, T::AccountId, OptionQuery>; /// Orgs created by account. /// /// OrgsCreated: map AccountId => Vec #[pallet::storage] - pub(super) type OrgsCreated = StorageMap<_, Blake2_128Concat, T::AccountId, Vec, ValueQuery>; + pub(super) type OrgsCreated = StorageMap<_, Blake2_128Concat, T::AccountId, + BoundedVec, ValueQuery>; /// Number of Orgs created by account. /// @@ -208,7 +224,8 @@ pub mod pallet { /// /// OrgsControlled: map AccountId => Vec #[pallet::storage] - pub(super) type OrgsControlled = StorageMap<_, Blake2_128Concat, T::AccountId, Vec, ValueQuery>; + pub(super) type OrgsControlled = StorageMap<_, Blake2_128Concat, T::AccountId, + BoundedVec, ValueQuery>; /// Number of Orgs controlled by account. /// @@ -225,8 +242,8 @@ pub mod pallet { #[pallet::genesis_config] pub struct GenesisConfig { - pub orgs: Vec<(T::AccountId, T::AccountId, T::AccountId, Vec, Vec, OrgType, - AccessModel, FeeModel, T::Balance, T::CurrencyId, T::CurrencyId, u64, T::Balance)>, + pub orgs: Vec<(T::AccountId, T::AccountId, T::AccountId, BoundedVec, BoundedVec, + OrgType, AccessModel, FeeModel, T::Balance, T::CurrencyId, T::CurrencyId, u64, T::Balance)>, } #[cfg(feature = "std")] @@ -249,7 +266,7 @@ pub mod pallet { creator_id.clone(), org_id.clone(), controller_id.clone(), treasury_id.clone(), name.clone(), cid.clone(), org_type.clone(), access.clone(), fee_model.clone(), fee.clone(), gov_asset.clone(), pay_asset.clone(), member_limit.clone(), deposit.clone(), nonce - ); + ).unwrap(); Pallet::::do_add_member( org_id, controller_id.clone(), fee.clone(), fee_model.clone(), ControlMemberState::Active ).unwrap(); @@ -324,8 +341,12 @@ pub mod pallet { GuruMeditation, /// Treasury account already exists. TreasuryExists, + /// Treasury account does not exists. + TreasuryNotExists, /// Minimum deposit to Treasury too low. - MinimumDepositTooLow + MinimumDepositTooLow, + /// Too many orgs, created or controlled by the account + TooManyOrgs } #[pallet::call] @@ -353,12 +374,11 @@ pub mod pallet { /// /// Weight: `O(1)` #[pallet::weight(T::WeightInfo::create_org())] - #[transactional] pub fn create_org( origin: OriginFor, controller_id: T::AccountId, - name: Vec, - cid: Vec, + name: BoundedVec, + cid: BoundedVec, org_type: OrgType, access: AccessModel, fee_model: FeeModel, @@ -384,7 +404,7 @@ pub mod pallet { // TODO validation: name, cid ? let nonce = Self::get_and_increment_nonce(); - let treasury_account_id = T::PalletId::get().into_sub_account(nonce as i32); + let treasury_account_id = T::PalletId::get().into_sub_account_truncating(nonce as i32); ensure!(!>::account_exists(&treasury_account_id), Error::::TreasuryExists); let org_id = T::Hashing::hash_of(&treasury_account_id); @@ -393,7 +413,7 @@ pub mod pallet { Self::do_create_org( sender.clone(), org_id.clone(), controller_id.clone(), treasury_account_id.clone(), name, cid, org_type, access, fee_model.clone(), fee.clone(), gov_asset, pay_asset, member_limit, org_deposit, nonce - ); + )?; Self::do_add_member(org_id.clone(), controller_id, fee, fee_model, ControlMemberState::Active)?; Self::mint_nft()?; @@ -456,7 +476,7 @@ pub mod pallet { /// /// Weight: `O(log n)` #[pallet::weight(T::WeightInfo::add_member( - T::MaxMembersPerDAO::get() + T::MaxMembersPerOrg::get() ))] pub fn add_member( origin: OriginFor, @@ -467,7 +487,7 @@ pub mod pallet { ensure!(Orgs::::contains_key(&org_id), Error::::OrganizationUnknown); ensure!(!OrgMembers::::get(org_id).contains(&account_id), Error::::MemberExists); ensure!( - OrgMemberCount::::get(&org_id) < T::MaxMembersPerDAO::get().into(), + OrgMemberCount::::get(&org_id) < T::MaxMembersPerOrg::get().into(), Error::::MembershipLimitReached ); let config = OrgConfiguration::::get(&org_id).ok_or(Error::::OrganizationUnknown)?; @@ -500,7 +520,7 @@ pub mod pallet { /// /// Weight: `O(log n)` #[pallet::weight(T::WeightInfo::remove_member( - T::MaxMembersPerDAO::get() + T::MaxMembersPerOrg::get() ))] pub fn remove_member(origin: OriginFor, org_id: T::Hash, account_id: T::AccountId) -> DispatchResultWithPostInfo { ensure_signed(origin)?; @@ -601,8 +621,8 @@ impl Pallet { org_id: T::Hash, controller_id: T::AccountId, treasury_id: T::AccountId, - name: Vec, - cid: Vec, + name: BoundedVec, + cid: BoundedVec, org_type: OrgType, access: AccessModel, fee_model: FeeModel, @@ -612,7 +632,7 @@ impl Pallet { member_limit: u64, deposit: T::Balance, nonce: u128 - ) { + ) -> Result<(), DispatchError> { let now = >::block_number(); let org = Org { @@ -651,10 +671,22 @@ impl Pallet { OrgController::::insert(org_id.clone(), controller_id.clone()); OrgTreasury::::insert(org_id.clone(), treasury_id.clone()); OrgState::::insert(org_id.clone(), ControlState::Active); - OrgsControlled::::mutate(&controller_id, |controlled| controlled.push(org_id.clone())); + OrgsControlled::::try_mutate( + &controller_id, + |ref mut controlled| -> Result<(), DispatchError> { + controlled.try_push(org_id.clone()).map_err(|_| Error::::TooManyOrgs)?; + Ok(()) + } + )?; OrgsControlledCount::::mutate(&controller_id, |controlled_count| *controlled_count += 1); - OrgsCreated::::mutate(&creator, |created| created.push(org_id.clone())); + OrgsCreated::::try_mutate( + &creator, + |ref mut created| -> Result<(), DispatchError> { + created.try_push(org_id.clone()).map_err(|_| Error::::TooManyOrgs)?; + Ok(()) + } + )?; // initiate member registry -> consumes fees // creator and controller can be equal @@ -671,6 +703,7 @@ impl Pallet { deposit, ); debug_assert!(res.is_ok()); + Ok(()) } fn mint_nft() -> DispatchResult { @@ -797,7 +830,7 @@ impl Pallet { }, // transfer to treasury FeeModel::Transfer => { - let treasury = OrgTreasury::::get(org_id); + let treasury = OrgTreasury::::get(org_id).ok_or(Error::::TreasuryNotExists)?; let res = T::Currency::transfer(currency_id, &account_id, &treasury, fee); debug_assert!(res.is_ok()); } @@ -823,7 +856,7 @@ impl Pallet { // not a member, insert at index Err(index) => { - members.insert(index, account_id.clone()); + members.try_insert(index, account_id.clone()).map_err(|_| Error::::MemberAddOverflow)?; // OrgMembers::::mutate( &org_id, |members| members.push(account_id.clone()) ); OrgMembers::::insert(&org_id, members.clone()); @@ -831,7 +864,7 @@ impl Pallet { OrgMemberCount::::insert(&org_id, count as u64); let mut memberships = Memberships::::get(&account_id); - memberships.push(org_id.clone()); + memberships.try_push(org_id.clone()).map_err(|_| Error::::MembershipLimitReached)?; Memberships::::insert(&account_id, memberships); // Member state @@ -899,10 +932,10 @@ impl Pallet { impl ControlTrait for Pallet { - fn org_controller_account(org_id: &T::Hash) -> T::AccountId { + fn org_controller_account(org_id: &T::Hash) -> Option { OrgController::::get(org_id) } - fn org_treasury_account(org_id: &T::Hash) -> T::AccountId { + fn org_treasury_account(org_id: &T::Hash) -> Option { OrgTreasury::::get(org_id) } fn is_org_active(org_id: &T::Hash) -> bool { @@ -918,8 +951,8 @@ impl ControlBenchmarkingTrait for Pallet { #[cfg(feature = "runtime-benchmarks")] fn create_org(caller: T::AccountId) -> Result { let org_nonce = Nonce::::get(); - let name: Vec = vec![0; 255]; - let cid: Vec = vec![0; 255]; + let name: BoundedVec = BoundedVec::truncate_from(vec![0; T::StringLimit::get() as usize]); + let cid: BoundedVec = BoundedVec::truncate_from(vec![0; T::StringLimit::get() as usize]); Pallet::::create_org( frame_system::RawOrigin::Signed(caller.clone()).into(), caller.into(), @@ -941,8 +974,8 @@ impl ControlBenchmarkingTrait for Pallet { /// ** Should be used for benchmarking only!!! ** #[cfg(feature = "runtime-benchmarks")] - fn fill_org_with_members(org_id: &T::Hash, accounts: &Vec) -> Result<(), DispatchError> { - for acc in accounts { + fn fill_org_with_members(org_id: &T::Hash, accounts: Vec) -> Result<(), DispatchError> { + for acc in BoundedVec::::truncate_from(accounts) { Pallet::::add_member( frame_system::RawOrigin::Signed(acc.clone()).into(), org_id.clone(), diff --git a/control/src/mock.rs b/control/src/mock.rs index a8c528fd1..604a2f570 100644 --- a/control/src/mock.rs +++ b/control/src/mock.rs @@ -1,31 +1,39 @@ #![cfg(test)] use crate as pallet_control; -use frame_support::{PalletId, {traits::GenesisBuild}}; +use frame_support::{PalletId, {traits::GenesisBuild}, pallet_prelude::*}; use frame_system; +use codec::MaxEncodedLen; use sp_core::H256; -use sp_runtime::{testing::Header, traits::IdentityLookup}; +use sp_std::convert::{TryInto, TryFrom}; +use sp_runtime::{testing::Header, traits::{ConstU32, IdentityLookup}}; // Types: pub type AccountId = u32; pub type BlockNumber = u64; pub type Hash = H256; -pub type Timestamp = u64; -pub type Moment = u64; pub type Balance = u128; pub type Amount = i128; pub type CurrencyId = u32; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; +#[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, RuntimeDebug, PartialOrd, Ord, MaxEncodedLen, TypeInfo)] +#[repr(u8)] +pub enum ReserveIdentifier { + CollatorSelection, + Nft, + TransactionPayment, + TransactionPaymentDeposit, + + // always the last, indicate number of variants + Count, +} + // Constants: pub const MILLICENTS: Balance = 1_000_000_000; pub const CENTS: Balance = 1_000 * MILLICENTS; pub const DOLLARS: Balance = 100 * CENTS; -pub const MILLISECS_PER_BLOCK: u64 = 6000; -pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); -pub const HOURS: BlockNumber = MINUTES * 60; -pub const DAYS: BlockNumber = HOURS * 24; pub const PROTOCOL_TOKEN_ID: CurrencyId = 1; pub const PAYMENT_TOKEN_ID: CurrencyId = 2; @@ -46,7 +54,7 @@ frame_support::construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Config, Storage, Event}, - Currencies: orml_currencies::{Pallet, Call, Event}, + Currencies: orml_currencies::{Pallet, Call}, Tokens: orml_tokens::{Pallet, Storage, Event, Config}, PalletBalances: pallet_balances::{Pallet, Call, Storage, Event}, Control: pallet_control::{Pallet, Call, Storage, Event}, @@ -84,8 +92,12 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = SS58Prefix; type OnSetCode = (); + type MaxConsumers = ConstU32<128>; } +frame_support::parameter_types! { + pub const MaxReserves: u32 = ReserveIdentifier::Count as u32; +} orml_traits::parameter_type_with_key! { pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance { Default::default() @@ -101,6 +113,10 @@ impl orml_tokens::Config for Test { type OnDust = (); type MaxLocks = (); type DustRemovalWhitelist = frame_support::traits::Nothing; + type OnNewTokenAccount = (); + type OnKilledTokenAccount = (); + type ReserveIdentifier = ReserveIdentifier; + type MaxReserves = MaxReserves; } frame_support::parameter_types! { @@ -113,24 +129,24 @@ impl pallet_balances::Config for Test { type ExistentialDeposit = ExistentialDeposit; type AccountStore = frame_system::Pallet; type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; + type MaxReserves = MaxReserves; + type ReserveIdentifier = ReserveIdentifier; type WeightInfo = (); } -pub type AdaptedBasicCurrency = orml_currencies::BasicCurrencyAdapter; impl orml_currencies::Config for Test { - type Event = Event; type MultiCurrency = Tokens; - type NativeCurrency = AdaptedBasicCurrency; + type NativeCurrency = orml_currencies::BasicCurrencyAdapter; type GetNativeCurrencyId = (); type WeightInfo = (); } frame_support::parameter_types! { - pub const MaxDAOsPerAccount: u32 = 2; - pub const MaxMembersPerDAO: u32 = 2; + pub const MaxOrgsPerAccount: u32 = 2; + pub const MaxMembersPerOrg: u32 = 2; pub const MaxCreationsPerBlock: u32 = 2; + pub const MaxCreationsPerAccount: u32 = 1000; + pub const MaxOrgsPerController: u32 = 100; pub const ProtocolTokenId: u32 = PROTOCOL_TOKEN_ID; pub const PaymentTokenId: CurrencyId = PAYMENT_TOKEN_ID; pub const MinimumDeposit: Balance = 5 * DOLLARS; @@ -144,15 +160,18 @@ impl pallet_control::Config for Test { type WeightInfo = (); type Event = Event; type Currency = Currencies; - type MaxDAOsPerAccount = MaxDAOsPerAccount; - type MaxMembersPerDAO = MaxMembersPerDAO; + type MaxOrgsPerAccount = MaxOrgsPerAccount; + type MaxMembersPerOrg = MaxMembersPerOrg; type MaxCreationsPerBlock = MaxCreationsPerBlock; + type MaxCreationsPerAccount = MaxCreationsPerAccount; + type MaxOrgsPerController = MaxOrgsPerController; type ProtocolTokenId = ProtocolTokenId; type PaymentTokenId = PaymentTokenId; type MinimumDeposit = MinimumDeposit; type PalletId = ControlPalletId; type Game3FoundationTreasury = Game3FoundationTreasuryAccountId; type GameDAOTreasury = GameDAOTreasuryAccountId; + type StringLimit = ConstU32<256>; } pub fn new_test_ext() -> sp_io::TestExternalities { diff --git a/control/src/tests.rs b/control/src/tests.rs index ebf388621..8ef833457 100644 --- a/control/src/tests.rs +++ b/control/src/tests.rs @@ -9,8 +9,9 @@ use mock::*; fn create_org() -> H256 { let nonce: u128 = Nonce::::get(); + let bounded_str = BoundedVec::truncate_from(vec![1,2]); assert_ok!( - Control::create_org(Origin::signed(ALICE), BOB, vec![1, 2], vec![2, 3], + Control::create_org(Origin::signed(ALICE), BOB, bounded_str.clone(), bounded_str, Default::default(), Default::default(), Default::default(), 1 * DOLLARS, PROTOCOL_TOKEN_ID, PAYMENT_TOKEN_ID, 10, None )); @@ -23,13 +24,14 @@ fn control_create_org() { new_test_ext().execute_with(|| { let current_block = 3; System::set_block_number(current_block); + let bounded_str = BoundedVec::truncate_from(vec![1,2]); let org_id = create_org(); System::assert_has_event( mock::Event::Control( crate::Event::OrgCreated { sender_id: ALICE, org_id, - treasury_id: OrgTreasury::::get(org_id), + treasury_id: OrgTreasury::::get(org_id).unwrap(), created_at: current_block, realm_index: 0 } @@ -39,7 +41,7 @@ fn control_create_org() { // to make a deposit into org's treasury // Error: BalanceTooLow assert_noop!( - Control::create_org(Origin::signed(BOB), BOB, vec![1, 2], vec![2, 3], + Control::create_org(Origin::signed(BOB), BOB, bounded_str.clone(), bounded_str.clone(), Default::default(), Default::default(), Default::default(), 1 * DOLLARS, PROTOCOL_TOKEN_ID, PAYMENT_TOKEN_ID, 10, None), @@ -50,7 +52,7 @@ fn control_create_org() { // Error: BalanceTooLow let deposit = 101 * DOLLARS; assert_noop!( - Control::create_org(Origin::signed(BOB), BOB, vec![1, 2], vec![2, 3], + Control::create_org(Origin::signed(BOB), BOB, bounded_str.clone(), bounded_str, Default::default(), Default::default(), Default::default(), 1 * DOLLARS, PROTOCOL_TOKEN_ID, PAYMENT_TOKEN_ID, 10, Some(deposit)), @@ -152,4 +154,4 @@ fn control_add_remove_member_errors() { Error::::MemberUnknown ); }) -} \ No newline at end of file +} diff --git a/control/src/types.rs b/control/src/types.rs index 92e06a65f..ec9ddbf69 100644 --- a/control/src/types.rs +++ b/control/src/types.rs @@ -1,7 +1,8 @@ use super::*; use frame_support::pallet_prelude::*; +use codec::MaxEncodedLen; -#[derive(Encode, Decode, PartialEq, Clone, Eq, PartialOrd, Ord, TypeInfo)] +#[derive(Encode, Decode, PartialEq, Clone, Eq, PartialOrd, Ord, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub enum OrgType { Individual = 0, @@ -15,7 +16,7 @@ impl Default for OrgType { } } -#[derive(Encode, Decode, PartialEq, Clone, Eq, PartialOrd, Ord, TypeInfo)] +#[derive(Encode, Decode, PartialEq, Clone, Eq, PartialOrd, Ord, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] #[repr(u8)] pub enum ControlMemberState { @@ -33,7 +34,7 @@ impl Default for ControlMemberState { } } -#[derive(Encode, Decode, PartialEq, Clone, Eq, PartialOrd, Ord, TypeInfo)] +#[derive(Encode, Decode, PartialEq, Clone, Eq, PartialOrd, Ord, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] #[repr(u8)] pub enum ControlState { @@ -48,7 +49,7 @@ impl Default for ControlState { } } -#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, TypeInfo)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub enum FeeModel { NoFees = 0, // feeless @@ -61,7 +62,7 @@ impl Default for FeeModel { } } -#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, TypeInfo)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub enum AccessModel { Open = 0, // anyDAO can join @@ -75,9 +76,9 @@ impl Default for AccessModel { } /// Organization -#[derive(Encode, Decode, Default, PartialEq, Eq, TypeInfo)] +#[derive(Encode, Decode, Default, PartialEq, Eq, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -pub struct Org { +pub struct Org { /// Org Hash pub(super) id: Hash, /// Org global index @@ -85,9 +86,9 @@ pub struct Org { /// Org Creator pub(super) creator: AccountId, /// Org Name - pub(super) name: Vec, + pub(super) name: BoundedString, /// IPFS Hash - pub(super) cid: Vec, + pub(super) cid: BoundedString, /// Organization Type pub(super) org_type: OrgType, /// Creation Block @@ -98,7 +99,7 @@ pub struct Org { /// Organization Config // TODO: refactor to bit flags -#[derive(Encode, Decode, PartialEq, Eq, TypeInfo)] +#[derive(Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub struct OrgConfig { /// Fee Model: TX only | Reserve | Transfer diff --git a/control/src/weights.rs b/control/src/weights.rs index 91eaa98d6..694f52f8f 100644 --- a/control/src/weights.rs +++ b/control/src/weights.rs @@ -18,12 +18,13 @@ //! Autogenerated weights for gamedao_control //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-06-22, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128 +//! DATE: 2022-07-11, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 // Executed Command: // ./target/release/subzero // benchmark +// pallet // --pallet=gamedao_control // --extrinsic=* // --steps=20 @@ -70,18 +71,18 @@ impl WeightInfo for SubstrateWeight { // Storage: Control OrgMemberState (r:0 w:1) // Storage: Control OrgCreator (r:0 w:1) fn create_org() -> Weight { - (41_000_000 as Weight) + (93_882_000 as Weight) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(19 as Weight)) } // Storage: Control OrgState (r:0 w:1) fn disable_org() -> Weight { - (8_000_000 as Weight) + (21_063_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Control OrgState (r:0 w:1) fn enable_org() -> Weight { - (7_000_000 as Weight) + (18_289_000 as Weight) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } // Storage: Control Orgs (r:1 w:0) @@ -91,9 +92,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Control Memberships (r:1 w:1) // Storage: Control OrgMemberState (r:0 w:1) fn add_member(r: u32, ) -> Weight { - (19_229_000 as Weight) - // Standard Error: 1_000 - .saturating_add((223_000 as Weight).saturating_mul(r as Weight)) + (59_829_000 as Weight) + // Standard Error: 3_000 + .saturating_add((104_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } @@ -104,15 +105,15 @@ impl WeightInfo for SubstrateWeight { // Storage: Control OrgMemberCount (r:0 w:1) // Storage: Control OrgMemberState (r:0 w:1) fn remove_member(r: u32, ) -> Weight { - (18_021_000 as Weight) - // Standard Error: 2_000 - .saturating_add((230_000 as Weight).saturating_mul(r as Weight)) + (63_208_000 as Weight) + // Standard Error: 3_000 + .saturating_add((104_000 as Weight).saturating_mul(r as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } // Storage: Control OrgMembers (r:1 w:0) fn check_membership() -> Weight { - (9_000_000 as Weight) + (23_141_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) } } @@ -138,18 +139,18 @@ impl WeightInfo for () { // Storage: Control OrgMemberState (r:0 w:1) // Storage: Control OrgCreator (r:0 w:1) fn create_org() -> Weight { - (41_000_000 as Weight) + (93_882_000 as Weight) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().writes(19 as Weight)) } // Storage: Control OrgState (r:0 w:1) fn disable_org() -> Weight { - (8_000_000 as Weight) + (21_063_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Control OrgState (r:0 w:1) fn enable_org() -> Weight { - (7_000_000 as Weight) + (18_289_000 as Weight) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } // Storage: Control Orgs (r:1 w:0) @@ -159,9 +160,9 @@ impl WeightInfo for () { // Storage: Control Memberships (r:1 w:1) // Storage: Control OrgMemberState (r:0 w:1) fn add_member(r: u32, ) -> Weight { - (19_229_000 as Weight) - // Standard Error: 1_000 - .saturating_add((223_000 as Weight).saturating_mul(r as Weight)) + (59_829_000 as Weight) + // Standard Error: 3_000 + .saturating_add((104_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } @@ -172,15 +173,15 @@ impl WeightInfo for () { // Storage: Control OrgMemberCount (r:0 w:1) // Storage: Control OrgMemberState (r:0 w:1) fn remove_member(r: u32, ) -> Weight { - (18_021_000 as Weight) - // Standard Error: 2_000 - .saturating_add((230_000 as Weight).saturating_mul(r as Weight)) + (63_208_000 as Weight) + // Standard Error: 3_000 + .saturating_add((104_000 as Weight).saturating_mul(r as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } // Storage: Control OrgMembers (r:1 w:0) fn check_membership() -> Weight { - (9_000_000 as Weight) + (23_141_000 as Weight) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) } } diff --git a/flow/Cargo.toml b/flow/Cargo.toml index 74489ea13..4654f59b8 100644 --- a/flow/Cargo.toml +++ b/flow/Cargo.toml @@ -14,13 +14,13 @@ repository = "https://github.com/gamedaoco/gamedao-protocol" [dependencies] serde = { version = "1.0.124", optional = true } -codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false, optional = true } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false, optional = true } orml-traits = { path = "../../orml/traits", default-features = false } orml-tokens = { path = "../../orml/tokens", optional = true } @@ -30,12 +30,12 @@ gamedao-traits = { package = "gamedao-traits", path = "../traits", default-featu gamedao-control = { package = "gamedao-control", path = "../control", optional = true } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -frame-support-test = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +frame-support-test = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } -pallet-timestamp = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } +pallet-timestamp = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } gamedao-control = { package = "gamedao-control", path = "../control", default-features = true } diff --git a/flow/src/benchmarking.rs b/flow/src/benchmarking.rs index d654a2361..66eba7198 100644 --- a/flow/src/benchmarking.rs +++ b/flow/src/benchmarking.rs @@ -46,7 +46,7 @@ benchmarks! { // 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); + let treasury_id = T::Control::org_treasury_account(&org_id).unwrap(); fund_account::(&treasury_id)?; // Create some campaigns, respecting per block limitation @@ -63,15 +63,15 @@ benchmarks! { RawOrigin::Signed(caller.clone()), org_id, caller.clone(), - vec![0; T::MaxNameLength::get() as usize], + BoundedVec::truncate_from(vec![0; T::StringLimit::get() as usize]), T::MinContribution::get(), T::MinContribution::get(), frame_system::Pallet::::block_number() + 200_u32.into(), Default::default(), Default::default(), - vec![0; T::MaxNameLength::get() as usize], - vec![0; 5], - vec![0; 32] + BoundedVec::truncate_from(vec![0; T::StringLimit::get() as usize]), + BoundedVec::truncate_from(vec![0; 5]), + BoundedVec::truncate_from(vec![0; 32]) ) verify { assert!(CampaignsCount::::get() == count_before + 1); @@ -86,7 +86,7 @@ benchmarks! { // 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); + let treasury_id = T::Control::org_treasury_account(&org_id).unwrap(); fund_account::(&treasury_id)?; // Create some campaigns, respecting per block limitation @@ -118,7 +118,7 @@ benchmarks! { // Prepare organization and treasury let org_id = T::Control::create_org(owner.clone().into())?; - let treasury_id = T::Control::org_treasury_account(&org_id); + let treasury_id = T::Control::org_treasury_account(&org_id).unwrap(); fund_account::(&treasury_id)?; // Create campaign to use for contributions @@ -140,7 +140,7 @@ benchmarks! { // Prepare organization and treasury let org_id = T::Control::create_org(owner.clone().into())?; - let treasury_id = T::Control::org_treasury_account(&org_id); + let treasury_id = T::Control::org_treasury_account(&org_id).unwrap(); fund_account::(&treasury_id)?; // Create campaign and add some contributions @@ -152,7 +152,7 @@ benchmarks! { } // Trigger on_finalize to prepare object to be used in initialize hook - let mut block_number = Campaigns::::get(&campaign_id).expiry; + let mut block_number = Campaigns::::get(&campaign_id).unwrap().expiry; frame_system::Pallet::::set_block_number(block_number.clone()); Flow::::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 e554989fe..be02e6a5c 100644 --- a/flow/src/lib.rs +++ b/flow/src/lib.rs @@ -35,8 +35,7 @@ // 1. create campaigns with custom funding goal and runtime // 2. invest into open campaigns #![cfg_attr(not(feature = "std"), no_std)] -// #[warn(unused_imports)] -// pub use weights::WeightInfo; +#![allow(deprecated)] // TODO: clean transactional pub mod types; pub use types::*; @@ -53,15 +52,16 @@ pub mod weights; use frame_support::{ dispatch::{DispatchResult, DispatchError, DispatchResultWithPostInfo}, traits::{Get, BalanceStatus, Hooks, StorageVersion, UnixTime}, + weights::Weight, transactional, - weights::Weight + BoundedVec }; use scale_info::TypeInfo; use sp_runtime::{traits::{AtLeast32BitUnsigned, Hash, Saturating}, Permill}; -use sp_std::{vec, vec::Vec}; -use sp_std::convert::TryFrom; +use sp_std::{vec, vec::Vec, convert::{TryFrom, TryInto}}; + use gamedao_traits::{ControlTrait, ControlBenchmarkingTrait, FlowTrait, FlowBenchmarkingTrait}; use orml_traits::{MultiCurrency, MultiReservableCurrency}; @@ -129,10 +129,6 @@ pub mod pallet { /// The min length of a campaign name. #[pallet::constant] type MinNameLength: Get; - - /// The max length of a campaign name. - #[pallet::constant] - type MaxNameLength: Get; #[pallet::constant] type MaxCampaignsPerAddress: Get; @@ -148,11 +144,18 @@ pub mod pallet { #[pallet::constant] type MaxContributionsPerBlock: Get; + /// The max number of contributions per one Campaign. + #[pallet::constant] + type MaxCampaignContributions: Get; + /// The max number of contributors for processing in one block (batch size) /// during Campaign finalization. #[pallet::constant] type MaxContributorsProcessing: Get; + #[pallet::constant] + type MaxCampaignsPerStatus: Get; + /// The min number of blocks for campaign duration. #[pallet::constant] type MinCampaignDuration: Get; @@ -177,6 +180,10 @@ pub mod pallet { /// after successfull Campaign finalization #[pallet::constant] type CampaignFee: Get; + + /// The maximum length of a name or symbol stored on-chain. + #[pallet::constant] + type StringLimit: Get; } /// Campaign by its id. @@ -187,8 +194,8 @@ pub mod pallet { _, Blake2_128Concat, T::Hash, - Campaign, - ValueQuery, + Campaign>, + OptionQuery, >; /// Org id by campaign id. @@ -220,16 +227,21 @@ pub mod pallet { /// 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: double_map FlowState, Hash => Vec + /// CampaignsByState: double_map FlowState, Hash => BoundedVec #[pallet::storage] - pub(super) type CampaignsByState = StorageDoubleMap<_, Blake2_128Concat, FlowState, Blake2_128Concat, T::Hash, Vec, ValueQuery>; + pub(super) type CampaignsByState = StorageDoubleMap<_, + Blake2_128Concat, FlowState, + Blake2_128Concat, T::Hash, + BoundedVec, + ValueQuery + >; /// Campaigns ending in block x. /// - /// CampaignsByBlock: map BlockNumber => Vec + /// CampaignsByBlock: map BlockNumber => BoundedVec #[pallet::storage] pub(super) type CampaignsByBlock = - StorageMap<_, Blake2_128Concat, T::BlockNumber, Vec, ValueQuery>; + StorageMap<_, Blake2_128Concat, T::BlockNumber, BoundedVec, ValueQuery>; /// Total number of campaigns -> campaign id. /// @@ -285,16 +297,16 @@ pub mod pallet { /// The list of campaigns contributed by account id. /// - /// CampaignsContributed: map AccountId => Vec + /// CampaignsContributed: map AccountId => BoundedVec #[pallet::storage] pub(super) type CampaignsContributed = - StorageMap<_, Blake2_128Concat, T::AccountId, Vec, ValueQuery>; + StorageMap<_, Blake2_128Concat, T::AccountId, BoundedVec, ValueQuery>; /// Campaigns related to an organization. /// - /// CampaignsByOrg: map Hash => Vec + /// CampaignsByOrg: map Hash => BoundedVec #[pallet::storage] - pub(super) type CampaignsByOrg = StorageMap<_, Blake2_128Concat, T::Hash, Vec, ValueQuery>; + pub(super) type CampaignsByOrg = StorageMap<_, Blake2_128Concat, T::Hash, BoundedVec, ValueQuery>; /// (account id, total number of campaigns contributed by account id) -> campaign id. /// @@ -333,10 +345,11 @@ pub mod pallet { /// Campaign contributors by campaign id. /// - /// CampaignContributors: map Hash => Vec + /// CampaignContributors: map Hash => BoundedVec #[pallet::storage] pub(super) type CampaignContributors = - StorageMap<_, Blake2_128Concat, T::Hash, Vec, ValueQuery>; + // TODO: Contributor vs Contribution? + StorageMap<_, Blake2_128Concat, T::Hash, BoundedVec, ValueQuery>; /// Total number of contributors for particular campaign. /// @@ -370,7 +383,7 @@ pub mod pallet { target: T::Balance, deposit: T::Balance, expiry: T::BlockNumber, - name: Vec, + name: BoundedVec, }, /// Campaign was contributed. CampaignContributed { @@ -411,7 +424,7 @@ pub mod pallet { state: FlowState, block_number: T::BlockNumber, }, - Message(Vec), + Message(BoundedVec), } #[pallet::error] @@ -441,6 +454,10 @@ pub mod pallet { CampaignExpired, /// Cannot dispense Campaigns from an unsuccessful Campaign. UnsuccessfulCampaign, + /// Campaigns limit reached. + TooManyCampaigns, + /// Contributors limit reached. + TooManyContributors, // create /// Campaign must end after it starts. @@ -451,8 +468,8 @@ pub mod pallet { CampaignsPerBlockExceeded, /// Max campaigns per org exceeded. CampaignsPerOrgExceeded, - /// Name too long. - NameTooLong, + /// Max campaigns per state exceeded. + CampaignsPerStateExceeded, /// Name too short. NameTooShort, /// Deposit exceeds the campaign target. @@ -503,7 +520,7 @@ pub mod pallet { } fn on_runtime_upgrade() -> Weight { - migration::migrate::() + migration::migrate::() } } @@ -535,24 +552,24 @@ pub mod pallet { origin: OriginFor, org_id: T::Hash, admin_id: T::AccountId, - name: Vec, + name: BoundedVec, target: T::Balance, deposit: T::Balance, expiry: T::BlockNumber, protocol: FlowProtocol, governance: FlowGovernance, - cid: Vec, - token_symbol: Vec, // up to 5 - token_name: Vec, /* cleartext + cid: BoundedVec, + token_symbol: BoundedVec, // up to 5 + token_name: BoundedVec, /* cleartext * token_curve_a: u8, // preset - * token_curve_b: Vec, // custom */ + * token_curve_b: BoundedVec, // custom */ ) -> DispatchResultWithPostInfo { let creator = ensure_signed(origin)?; - let owner = T::Control::org_controller_account(&org_id); + let owner = T::Control::org_controller_account(&org_id).ok_or(Error::::OwnerUnknown)?; ensure!(creator == owner, Error::::AuthorizationError); // Get Treasury account for deposits and fees - let treasury_id = T::Control::org_treasury_account(&org_id); + let treasury_id = T::Control::org_treasury_account(&org_id).unwrap(); let free_balance = T::Currency::free_balance(T::ProtocolTokenId::get(), &treasury_id); ensure!(free_balance > deposit, Error::::TreasuryBalanceTooLow); @@ -564,7 +581,6 @@ pub mod pallet { // check name length boundary ensure!((name.len() as u32) >= T::MinNameLength::get(), Error::::NameTooShort); - ensure!((name.len() as u32) <= T::MaxNameLength::get(), Error::::NameTooLong); let current_block = >::block_number(); @@ -616,7 +632,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, &org_id); + Self::set_state(id.clone(), FlowState::Active, &org_id)?; // deposit the event Self::deposit_event(Event::CampaignCreated { @@ -656,7 +672,7 @@ pub mod pallet { ensure!(sender == admin, Error::::AuthorizationError); // expired? - let campaign = Campaigns::::get(&campaign_id); + let campaign = Campaigns::::get(&campaign_id).ok_or(Error::::IdUnknown)?; let current_block = >::block_number(); ensure!(current_block < campaign.expiry, Error::::CampaignExpired); @@ -666,7 +682,7 @@ pub mod pallet { let current_state = CampaignState::::get(&campaign_id); ensure!(current_state < FlowState::Success, Error::::CampaignExpired); - Self::set_state(campaign_id.clone(), state.clone(), &org_id); + Self::set_state(campaign_id.clone(), state.clone(), &org_id)?; // dispatch status update event Self::deposit_event(Event::CampaignUpdated { @@ -701,7 +717,7 @@ pub mod pallet { ensure!(Campaigns::::contains_key(campaign_id), Error::::InvalidId); let state = CampaignState::::get(campaign_id); ensure!(state == FlowState::Active, Error::::NoContributionsAllowed); - let campaign = Campaigns::::get(&campaign_id); + let campaign = Campaigns::::get(&campaign_id).ok_or(Error::::IdUnknown)?; ensure!( >::block_number() < campaign.expiry, Error::::CampaignExpired @@ -726,7 +742,7 @@ pub mod pallet { } impl Pallet { - fn set_state(campaign_id: T::Hash, state: FlowState, org_id: &T::Hash) { + fn set_state(campaign_id: T::Hash, state: FlowState, org_id: &T::Hash) -> DispatchResult { let current_state = CampaignState::::get(&campaign_id); // remove @@ -741,11 +757,18 @@ impl Pallet { } // add - CampaignsByState::::mutate(&state, org_id, |campaigns| campaigns.push(campaign_id.clone())); + CampaignsByState::::try_mutate( + &state, org_id, + |ref mut campaigns| -> Result<(), DispatchError> { + campaigns.try_push(campaign_id.clone()).map_err(|_| Error::::CampaignsPerStateExceeded)?; + Ok(()) + } + )?; CampaignState::::insert(campaign_id, state); + Ok(()) } - fn mint_campaign(campaign: Campaign) -> DispatchResult { + fn mint_campaign(campaign: Campaign>) -> DispatchResult { // add campaign to campaigns Campaigns::::insert(&campaign.id, campaign.clone()); // add org to index @@ -754,11 +777,23 @@ impl Pallet { CampaignOwner::::insert(&campaign.id, campaign.owner.clone()); // TODO: Admin == Council CampaignAdmin::::insert(&campaign.id, campaign.admin.clone()); - // add to campaigns by body - CampaignsByOrg::::mutate(&campaign.org, |campaigns| campaigns.push(campaign.id)); + // add to campaigns by org + CampaignsByOrg::::try_mutate( + &campaign.org, + |ref mut campaigns| -> Result<(), DispatchError> { + campaigns.try_push(campaign.id).map_err(|_| Error::::TooManyCampaigns)?; + Ok(()) + } + )?; // expiration - CampaignsByBlock::::mutate(&campaign.expiry, |campaigns| campaigns.push(campaign.id.clone())); + CampaignsByBlock::::mutate( + &campaign.expiry, + |ref mut campaigns| -> Result<(), DispatchError> { + campaigns.try_push(campaign.id.clone()).map_err(|_| Error::::TooManyCampaigns)?; + Ok(()) + } + )?; // global campaigns count @@ -785,7 +820,7 @@ impl Pallet { // TODO: this should be a proper mechanism // to reserve some of the staked GAME - let treasury = T::Control::org_treasury_account(&campaign.org); + let treasury = T::Control::org_treasury_account(&campaign.org).ok_or(Error::::InvalidId)?; T::Currency::reserve(T::ProtocolTokenId::get(), &treasury, campaign.deposit.clone())?; @@ -816,13 +851,19 @@ impl Pallet { CampaignContributorsCount::::insert(campaign_id.clone(), update_contributors); // add contibutor to campaign contributors - CampaignContributors::::mutate(&campaign_id, |accounts| accounts.push(sender.clone())); + CampaignContributors::::mutate( + &campaign_id, + |accounts| -> Result<(), DispatchError> { + accounts.try_push(sender.clone()).map_err(|_| Error::::TooManyContributors)?; + Ok(()) + } + )?; } // check if campaign is in contributions map of contributor and add let mut campaigns_contributed = CampaignsContributed::::get(&sender); if !campaigns_contributed.contains(&campaign_id) { - campaigns_contributed.push(campaign_id.clone()); + campaigns_contributed.try_push(campaign_id.clone()).map_err(|_| Error::::TooManyCampaigns)?; CampaignsContributed::::insert(&sender, campaigns_contributed); } @@ -851,12 +892,12 @@ impl Pallet { fn schedule_campaign_settlements(block_number: T::BlockNumber) { // Iterate over campaigns ending in this block for campaign_id in &CampaignsByBlock::::get(block_number) { - let campaign = Campaigns::::get(campaign_id); + let campaign = Campaigns::::get(campaign_id).unwrap(); let campaign_balance = CampaignBalance::::get(campaign_id); - + // Campaign cap reached: Finalizing if campaign_balance >= campaign.cap { - Self::set_state(campaign.id, FlowState::Finalizing, &campaign.org); + let _ = Self::set_state(campaign.id, FlowState::Finalizing, &campaign.org); Self::deposit_event(Event::CampaignFinalising { campaign_id: *campaign_id, @@ -866,7 +907,7 @@ impl Pallet { // Campaign cap not reached: Reverting } else { - Self::set_state(campaign.id, FlowState::Reverting, &campaign.org); + let _ = Self::set_state(campaign.id, FlowState::Reverting, &campaign.org); Self::deposit_event(Event::CampaignReverting { campaign_id: *campaign_id, @@ -879,12 +920,12 @@ impl Pallet { fn process_campaigns(block_number: &T::BlockNumber, state: FlowState, processed: &mut u32) -> u32 { let mut campaigns_processed: u32 = 0; - let campaign_ids_by_org: Vec<(T::Hash, Vec)> = CampaignsByState::::iter_prefix(&state).collect(); + let campaign_ids_by_org: Vec<(T::Hash, BoundedVec)> = 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 = Campaigns::::get(campaign_id).unwrap(); let campaign_balance = CampaignBalance::::get(&campaign_id); - let org_treasury = T::Control::org_treasury_account(&campaign.org); + let org_treasury = T::Control::org_treasury_account(&campaign.org).unwrap(); let contributors = CampaignContributors::::get(&campaign_id); if state == FlowState::Finalizing { @@ -904,7 +945,7 @@ impl Pallet { fn finalize_campaign( block_number: &T::BlockNumber, processed: &mut u32, - campaign: &Campaign, + campaign: &Campaign>, campaign_balance: &T::Balance, org_treasury: &T::AccountId, contributors: &Vec, owner: &T::AccountId ) { @@ -941,7 +982,7 @@ impl Pallet { 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, &campaign.org); + let _ = Self::set_state(campaign.id, FlowState::Reverting, &campaign.org); return } let commission = T::CampaignFee::get().mul_floor(campaign_balance.clone()); @@ -957,7 +998,7 @@ impl Pallet { let updated_balance = *campaign_balance - commission; CampaignBalance::::insert(campaign.id, updated_balance); - Self::set_state(campaign.id, FlowState::Success, &campaign.org); + let _ = Self::set_state(campaign.id, FlowState::Success, &campaign.org); Self::deposit_event(Event::CampaignFinalized { campaign_id: campaign.id, @@ -969,7 +1010,7 @@ impl Pallet { fn revert_campaign( block_number: &T::BlockNumber, processed: &mut u32, - campaign: &Campaign, + campaign: &Campaign>, campaign_balance: &T::Balance, org_treasury: &T::AccountId, contributors: &Vec ) { @@ -989,7 +1030,7 @@ impl Pallet { // Unreserve Initial deposit T::Currency::unreserve(T::ProtocolTokenId::get(), &org_treasury, campaign.deposit); - Self::set_state(campaign.id, FlowState::Failed, &campaign.org); + let _ = Self::set_state(campaign.id, FlowState::Failed, &campaign.org); Self::deposit_event(Event::CampaignFailed { campaign_id: campaign.id, campaign_balance: *campaign_balance, @@ -1020,13 +1061,14 @@ impl FlowTrait for Pallet { } impl FlowBenchmarkingTrait for Pallet { + /// ** Should be used for benchmarking only!!! ** #[cfg(feature = "runtime-benchmarks")] fn create_campaign(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 name: BoundedVec = BoundedVec::truncate_from(vec![0; T::StringLimit::get() as usize]); + let cid: BoundedVec = BoundedVec::truncate_from(vec![0; T::StringLimit::get() as usize]); + let token_symbol: BoundedVec = BoundedVec::truncate_from(vec![0; T::StringLimit::get() as usize]); + let token_name: BoundedVec = BoundedVec::truncate_from(vec![0; T::StringLimit::get() as usize]); 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(); @@ -1052,8 +1094,8 @@ impl FlowBenchmarkingTrait for /// ** Should be used for benchmarking only!!! ** #[cfg(feature = "runtime-benchmarks")] - fn create_contributions(campaign_id: &T::Hash, contributors: &Vec) -> Result<(), DispatchError> { - for account_id in contributors { + fn create_contributions(campaign_id: &T::Hash, contributors: Vec) -> Result<(), DispatchError> { + for account_id in BoundedVec::::truncate_from(contributors) { Pallet::::contribute( frame_system::RawOrigin::Signed(account_id.clone()).into(), campaign_id.clone(), diff --git a/flow/src/migration.rs b/flow/src/migration.rs index b97bae44c..42b7ae407 100644 --- a/flow/src/migration.rs +++ b/flow/src/migration.rs @@ -1,7 +1,7 @@ use frame_support::{ - generate_storage_alias, - traits::Get, + traits::{Get, GetStorageVersion, PalletInfoAccess, StorageVersion}, Blake2_128Concat, + BoundedVec }; use sp_std::prelude::*; use crate::{ @@ -14,14 +14,13 @@ use crate::{ }; -pub fn migrate() -> Weight { - use frame_support::traits::StorageVersion; +pub fn migrate() -> Weight { let version = StorageVersion::get::>(); let mut weight: Weight = 0; if version < 1 { - weight = weight.saturating_add(v1::migrate::()); + weight = weight.saturating_add(v1::migrate::()); StorageVersion::new(1).put::>(); } @@ -31,20 +30,31 @@ pub fn migrate() -> Weight { mod v1 { use super::*; - generate_storage_alias!( - Flow, - CampaignsByState => Map<(Blake2_128Concat, FlowState), Vec> - ); + #[frame_support::storage_alias] + type CampaignsByState = StorageMap< + Pallet, + Blake2_128Concat, + FlowState, + BoundedVec<::Hash, ::MaxCampaignsPerStatus> + >; - pub fn migrate() -> Weight { + pub fn migrate() -> Weight { let mut weight: Weight = 0; - let old_records: Vec<(FlowState, Vec)> = CampaignsByState::::drain().collect(); + let old_records: Vec<(FlowState, BoundedVec)> = 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)); + let updated = CampaignsByStateNew::::try_mutate( + &state, &org_id, + |campaigns| -> Result<(), ()> { + campaigns.try_push(campaign_id)?; + Ok(()) + } + ); + if updated.is_ok() { + weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); + } } } diff --git a/flow/src/mock.rs b/flow/src/mock.rs index c12b168f0..6fe7b5e91 100644 --- a/flow/src/mock.rs +++ b/flow/src/mock.rs @@ -4,18 +4,19 @@ pub use super::*; use frame_support::{ construct_runtime, parameter_types, PalletId, traits::{Everything, GenesisBuild, Nothing}, + pallet_prelude::*, }; use sp_core::H256; use sp_runtime::{traits::IdentityLookup, Permill}; use orml_traits::parameter_type_with_key; -impl Campaign { - pub fn new(campaign_id: Hash, expiry: BlockNumber) -> Campaign { +impl Campaign::StringLimit>> { + pub fn new(campaign_id: Hash, expiry: BlockNumber) -> Campaign::StringLimit>> { Campaign { id: campaign_id, org: H256::random(), - name: vec![1, 2], + name: BoundedVec::truncate_from(vec![1, 2]), owner: BOB, admin: BOB, deposit: 10 * DOLLARS, @@ -23,14 +24,26 @@ impl Campaign { cap: 110 * DOLLARS, protocol: FlowProtocol::Raise, governance: FlowGovernance::No, - cid: vec![1, 2], - token_symbol: vec![1, 2], - token_name: vec![1, 2], + cid: BoundedVec::truncate_from(vec![1, 2]), + token_symbol: BoundedVec::truncate_from(vec![1, 2]), + token_name: BoundedVec::truncate_from(vec![1, 2]), created: PalletTimestamp::now(), } } } +#[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, RuntimeDebug, PartialOrd, Ord, MaxEncodedLen, TypeInfo)] +#[repr(u8)] +pub enum ReserveIdentifier { + CollatorSelection, + Nft, + TransactionPayment, + TransactionPaymentDeposit, + + // always the last, indicate number of variants + Count, +} + // Types: pub type AccountId = u32; pub type BlockNumber = u64; @@ -104,6 +117,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = ConstU32<128>; } parameter_type_with_key! { @@ -111,6 +125,9 @@ parameter_type_with_key! { Default::default() }; } +parameter_types! { + pub const MaxReserves: u32 = ReserveIdentifier::Count as u32; +} impl orml_tokens::Config for Test { type Event = Event; @@ -121,7 +138,11 @@ impl orml_tokens::Config for Test { type ExistentialDeposits = ExistentialDeposits; type OnDust = (); type MaxLocks = (); + type MaxReserves = MaxReserves; + type OnNewTokenAccount = (); + type OnKilledTokenAccount = (); type DustRemovalWhitelist = Nothing; + type ReserveIdentifier = ReserveIdentifier; } parameter_types! { @@ -136,13 +157,12 @@ impl pallet_balances::Config for Test { type AccountStore = frame_system::Pallet; type MaxLocks = (); type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; + type ReserveIdentifier = ReserveIdentifier; type WeightInfo = (); } pub type AdaptedBasicCurrency = orml_currencies::BasicCurrencyAdapter; impl orml_currencies::Config for Test { - type Event = Event; type MultiCurrency = Tokens; type NativeCurrency = AdaptedBasicCurrency; type GetNativeCurrencyId = (); @@ -161,9 +181,11 @@ impl pallet_timestamp::Config for Test { } frame_support::parameter_types! { - pub const MaxDAOsPerAccount: u32 = 2; - pub const MaxMembersPerDAO: u32 = 2; + pub const MaxOrgsPerAccount: u32 = 2; + pub const MaxMembersPerOrg: u32 = 2; pub const MaxCreationsPerBlock: u32 = 2; + pub const MaxCreationsPerAccount: u32 = 1000; + pub const MaxOrgsPerController: u32 = 100; pub const ProtocolTokenId: u32 = PROTOCOL_TOKEN_ID; pub const PaymentTokenId: CurrencyId = PAYMENT_TOKEN_ID; pub const MinimumDeposit: Balance = 1 * DOLLARS; @@ -178,8 +200,10 @@ impl gamedao_control::Config for Test { type WeightInfo = (); type Event = Event; type Currency = Currencies; - type MaxDAOsPerAccount = MaxDAOsPerAccount; - type MaxMembersPerDAO = MaxMembersPerDAO; + type MaxOrgsPerAccount = MaxOrgsPerAccount; + type MaxMembersPerOrg = MaxMembersPerOrg; + type MaxCreationsPerAccount = MaxCreationsPerAccount; + type MaxOrgsPerController = MaxOrgsPerController; type MaxCreationsPerBlock = MaxCreationsPerBlock; type ProtocolTokenId = ProtocolTokenId; type PaymentTokenId = ProtocolTokenId; @@ -187,11 +211,11 @@ impl gamedao_control::Config for Test { type PalletId = ControlPalletId; type Game3FoundationTreasury = Game3FoundationTreasuryAccountId; type GameDAOTreasury = GameDAOTreasuryAccountId; + type StringLimit = ConstU32<256>; } parameter_types! { pub const MinNameLength: u32 = 2; - pub const MaxNameLength: u32 = 4; pub const MaxCampaignsPerAddress: u32 = 3; pub const MaxCampaignsPerBlock: u32 = 1; pub const MaxCampaignsPerOrg: u32 = 64; @@ -207,7 +231,6 @@ parameter_types! { impl Config for Test { type Balance = Balance; - // type Moment = Moment; type CurrencyId = CurrencyId; type WeightInfo = (); type Event = Event; @@ -219,15 +242,17 @@ impl Config for Test { type GameDAOTreasury = GameDAOTreasury; type MaxContributorsProcessing = MaxContributorsProcessing; type MinNameLength = MinNameLength; - type MaxNameLength = MaxNameLength; type MaxCampaignsPerAddress = MaxCampaignsPerAddress; type MaxCampaignsPerBlock = MaxCampaignsPerBlock; type MaxCampaignsPerOrg = MaxCampaignsPerOrg; type MaxContributionsPerBlock = MaxContributionsPerBlock; + type MaxCampaignContributions = ConstU32<1000>; + type MaxCampaignsPerStatus = ConstU32<10000>; type MinCampaignDuration = MinCampaignDuration; type MaxCampaignDuration = MaxCampaignDuration; type MinContribution = MinContribution; type CampaignFee = CampaignFee; + type StringLimit = ConstU32<256>; } construct_runtime!( @@ -237,7 +262,7 @@ construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Storage, Config, Event}, - Currencies: orml_currencies::{Pallet, Call, Event}, + Currencies: orml_currencies::{Pallet, Call}, Tokens: orml_tokens::{Pallet, Storage, Event, Config}, PalletBalances: pallet_balances::{Pallet, Call, Storage, Event}, PalletTimestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, diff --git a/flow/src/tests.rs b/flow/src/tests.rs index d6adc0873..1404422e9 100644 --- a/flow/src/tests.rs +++ b/flow/src/tests.rs @@ -13,13 +13,14 @@ use gamedao_control::{AccessModel, FeeModel, OrgType}; fn create_org_treasury() -> (H256, AccountId, Balance) { let nonce = Control::nonce(); assert_ok!(Control::create_org( - Origin::signed(BOB), BOB, vec![1, 2], vec![1, 2], + Origin::signed(BOB), BOB, + BoundedVec::truncate_from(vec![1, 2]), BoundedVec::truncate_from(vec![1, 2]), OrgType::default(), AccessModel::default(), FeeModel::default(), 0, 0, 0, 0, Some(1 * DOLLARS) )); - let treasury_id = ::PalletId::get().into_sub_account(nonce as i32); + let treasury_id = ::PalletId::get().into_sub_account_truncating(nonce as i32); let org_id = ::Hashing::hash_of(&treasury_id); - assert_eq!(treasury_id, Control::org_treasury_account(&org_id)); + assert_eq!(treasury_id, Control::org_treasury_account(&org_id).unwrap()); let tbalance = 30 * DOLLARS; let _ = Tokens::set_balance(RawOrigin::Root.into(), treasury_id, PROTOCOL_TOKEN_ID, tbalance, 0); @@ -31,6 +32,8 @@ fn flow_create_errors() { new_test_ext().execute_with(|| { let (org, _, _) = create_org_treasury(); let current_block = 3; + let empty_vec = BoundedVec::truncate_from(vec![]); + let name = BoundedVec::truncate_from(vec![1, 2]); System::set_block_number(current_block); // Check if creator is the controller of organization @@ -38,8 +41,12 @@ fn flow_create_errors() { let not_creator = ALICE; assert_noop!( Flow::create_campaign( - Origin::signed(not_creator), org, not_creator, vec![1, 2], 0, 0, 0, - FlowProtocol::Raise, FlowGovernance::No, vec![], vec![], vec![] + Origin::signed(not_creator), org, not_creator, + name.clone(), 0, 0, 0, + FlowProtocol::Raise, FlowGovernance::No, + empty_vec.clone(), + empty_vec.clone(), + empty_vec.clone(), ), Error::::AuthorizationError ); @@ -48,9 +55,12 @@ fn flow_create_errors() { let deposit_more_than_treasury = 1000 * DOLLARS; assert_noop!( Flow::create_campaign( - Origin::signed(BOB), org, BOB, vec![1, 2], 0, - deposit_more_than_treasury, 0, - FlowProtocol::Raise, FlowGovernance::No, vec![], vec![], vec![] + Origin::signed(BOB), org, BOB, + name.clone(), 0, deposit_more_than_treasury, 0, + FlowProtocol::Raise, FlowGovernance::No, + empty_vec.clone(), + empty_vec.clone(), + empty_vec.clone(), ), Error::::TreasuryBalanceTooLow ); @@ -60,39 +70,38 @@ fn flow_create_errors() { let deposit_more_than_target = 20 * DOLLARS; assert_noop!( Flow::create_campaign( - Origin::signed(BOB), org, BOB, vec![1, 2], - target, deposit_more_than_target, 0, - FlowProtocol::Raise, FlowGovernance::No, vec![], vec![], vec![] + Origin::signed(BOB), org, BOB, + name.clone(), target, deposit_more_than_target, 0, + FlowProtocol::Raise, FlowGovernance::No, + empty_vec.clone(), + empty_vec.clone(), + empty_vec.clone(), ), Error::::DepositTooHigh ); // Check Campaign name length // Error: NameTooShort - let short_name = vec![1]; + let short_name = BoundedVec::truncate_from(vec![1]); assert_noop!( Flow::create_campaign( Origin::signed(BOB), org, BOB, short_name, 20 * DOLLARS, 10 * DOLLARS, 0, - FlowProtocol::Raise, FlowGovernance::No, vec![], vec![], vec![] + FlowProtocol::Raise, FlowGovernance::No, + empty_vec.clone(), + empty_vec.clone(), + empty_vec.clone(), ), Error::::NameTooShort ); - // Error: NameTooLong - let long_name = vec![1, 2, 3, 4, 5]; - assert_noop!( - Flow::create_campaign( - Origin::signed(BOB), org, BOB, long_name, 20 * DOLLARS, 10 * DOLLARS, 0, - FlowProtocol::Raise, FlowGovernance::No, vec![], vec![], vec![] - ), - Error::::NameTooLong - ); // Ensure campaign expires after the current block // Error: EndTooEarly let expiration_block = current_block - 1; assert_noop!( Flow::create_campaign( - Origin::signed(BOB), org, BOB, vec![1, 2], 20 * DOLLARS, 10 * DOLLARS, + Origin::signed(BOB), org, BOB, name.clone(), 20 * DOLLARS, 10 * DOLLARS, expiration_block, FlowProtocol::Raise, FlowGovernance::No, - vec![], vec![],vec![] + empty_vec.clone(), + empty_vec.clone(), + empty_vec.clone(), ), Error::::EndTooEarly ); @@ -101,20 +110,33 @@ fn flow_create_errors() { let expiration_block = MaxCampaignDuration::get() + current_block + 1; assert_noop!( Flow::create_campaign( - Origin::signed(BOB), org, BOB, vec![1, 2], + Origin::signed(BOB), org, BOB, name.clone(), 20 * DOLLARS, 10 * DOLLARS, expiration_block, - FlowProtocol::Raise, FlowGovernance::No, vec![], vec![], vec![] + FlowProtocol::Raise, FlowGovernance::No, + empty_vec.clone(), + empty_vec.clone(), + empty_vec.clone(), ), Error::::EndTooLate ); // Check campaigns limit per block // Error: CampaignsPerBlockExceeded - CampaignsByBlock::::mutate(current_block + 1, |campaigns| campaigns.push(H256::random())); + assert_ok!(CampaignsByBlock::::try_mutate( + current_block + 1, + |campaigns| -> Result<(), Error::> { + campaigns.try_push(H256::random()).map_err(|_| Error::::TooManyCampaigns)?; + Ok(()) + } + )); + let block_campaigns_cnt = CampaignsByBlock::::get(current_block+1).len() as u32; + println!("Current limit is {:?} and max is {:?}", block_campaigns_cnt, ::MaxCampaignsPerBlock::get()); assert_noop!( Flow::create_campaign( - Origin::signed(BOB), org, BOB, vec![1, 2], 20 * DOLLARS, 10 * DOLLARS, + Origin::signed(BOB), org, BOB, name.clone(), 20 * DOLLARS, 10 * DOLLARS, current_block + 1, FlowProtocol::Raise, FlowGovernance::No, - vec![1, 2], vec![], vec![] + empty_vec.clone(), + empty_vec.clone(), + empty_vec.clone(), ), Error::::CampaignsPerBlockExceeded ); @@ -133,14 +155,17 @@ fn flow_create_success() { let expiry = current_block + 1; let deposit = 10 * DOLLARS; let target = 20 * DOLLARS; - let name = vec![1, 2]; + let name = BoundedVec::truncate_from(vec![1, 2]); assert_ok!(Flow::create_campaign( Origin::signed(BOB), org, BOB, name.clone(), target, deposit, expiry, - FlowProtocol::Raise, FlowGovernance::No, vec![1, 2], vec![], vec![] + FlowProtocol::Raise, FlowGovernance::No, + BoundedVec::truncate_from(vec![1, 2]), + BoundedVec::truncate_from(vec![]), + BoundedVec::truncate_from(vec![]), )); - assert_eq!(Campaigns::::get(id).id, id); + assert_eq!(Campaigns::::get(id).unwrap().id, id); assert_eq!(CampaignOrg::::get(id), org); assert_eq!(CampaignOwner::::get(id), Some(BOB)); assert_eq!(CampaignAdmin::::get(id), Some(BOB)); @@ -230,7 +255,7 @@ fn flow_update_state_success() { CampaignOwner::::insert(campaign_id, BOB); CampaignAdmin::::insert(campaign_id, BOB); CampaignOrg::::insert(campaign_id, campaign.org); - CampaignsByOrg::::insert(campaign.org, vec![campaign_id]); + CampaignsByOrg::::insert(campaign.org, BoundedVec::truncate_from(vec![campaign_id])); assert_ok!(Flow::update_state(Origin::signed(BOB), campaign_id, FlowState::Paused)); assert_eq!(CampaignsByState::::get(FlowState::Paused, &campaign.org), vec![campaign_id]); @@ -341,8 +366,13 @@ 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.clone(), BOB, vec![1, 2], target, deposit, expiry, - FlowProtocol::Raise, FlowGovernance::No, vec![1, 2], vec![], vec![] + Origin::signed(BOB), org.clone(), BOB, + BoundedVec::truncate_from(vec![1, 2]), + target, deposit, expiry, + FlowProtocol::Raise, FlowGovernance::No, + BoundedVec::truncate_from(vec![1, 2]), + BoundedVec::truncate_from(vec![]), + BoundedVec::truncate_from(vec![]), )); let total_contributors: u128 = 10; @@ -456,8 +486,13 @@ 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.clone(), BOB, vec![1, 2], target, deposit, expiry, - FlowProtocol::Raise, FlowGovernance::No, vec![1, 2], vec![], vec![] + Origin::signed(BOB), org.clone(), BOB, + BoundedVec::truncate_from(vec![1, 2]), + target, deposit, expiry, + FlowProtocol::Raise, FlowGovernance::No, + BoundedVec::truncate_from(vec![1, 2]), + BoundedVec::truncate_from(vec![]), + BoundedVec::truncate_from(vec![]), )); let total_contributors: u128 = 10; diff --git a/flow/src/types.rs b/flow/src/types.rs index 076824ff1..2c9fdc404 100644 --- a/flow/src/types.rs +++ b/flow/src/types.rs @@ -1,7 +1,6 @@ -use super::*; use frame_support::pallet_prelude::*; -#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, TypeInfo)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Debug))] #[repr(u8)] pub enum FlowProtocol { @@ -19,7 +18,7 @@ impl Default for FlowProtocol { } } -#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, TypeInfo)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Debug))] #[repr(u8)] pub enum FlowState { @@ -39,7 +38,7 @@ impl Default for FlowState { } } -#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, TypeInfo)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Debug))] #[repr(u8)] pub enum FlowGovernance { @@ -54,15 +53,15 @@ impl Default for FlowGovernance { } // TODO: this can be decomposed to improve weight -#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, TypeInfo)] +#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Debug))] -pub struct Campaign { +pub struct Campaign { // unique hash to identify campaign (generated) pub(super) id: Hash, // hash of the overarching body from module-control pub(super) org: Hash, // name - pub(super) name: Vec, + pub(super) name: BoundedString, // controller account -> must match body controller // during campaing runtime controller change is not allowed @@ -91,7 +90,7 @@ pub struct Campaign { pub(super) governance: FlowGovernance, /// content storage - pub(super) cid: Vec, + pub(super) cid: BoundedString, // TODO: prepare for launchpad functionality // token cap @@ -99,9 +98,9 @@ pub struct Campaign { // token_price // token_price: u64, // /// token symbol - pub(super) token_symbol: Vec, + pub(super) token_symbol: BoundedString, // /// token name - pub(super) token_name: Vec, + pub(super) token_name: BoundedString, /// creation timestamp pub(super) created: Moment, diff --git a/flow/src/weights.rs b/flow/src/weights.rs index 9dd841443..a18421033 100644 --- a/flow/src/weights.rs +++ b/flow/src/weights.rs @@ -18,12 +18,13 @@ //! Autogenerated weights for gamedao_flow //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-06-21, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128 +//! DATE: 2022-07-11, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 // Executed Command: // ./target/release/subzero // benchmark +// pallet // --pallet=gamedao_flow // --extrinsic=* // --steps=20 @@ -69,9 +70,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Flow CampaignOrg (r:0 w:1) // Storage: Flow CampaignsIndex (r:0 w:1) 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)) + (91_472_000 as Weight) + // Standard Error: 10_000 + .saturating_add((682_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)) } @@ -83,9 +84,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Flow CampaignState (r:1 w:1) // Storage: Flow CampaignsByState (r:2 w:2) 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)) + (54_719_000 as Weight) + // Standard Error: 10_000 + .saturating_add((543_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)) } @@ -102,7 +103,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Flow CampaignsContributedIndex (r:0 w:1) // Storage: Flow CampaignsContributedArray (r:0 w:1) fn contribute() -> Weight { - (53_779_000 as Weight) + (70_007_000 as Weight) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(9 as Weight)) } @@ -118,9 +119,9 @@ impl WeightInfo for SubstrateWeight { // Storage: System Account (r:1 w:1) // 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)) + (96_440_000 as Weight) + // Standard Error: 106_000 + .saturating_add((14_849_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)) @@ -150,9 +151,9 @@ impl WeightInfo for () { // Storage: Flow CampaignOrg (r:0 w:1) // Storage: Flow CampaignsIndex (r:0 w:1) 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)) + (91_472_000 as Weight) + // Standard Error: 10_000 + .saturating_add((682_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(12 as Weight)) .saturating_add(RocksDbWeight::get().writes(16 as Weight)) } @@ -164,9 +165,9 @@ impl WeightInfo for () { // Storage: Flow CampaignState (r:1 w:1) // Storage: Flow CampaignsByState (r:2 w:2) 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)) + (54_719_000 as Weight) + // Standard Error: 10_000 + .saturating_add((543_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } @@ -183,7 +184,7 @@ impl WeightInfo for () { // Storage: Flow CampaignsContributedIndex (r:0 w:1) // Storage: Flow CampaignsContributedArray (r:0 w:1) fn contribute() -> Weight { - (53_779_000 as Weight) + (70_007_000 as Weight) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().writes(9 as Weight)) } @@ -199,9 +200,9 @@ impl WeightInfo for () { // Storage: System Account (r:1 w:1) // 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)) + (96_440_000 as Weight) + // Standard Error: 106_000 + .saturating_add((14_849_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)) diff --git a/sense/Cargo.toml b/sense/Cargo.toml index aeaddfd93..d54891aa7 100755 --- a/sense/Cargo.toml +++ b/sense/Cargo.toml @@ -20,18 +20,18 @@ categories = [ [dependencies] serde = { version = "1.0.124", optional = true } -codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false, optional = true } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false, optional = true } [dev-dependencies] -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } [features] default = ["std"] diff --git a/sense/src/benchmarking.rs b/sense/src/benchmarking.rs index bce558e95..9d75d4e37 100644 --- a/sense/src/benchmarking.rs +++ b/sense/src/benchmarking.rs @@ -9,21 +9,21 @@ use sp_std::vec; benchmarks! { - create_entity {}: _(RawOrigin::Root, account("1", 0, 0), vec![1; 256]) + create_entity {}: _(RawOrigin::Root, account("1", 0, 0), BoundedVec::truncate_from(vec![1; 256])) mod_xp { let caller_origin = ::Origin::from(RawOrigin::Root); - Sense::::create_entity(caller_origin, account("1", 0, 0), vec![1; 1])?; + Sense::::create_entity(caller_origin, account("1", 0, 0), BoundedVec::truncate_from(vec![1; 1]))?; }: _(RawOrigin::Root, account("1", 0, 0), 255) mod_rep { let caller_origin = ::Origin::from(RawOrigin::Root); - Sense::::create_entity(caller_origin, account("1", 0, 0), vec![1; 1])?; + Sense::::create_entity(caller_origin, account("1", 0, 0), BoundedVec::truncate_from(vec![1; 1]))?; }: _(RawOrigin::Root, account("1", 0, 0), 255) mod_trust { let caller_origin = ::Origin::from(RawOrigin::Root); - Sense::::create_entity(caller_origin, account("1", 0, 0), vec![1; 1])?; + Sense::::create_entity(caller_origin, account("1", 0, 0), BoundedVec::truncate_from(vec![1; 1]))?; }: _(RawOrigin::Root, account("1", 0, 0), 255) } diff --git a/sense/src/lib.rs b/sense/src/lib.rs index decdf7032..f200bc271 100644 --- a/sense/src/lib.rs +++ b/sense/src/lib.rs @@ -13,11 +13,11 @@ //! Sense Properties: Experience, Reputation and Trust. #![cfg_attr(not(feature = "std"), no_std)] #[warn(unused_imports)] -use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; +use frame_support::{pallet_prelude::*, storage::bounded_vec::BoundedVec}; use frame_system::pallet_prelude::*; use scale_info::TypeInfo; -use sp_std::vec::Vec; - +use sp_std::convert::TryInto; +use codec::MaxEncodedLen; pub use weights::WeightInfo; #[cfg(feature = "runtime-benchmarks")] @@ -28,32 +28,29 @@ pub mod weights; pub use pallet::*; -pub const MAX_STRING_FIELD_LENGTH: usize = 256; -#[derive(Encode, Decode, Default, PartialEq, Eq, TypeInfo)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct Entity { +#[derive(Encode, Decode, Default, Eq, Copy, PartialEq, Clone, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct Entity { account: AccountId, index: u128, - cid: Vec, + cid: BoundedString, created: BlockNumber, mutated: BlockNumber, } -#[derive(Encode, Decode, Default, PartialEq, Eq, TypeInfo)] -#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Encode, Decode, Default, Eq, Copy, PartialEq, Clone, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct EntityProperty { value: u64, mutated: BlockNumber, } -impl Entity { +impl Entity { pub fn new( account: AccountId, block_number: BlockNumber, index: u128, - cid: Vec, - ) -> Entity + cid: BoundedString, + ) -> Entity where BlockNumber: Clone, { @@ -77,6 +74,10 @@ pub mod pallet { + IsType<::Event> + Into<::Event>; type WeightInfo: WeightInfo; + + /// The maximum length of a name or symbol stored on-chain. + #[pallet::constant] + type StringLimit: Get; } #[pallet::pallet] @@ -89,7 +90,7 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn entity)] pub(super) type SenseEntity = StorageMap<_, Blake2_128Concat, T::AccountId, - Entity, ValueQuery>; + Entity>, OptionQuery>; /// Experience property of the account. /// @@ -97,7 +98,7 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn xp)] pub(super) type SenseXP = - StorageMap<_, Blake2_128Concat, T::AccountId, EntityProperty, ValueQuery>; + StorageMap<_, Blake2_128Concat, T::AccountId, EntityProperty, OptionQuery>; /// Reputation property of the account. /// @@ -105,7 +106,7 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn rep)] pub(super) type SenseREP = - StorageMap<_, Blake2_128Concat, T::AccountId, EntityProperty, ValueQuery>; + StorageMap<_, Blake2_128Concat, T::AccountId, EntityProperty, OptionQuery>; /// Trust property of the account. /// @@ -113,7 +114,7 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn trust)] pub(super) type SenseTrust = - StorageMap<_, Blake2_128Concat, T::AccountId, EntityProperty, ValueQuery>; + StorageMap<_, Blake2_128Concat, T::AccountId, EntityProperty, OptionQuery>; /// Nonce. Increase per each entity creation. /// @@ -143,8 +144,6 @@ pub mod pallet { EntityUnknown, /// Guru Meditation. GuruMeditation, - /// Param limit exceed. - ParamLimitExceed, /// Invalid param. InvalidParam, /// Overflow adding a value to the entity property @@ -167,11 +166,10 @@ pub mod pallet { pub fn create_entity( origin: OriginFor, account_id: T::AccountId, - cid: Vec, + cid: BoundedVec, ) -> DispatchResult { ensure_root(origin)?; ensure!(cid.len() > 0, Error::::InvalidParam); - ensure!(cid.len() <= MAX_STRING_FIELD_LENGTH, Error::::ParamLimitExceed); ensure!(!>::contains_key(&account_id), Error::::EntityExists); let current_block = >::block_number(); @@ -218,7 +216,7 @@ pub mod pallet { let now = >::block_number(); let v = u64::from(value); - let current = Self::xp(&account_id); + let current = Self::xp(&account_id).unwrap(); let updated = EntityProperty { value: current.value.checked_add(v).ok_or(Error::::EntityPropertyOverflow)?, @@ -247,7 +245,7 @@ pub mod pallet { let now = >::block_number(); let v = u64::from(value); - let current = Self::rep(&account_id); + let current = Self::rep(&account_id).unwrap(); let updated = EntityProperty { value: current.value.checked_add(v).ok_or(Error::::EntityPropertyOverflow)?, @@ -276,7 +274,7 @@ pub mod pallet { let now = >::block_number(); let v = u64::from(value); - let current = Self::trust(&account_id); + let current = Self::trust(&account_id).unwrap(); let updated = EntityProperty { value: current.value.checked_add(v).ok_or(Error::::EntityPropertyOverflow)?, diff --git a/sense/src/mock.rs b/sense/src/mock.rs index f4f597718..06e65f05c 100644 --- a/sense/src/mock.rs +++ b/sense/src/mock.rs @@ -1,8 +1,12 @@ #![cfg(test)] -use frame_support::parameter_types; +use super::*; +use crate as pallet_sense; + +use frame_support::{construct_runtime, parameter_types}; use frame_system as system; use sp_core::H256; +use sp_std::convert::TryFrom; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, @@ -12,7 +16,7 @@ type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; // Configure a mock runtime to test the pallet. -frame_support::construct_runtime!( +construct_runtime!( pub enum Test where Block = Block, NodeBlock = Block, @@ -23,10 +27,6 @@ frame_support::construct_runtime!( } ); -mod pallet_sense { - pub use super::super::*; -} - parameter_types! { pub const BlockHashCount: u64 = 250; pub const SS58Prefix: u8 = 42; @@ -59,11 +59,17 @@ impl system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = SS58Prefix; type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +parameter_types! { + pub const StringLimit: u32 = 256; } impl pallet_sense::Config for Test { type Event = Event; type WeightInfo = (); + type StringLimit = StringLimit; } // Build genesis storage according to the mock runtime. diff --git a/sense/src/tests.rs b/sense/src/tests.rs index e91c8ee73..226ed1683 100644 --- a/sense/src/tests.rs +++ b/sense/src/tests.rs @@ -1,16 +1,16 @@ #![cfg(test)] use super::{ - mock::*, Entity, EntityProperty, Error, Event as SenseEvent, SenseEntity, SenseREP, SenseTrust, - SenseXP, + mock::*, }; -use frame_support::{assert_noop, assert_ok}; -use frame_system::{EventRecord, Phase, RawOrigin}; +use crate::{Event as SenseEvent, Entity, EntityProperty, Error, Config, SenseEntity, SenseREP, SenseTrust, SenseXP}; +use frame_support::{assert_noop, assert_ok, BoundedVec}; +use frame_system::RawOrigin; use sp_runtime::traits::BadOrigin; #[test] fn sense_create_entity() { new_test_ext().execute_with(|| { - let cid = vec![1, 2, 3]; + let cid: BoundedVec::StringLimit> = BoundedVec::truncate_from(vec![1,2,3]); let account = 1; let index = 0; @@ -19,36 +19,26 @@ fn sense_create_entity() { System::set_block_number(block_number); assert_noop!( - Sense::create_entity(RawOrigin::Root.into(), 1, vec![]), + Sense::create_entity(RawOrigin::Root.into(), 1, BoundedVec::default()), Error::::InvalidParam ); - assert_noop!( - Sense::create_entity(RawOrigin::Root.into(), 1, vec![1u8; 257]), - Error::::ParamLimitExceed - ); assert_ok!(Sense::create_entity(RawOrigin::Root.into(), account, cid.clone())); assert_eq!( Entity::new(account, block_number, index, cid.clone()), - Sense::entity(account) + Sense::entity(account).unwrap() ); - assert_eq!(EntityProperty::new(0, block_number), Sense::xp(account)); - assert_eq!(EntityProperty::new(0, block_number), Sense::rep(account)); - assert_eq!(EntityProperty::new(0, block_number), Sense::trust(account)); + assert_eq!(EntityProperty::new(0, block_number), Sense::xp(account).unwrap()); + assert_eq!(EntityProperty::new(0, block_number), Sense::rep(account).unwrap()); + assert_eq!(EntityProperty::new(0, block_number), Sense::trust(account).unwrap()); - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: Event::Sense(SenseEvent::EntityInit(account, block_number)), - topics: vec![], - }] + System::assert_has_event( + Event::Sense(SenseEvent::EntityInit(account, block_number)) ); // TODO: Check Nonce value increased in storage as a result of successful extrinsic call. - - assert_noop!(Sense::create_entity(Origin::signed(1), 1, vec![1u8]), BadOrigin); + assert_noop!(Sense::create_entity(Origin::signed(1), 1, cid.clone()), BadOrigin); assert_noop!( Sense::create_entity(RawOrigin::Root.into(), account, cid.clone()), @@ -68,6 +58,7 @@ macro_rules! sense_mod_tests { new_test_ext().execute_with(|| { let account = 1; let block_number = 3; + let cid: BoundedVec::StringLimit> = BoundedVec::truncate_from(vec![1,2,3]); System::set_block_number(block_number); assert_noop!($extrinsic(Origin::signed(1), 1, 1), BadOrigin); @@ -77,7 +68,7 @@ macro_rules! sense_mod_tests { ); SenseEntity::::insert( - account, Entity::new(account, block_number, 0, vec![1,2,3]) + account, Entity::new(account, block_number, 0, cid) ); $storage::::insert( account, EntityProperty::new(account, block_number) diff --git a/sense/src/weights.rs b/sense/src/weights.rs index d5269a970..c8b4c17d3 100644 --- a/sense/src/weights.rs +++ b/sense/src/weights.rs @@ -15,36 +15,31 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_sense +//! Autogenerated weights for gamedao_sense //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-11-15, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 +//! DATE: 2022-07-11, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 // Executed Command: -// ./target/release/node-template +// ./target/release/subzero // benchmark -// --chain=dev -// --execution=wasm -// --wasm-execution=compiled -// --pallet=pallet_sense +// pallet +// --pallet=gamedao_sense // --extrinsic=* // --steps=20 // --repeat=10 -// --raw -// --output=./pallets/sense/src/weights.rs +// --output=gamedao-protocol/sense/src/weights.rs // --template=./.maintain/frame-weight-template.hbs +#![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use sp_std::marker::PhantomData; -/// Weight functions needed for pallet_sense. +/// Weight functions needed for gamedao_sense. pub trait WeightInfo { fn create_entity() -> Weight; fn mod_xp() -> Weight; @@ -52,26 +47,37 @@ pub trait WeightInfo { fn mod_trust() -> Weight; } -/// Weights for pallet_sense using the Substrate node and recommended hardware. +/// Weights for gamedao_sense using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { + // Storage: Sense SenseEntity (r:1 w:1) + // Storage: Sense Nonce (r:1 w:1) + // Storage: Sense SenseTrust (r:0 w:1) + // Storage: Sense SenseREP (r:0 w:1) + // Storage: Sense SenseXP (r:0 w:1) fn create_entity() -> Weight { - (23_000_000 as Weight) + (28_232_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(5 as Weight)) } + // Storage: Sense SenseEntity (r:1 w:0) + // Storage: Sense SenseXP (r:1 w:1) fn mod_xp() -> Weight { - (18_000_000 as Weight) + (25_854_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + // Storage: Sense SenseEntity (r:1 w:0) + // Storage: Sense SenseREP (r:1 w:1) fn mod_rep() -> Weight { - (17_000_000 as Weight) + (24_018_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + // Storage: Sense SenseEntity (r:1 w:0) + // Storage: Sense SenseTrust (r:1 w:1) fn mod_trust() -> Weight { - (17_000_000 as Weight) + (22_808_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -79,24 +85,35 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { + // Storage: Sense SenseEntity (r:1 w:1) + // Storage: Sense Nonce (r:1 w:1) + // Storage: Sense SenseTrust (r:0 w:1) + // Storage: Sense SenseREP (r:0 w:1) + // Storage: Sense SenseXP (r:0 w:1) fn create_entity() -> Weight { - (23_000_000 as Weight) + (28_232_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } + // Storage: Sense SenseEntity (r:1 w:0) + // Storage: Sense SenseXP (r:1 w:1) fn mod_xp() -> Weight { - (18_000_000 as Weight) + (25_854_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } + // Storage: Sense SenseEntity (r:1 w:0) + // Storage: Sense SenseREP (r:1 w:1) fn mod_rep() -> Weight { - (17_000_000 as Weight) + (24_018_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } + // Storage: Sense SenseEntity (r:1 w:0) + // Storage: Sense SenseTrust (r:1 w:1) fn mod_trust() -> Weight { - (17_000_000 as Weight) + (22_808_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } -} \ No newline at end of file +} diff --git a/signal/Cargo.toml b/signal/Cargo.toml index 7882c82ca..af47a6d84 100644 --- a/signal/Cargo.toml +++ b/signal/Cargo.toml @@ -21,25 +21,25 @@ categories = [ ] [dependencies] -serde = { version = "1.0.136", optional = true } -codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false, optional = true } +serde = { version = "1.0.124", optional = true } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false, optional = true } orml-traits = { path = "../../orml/traits", default-features = false } gamedao-traits = { package = "gamedao-traits", path = "../traits", default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.13", default-features=false } +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.25", default-features=false } [dev-dependencies] -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } -frame-support-test = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.13" } -pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } -pallet-timestamp = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" } +frame-support-test = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.25" } +pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } +pallet-timestamp = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25" } orml-tokens = { path = "../../orml/tokens", default-features = false } orml-currencies = { path = "../../orml/currencies", default-features = false } diff --git a/signal/src/benchmarking.rs b/signal/src/benchmarking.rs index fb3febf9d..52d488fb5 100644 --- a/signal/src/benchmarking.rs +++ b/signal/src/benchmarking.rs @@ -2,9 +2,9 @@ use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller}; use frame_system::RawOrigin; -use frame_support::{dispatch::DispatchError, traits::Get}; +use frame_support::{dispatch::DispatchError, traits::Get, BoundedVec}; use sp_runtime::traits::{SaturatedConversion}; -// use sp_std::vec; +use sp_std::vec::Vec; use crate::*; @@ -31,13 +31,13 @@ fn fund_accounts(account_ids: &Vec) -> Result<(), Dispa fn create_and_finalize_campaign(caller: T::AccountId, contributors_count: u32) -> Result { let org_id = T::Control::create_org(caller.clone())?; - let treasury_account_id = T::Control::org_treasury_account(&org_id); + let treasury_account_id = T::Control::org_treasury_account(&org_id).unwrap(); fund_account::(&treasury_account_id)?; let campaign_id = T::Flow::create_campaign(&caller, &org_id)?; let contributors: Vec = (0..contributors_count).collect::>().iter() .map(|i| account("contributor", *i, SEED)).collect(); fund_accounts::(&contributors)?; - T::Flow::create_contributions(&campaign_id, &contributors)?; + T::Flow::create_contributions(&campaign_id, contributors)?; let current_block = frame_system::Pallet::::block_number(); let mut expiry = current_block + 200_u32.into(); for _ in 0 .. 10 { @@ -63,8 +63,8 @@ benchmarks! { }: _( RawOrigin::Signed(caller.clone()), org_id.clone(), - (0..255).collect(), - (0..255).collect(), + BoundedVec::truncate_from((0..255).collect()), + BoundedVec::truncate_from((0..255).collect()), start, expiry ) @@ -90,8 +90,8 @@ benchmarks! { }: _( RawOrigin::Signed(caller), campaign_id.clone(), - (0..255).collect(), - (0..255).collect(), + BoundedVec::truncate_from((0..255).collect()), + BoundedVec::truncate_from((0..255).collect()), T::Flow::campaign_balance(&campaign_id), frame_system::Pallet::::block_number() + 1_u32.into(), frame_system::Pallet::::block_number() + 200_u32.into() @@ -112,8 +112,8 @@ benchmarks! { Pallet::::general_proposal( RawOrigin::Signed(caller.clone()).into(), org_id.clone(), - (0..255).collect(), - (0..255).collect(), + BoundedVec::truncate_from((0..255).collect()), + BoundedVec::truncate_from((0..255).collect()), start, expiry )?; @@ -153,8 +153,8 @@ benchmarks! { Pallet::::withdraw_proposal( RawOrigin::Signed(caller.clone()).into(), campaign_id, - (0..255).collect(), - (0..255).collect(), + BoundedVec::truncate_from((0..255).collect()), + BoundedVec::truncate_from((0..255).collect()), withdraw_amount, start, expiry @@ -194,8 +194,8 @@ benchmarks! { Pallet::::withdraw_proposal( RawOrigin::Signed(caller.clone()).into(), campaign_id, - (0..255).collect(), - (0..255).collect(), + BoundedVec::truncate_from((0..255).collect()), + BoundedVec::truncate_from((0..255).collect()), withdraw_amount, start, expiry @@ -213,7 +213,7 @@ benchmarks! { Pallet::::unlock_balance( &proposal, 0 - ); + ).map_err(|e| "Unlock balance error")?; } verify { assert!(ProposalStates::::get(&proposal_id) == ProposalState::Finalized); diff --git a/signal/src/lib.rs b/signal/src/lib.rs index f0c454e47..665692644 100644 --- a/signal/src/lib.rs +++ b/signal/src/lib.rs @@ -12,7 +12,7 @@ //! SIGNAL is GameDAOs governance module providing simple interfaces to create proposals and vote on them #![cfg_attr(not(feature = "std"), no_std)] - +#![allow(deprecated)] // TODO: clean transactional pub mod types; pub mod migration; @@ -24,11 +24,15 @@ mod tests; mod benchmarking; pub mod weights; -use frame_support::{traits::StorageVersion, transactional, dispatch::DispatchResult, weights::Weight}; +use frame_support::{ + traits::StorageVersion, + dispatch::DispatchResult, + weights::Weight, + transactional +}; use frame_system::{ensure_signed}; use orml_traits::{MultiCurrency, MultiReservableCurrency}; use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedSub, Zero, Hash}; -use sp_std::vec::Vec; use gamedao_traits::{ControlTrait, ControlBenchmarkingTrait, FlowTrait, FlowBenchmarkingTrait}; @@ -100,11 +104,19 @@ pub mod pallet { /// The max number of proposals per one block. #[pallet::constant] - type MaxProposalsPerBlock: Get; // 3 + type MaxProposalsPerBlock: Get; + + /// The max number of proposals per single org. + #[pallet::constant] + type MaxProposalsPerOrg: Get; + + /// The max number of proposals account can vote on. + #[pallet::constant] + type MaxProposalsPerAccount: Get; /// The maximum time limit for a proposal in blocks. #[pallet::constant] - type MaxProposalDuration: Get; // 864000, 60 * 60 * 24 * 30 / 3 + type MaxProposalDuration: Get; /// The CurrencyId which is used as a payment token. #[pallet::constant] @@ -113,6 +125,10 @@ pub mod pallet { /// The CurrencyId which is used as a protokol token. #[pallet::constant] type ProtocolTokenId: Get; + + /// The maximum length of a string, stored on chain. + #[pallet::constant] + type StringLimit: Get; } /// Proposal by its id. @@ -127,7 +143,7 @@ pub mod pallet { /// Metadata: map Hash => ProposalMetadata #[pallet::storage] pub(super) type Metadata = - StorageMap<_, Blake2_128Concat, T::Hash, ProposalMetadata, ValueQuery>; + StorageMap<_, Blake2_128Concat, T::Hash, ProposalMetadata>, ValueQuery>; /// Proposal's owner. /// @@ -196,7 +212,7 @@ pub mod pallet { /// /// ProposalsByOrg: map Hash => Vec #[pallet::storage] - pub(super) type ProposalsByOrg = StorageMap<_, Blake2_128Concat, T::Hash, Vec, ValueQuery>; + pub(super) type ProposalsByOrg = StorageMap<_, Blake2_128Concat, T::Hash, BoundedVec, ValueQuery>; /// (owner account id, total number of proposals by owner) -> proposal id. /// @@ -224,7 +240,7 @@ pub mod pallet { /// ProposalsByVoter: map AccountId => Vec<(Hash, bool)> #[pallet::storage] pub(super) type ProposalsByVoter = - StorageMap<_, Blake2_128Concat, T::AccountId, Vec<(T::Hash, bool)>, ValueQuery>; + StorageMap<_, Blake2_128Concat, T::AccountId, BoundedVec<(T::Hash, bool), T::MaxProposalsPerAccount>, ValueQuery>; /// Proposal voters and votes by proposal. /// voter proposal id -> list of (voter account id, vote) @@ -232,7 +248,7 @@ pub mod pallet { /// ProposalVotesByVoters: map Hash => Vec<(AccountId, bool)> #[pallet::storage] pub(super) type ProposalVotesByVoters = - StorageMap<_, Blake2_128Concat, T::Hash, Vec<(T::AccountId, bool)>, ValueQuery>; + StorageMap<_, Blake2_128Concat, T::Hash, BoundedVec<(T::AccountId, bool), T::MaxProposalsPerAccount>, ValueQuery>; /// Total proposals voted on by voter. /// @@ -245,7 +261,7 @@ pub mod pallet { /// ProposalsByBlock: map BlockNumber => Vec #[pallet::storage] pub(super) type ProposalsByBlock = - StorageMap<_, Blake2_128Concat, T::BlockNumber, Vec, ValueQuery>; + StorageMap<_, Blake2_128Concat, T::BlockNumber, BoundedVec, ValueQuery>; /// The amount of currency that a project has used. /// @@ -270,7 +286,7 @@ pub mod pallet { /// /// ProposalVoters: map Hash => Vec #[pallet::storage] - pub(super) type ProposalVoters = StorageMap<_, Blake2_128Concat, T::Hash, Vec, ValueQuery>; + pub(super) type ProposalVoters = StorageMap<_, Blake2_128Concat, T::Hash, BoundedVec, ValueQuery>; /// Voter count per proposal. /// @@ -411,8 +427,8 @@ pub mod pallet { pub fn general_proposal( origin: OriginFor, org_id: T::Hash, - title: Vec, - cid: Vec, + title: BoundedVec, + cid: BoundedVec, start: T::BlockNumber, expiry: T::BlockNumber, ) -> DispatchResult { @@ -507,8 +523,8 @@ pub mod pallet { pub fn withdraw_proposal( origin: OriginFor, campaign_id: T::Hash, - title: Vec, - cid: Vec, + title: BoundedVec, + cid: BoundedVec, amount: T::Balance, start: T::BlockNumber, expiry: T::BlockNumber, @@ -763,7 +779,7 @@ pub mod pallet { // get treasury account for related org and unlock balance let org_id = T::Flow::campaign_org(&campaign_id); - let treasury_account = T::Control::org_treasury_account(&org_id); + let treasury_account = T::Control::org_treasury_account(&org_id).unwrap(); T::Currency::unreserve(T::PaymentTokenId::get(), &treasury_account, proposal_balance); // Change the used amount @@ -788,14 +804,14 @@ pub mod pallet { proposal_id: T::Hash, org_id: T::Hash, campaign_id: Option, - title: Vec, - cid: Vec, + title: BoundedVec, + cid: BoundedVec, amount: T::Balance, proposal_type: ProposalType, voting_type: VotingType, start: T::BlockNumber, expiry: T::BlockNumber, - ) -> Result> { + ) -> Result { let proposal = Proposal { proposal_id: proposal_id.clone(), org_id: org_id.clone(), @@ -828,7 +844,13 @@ pub mod pallet { Owners::::insert(proposal_id.clone(), sender.clone()); ProposalStates::::insert(proposal_id.clone(), ProposalState::Active); // update max per block - ProposalsByBlock::::mutate(expiry, |proposals| proposals.push(proposal_id.clone())); + ProposalsByBlock::::try_mutate( + expiry, + |proposals| -> Result<(), DispatchError> { + proposals.try_push(proposal_id.clone()).map_err(|_| Error::::TooManyProposals)?; + Ok(()) + } + )?; // update proposal map ProposalsArray::::insert(&proposals_count, proposal_id.clone()); ProposalsCount::::put(updated_proposals_count); @@ -843,7 +865,13 @@ pub mod pallet { (org_id.clone(), proposal_id.clone()), proposals_by_org_count, ); - ProposalsByOrg::::mutate(org_id.clone(), |proposals| proposals.push(proposal_id.clone())); + ProposalsByOrg::::try_mutate( + org_id.clone(), + |proposals| -> Result <(), DispatchError> { + proposals.try_push(proposal_id.clone()).map_err(|_| Error::::TooManyProposals)?; + Ok(()) + } + )?; // update owner map ProposalsByOwnerArray::::insert((sender.clone(), proposals_by_owner_count.clone()), proposal_id.clone()); ProposalsByOwnerCount::::insert(sender.clone(), updated_proposals_by_owner_count); @@ -856,7 +884,7 @@ pub mod pallet { sender: &T::AccountId, proposal: &Proposal, vote: bool, - ) -> Result> { + ) -> Result { let proposal_id = &proposal.proposal_id; let mut weight: Weight = 0; @@ -946,15 +974,27 @@ pub mod pallet { VotedBefore::::insert((&sender, proposal_id.clone()), true); ProposalsByVoterCount::::mutate(&sender, |v| *v += 1); - ProposalVotesByVoters::::mutate(&proposal_id, |votings| votings.push((sender.clone(), vote.clone()))); - ProposalsByVoter::::mutate(&sender, |votings| votings.push((proposal_id.clone(), vote))); + ProposalVotesByVoters::::try_mutate( + &proposal_id, + |ref mut votings| -> Result<(), DispatchError> { + votings.try_push((sender.clone(), vote.clone())).map_err(|_| Error::::TooManyVotes)?; + Ok(()) + } + )?; + ProposalsByVoter::::try_mutate( + &sender, + |ref mut votings| -> Result<(), DispatchError> { + votings.try_push((proposal_id.clone(), vote)).map_err(|_| Error::::TooManyVotes)?; + Ok(()) + } + )?; ProposalVotes::::insert(&proposal_id, ProposalVotes::::get(&proposal_id).saturating_add(1_u64)); let mut voters = ProposalVoters::::get(&proposal_id); match voters.binary_search(&sender) { Ok(_) => {} // should never happen Err(index) => { - voters.insert(index, sender.clone()); + voters.try_insert(index, sender.clone()).map_err(|_| Error::::TooManyVotes)?; ProposalVoters::::insert(&proposal_id, voters); } } diff --git a/signal/src/migration.rs b/signal/src/migration.rs index 1c06cd2bd..5a5fac4c0 100644 --- a/signal/src/migration.rs +++ b/signal/src/migration.rs @@ -34,8 +34,8 @@ mod v1 { pub fn migrate() -> Weight { - frame_support::storage::unhashed::kill_prefix( - &twox_128(>::name().as_bytes()), None + let _ = frame_support::storage::unhashed::clear_prefix( + &twox_128(>::name().as_bytes()), None, None ); T::DbWeight::get().writes(1) diff --git a/signal/src/mock.rs b/signal/src/mock.rs index 4eaa8e720..1972f1f35 100644 --- a/signal/src/mock.rs +++ b/signal/src/mock.rs @@ -1,7 +1,11 @@ #[cfg(test)] use crate as gamedao_signal; -use frame_support::{parameter_types, PalletId}; -use frame_support::traits::{GenesisBuild, Nothing}; +use frame_support::{ + parameter_types, + pallet_prelude::*, + traits::{GenesisBuild, Nothing}, + PalletId +}; use frame_system; use orml_traits::parameter_type_with_key; use sp_core::H256; @@ -10,6 +14,7 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, Permill, }; +use sp_std::convert::{TryFrom, TryInto}; pub type AccountId = u64; pub type Amount = i128; @@ -39,6 +44,18 @@ pub const PAYMENT_TOKEN_ID: CurrencyId = 2; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; +#[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, RuntimeDebug, PartialOrd, Ord, MaxEncodedLen, TypeInfo)] +#[repr(u8)] +pub enum ReserveIdentifier { + CollatorSelection, + Nft, + TransactionPayment, + TransactionPaymentDeposit, + + // always the last, indicate number of variants + Count, +} + // Configure a mock runtime to test the pallet. frame_support::construct_runtime!( pub enum Test where @@ -47,7 +64,7 @@ frame_support::construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Config, Storage, Event}, - Currencies: orml_currencies::{Pallet, Call, Event}, + Currencies: orml_currencies::{Pallet, Call}, Tokens: orml_tokens::{Pallet, Storage, Event, Config}, PalletBalances: pallet_balances::{Pallet, Call, Storage, Event}, PalletTimestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, @@ -57,12 +74,14 @@ frame_support::construct_runtime!( } ); +frame_support::parameter_types! { + pub const MaxReserves: u32 = ReserveIdentifier::Count as u32; +} parameter_type_with_key! { pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance { Default::default() }; } - impl orml_tokens::Config for Test { type Event = Event; type Balance = Balance; @@ -71,8 +90,12 @@ impl orml_tokens::Config for Test { type WeightInfo = (); type ExistentialDeposits = ExistentialDeposits; type OnDust = (); + type OnNewTokenAccount = (); + type OnKilledTokenAccount = (); type MaxLocks = (); type DustRemovalWhitelist = Nothing; + type ReserveIdentifier = ReserveIdentifier; + type MaxReserves = MaxReserves; } impl pallet_balances::Config for Test { @@ -83,13 +106,12 @@ impl pallet_balances::Config for Test { type AccountStore = frame_system::Pallet; type MaxLocks = (); type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; + type ReserveIdentifier = ReserveIdentifier; type WeightInfo = (); } pub type AdaptedBasicCurrency = orml_currencies::BasicCurrencyAdapter; impl orml_currencies::Config for Test { - type Event = Event; type MultiCurrency = Tokens; type NativeCurrency = AdaptedBasicCurrency; type GetNativeCurrencyId = (); @@ -127,6 +149,7 @@ impl frame_system::Config for Test { type SystemWeightInfo = (); type SS58Prefix = SS58Prefix; type OnSetCode = (); + type MaxConsumers = ConstU32<128>; } parameter_types! { @@ -140,9 +163,11 @@ impl pallet_timestamp::Config for Test { } parameter_types! { - pub const MaxDAOsPerAccount: u32 = 2; - pub const MaxMembersPerDAO: u32 = 2; + pub const MaxOrgsPerAccount: u32 = 2; + pub const MaxMembersPerOrg: u32 = 2; pub const MaxCreationsPerBlock: u32 = 2; + pub const MaxCreationsPerAccount: u32 = 100; + pub const MaxOrgsPerController: u32 = 100; pub const ProtocolTokenId: u32 = PROTOCOL_TOKEN_ID; pub const PaymentTokenId: u32 = PAYMENT_TOKEN_ID; pub const MinimumDeposit: Balance = 1 * DOLLARS; @@ -157,23 +182,28 @@ impl gamedao_control::Config for Test { type WeightInfo = (); type Event = Event; type Currency = Currencies; - type MaxDAOsPerAccount = MaxDAOsPerAccount; - type MaxMembersPerDAO = MaxMembersPerDAO; + type MaxOrgsPerAccount = MaxOrgsPerAccount; + type MaxMembersPerOrg = MaxMembersPerOrg; type MaxCreationsPerBlock = MaxCreationsPerBlock; + type MaxCreationsPerAccount = MaxCreationsPerAccount; + type MaxOrgsPerController = MaxOrgsPerController; type ProtocolTokenId = ProtocolTokenId; type PaymentTokenId = PaymentTokenId; type MinimumDeposit = MinimumDeposit; type PalletId = ControlPalletId; type Game3FoundationTreasury = Game3FoundationTreasuryAccountId; type GameDAOTreasury = GameDAOTreasuryAccountId; + type StringLimit = StringLimit; } parameter_types! { pub const MinNameLength: u32 = 2; - pub const MaxNameLength: u32 = 4; + pub const StringLimit: u32 = 4; pub const MaxCampaignsPerAddress: u32 = 3; pub const MaxCampaignsPerBlock: u32 = 1; pub const MaxCampaignsPerOrg: u32 = 64; + pub const MaxCampaignContributions: u32 = 100; + pub const MaxCampaignsPerStatus: u32 = 1000; pub const MaxContributionsPerBlock: u32 = 3; pub const MaxContributorsProcessing: u32 = 5; pub const MinCampaignDuration: BlockNumber = 1 * DAYS; @@ -183,7 +213,6 @@ parameter_types! { } impl gamedao_flow::Config for Test { type Balance = Balance; - // type Moment = Moment; type CurrencyId = CurrencyId; type WeightInfo = (); type Event = Event; @@ -194,11 +223,13 @@ impl gamedao_flow::Config for Test { type Control = Control; type GameDAOTreasury = GameDAOTreasury; type MinNameLength = MinNameLength; - type MaxNameLength = MaxNameLength; + type StringLimit = StringLimit; type MaxContributorsProcessing = MaxContributorsProcessing; type MaxCampaignsPerAddress = MaxCampaignsPerAddress; type MaxCampaignsPerBlock = MaxCampaignsPerBlock; type MaxCampaignsPerOrg = MaxCampaignsPerOrg; + type MaxCampaignContributions = MaxCampaignContributions; + type MaxCampaignsPerStatus = MaxCampaignsPerStatus; type MaxContributionsPerBlock = MaxContributionsPerBlock; type MinCampaignDuration = MinCampaignDuration; type MaxCampaignDuration = MaxCampaignDuration; @@ -208,6 +239,8 @@ impl gamedao_flow::Config for Test { parameter_types! { pub const MaxProposalsPerBlock: u32 = 2; + pub const MaxProposalsPerOrg: u32 = 1000; + pub const MaxProposalsPerAccount: u32 = 1000; pub const MaxProposalDuration: u32 = 20; pub const MaxVotesPerProposal: u32 = 1000; } @@ -218,12 +251,15 @@ impl gamedao_signal::Config for Test { type Flow = Flow; type MaxVotesPerProposal = MaxVotesPerProposal; type MaxProposalsPerBlock = MaxProposalsPerBlock; + type MaxProposalsPerOrg = MaxProposalsPerOrg; + type MaxProposalsPerAccount = MaxProposalsPerAccount; type MaxProposalDuration = MaxProposalDuration; type ProtocolTokenId = ProtocolTokenId; type PaymentTokenId = PaymentTokenId; type Currency = Currencies; type Balance = Balance; type CurrencyId = CurrencyId; + type StringLimit = StringLimit; } #[derive(Default)] diff --git a/signal/src/tests.rs b/signal/src/tests.rs index add31dfea..a46e4231f 100644 --- a/signal/src/tests.rs +++ b/signal/src/tests.rs @@ -7,10 +7,11 @@ use super::{ *, }; use frame_system::RawOrigin; -use frame_support::pallet_prelude::Encode; +// use frame_support::pallet_prelude::Encode; use frame_support::{ assert_noop, assert_ok, traits::Hooks, + BoundedVec }; use orml_tokens::Event as TokensEvent; use orml_traits::MultiReservableCurrency; @@ -23,11 +24,12 @@ use gamedao_flow::{FlowGovernance, FlowProtocol, FlowState}; fn create_org_treasury() -> (H256, AccountId) { let nonce = Control::nonce(); + let bounded_str = BoundedVec::truncate_from(vec![1, 2, 3]); assert_ok!(Control::create_org( Origin::signed(ACC1), ACC1, - vec![1, 2, 3], - vec![1, 2, 3], + bounded_str.clone(), + bounded_str.clone(), OrgType::Individual, AccessModel::Open, FeeModel::NoFees, @@ -37,9 +39,9 @@ fn create_org_treasury() -> (H256, AccountId) { 100, Some(1 * DOLLARS) )); - let treasury_id = ::PalletId::get().into_sub_account(nonce as i32); + let treasury_id = ::PalletId::get().into_sub_account_truncating(nonce as i32); let org_id = ::Hashing::hash_of(&treasury_id); - assert_eq!(treasury_id, Control::org_treasury_account(&org_id)); + assert_eq!(treasury_id, Control::org_treasury_account(&org_id).unwrap()); let _ = Tokens::set_balance(RawOrigin::Root.into(), treasury_id, PROTOCOL_TOKEN_ID, 25 * DOLLARS, 0); (org_id, treasury_id) @@ -52,19 +54,20 @@ fn create_campaign( expiry: Option, ) -> H256 { let nonce = Flow::nonce(); + let bounded_str = BoundedVec::truncate_from(vec![1, 2, 3]); assert_ok!(Flow::create_campaign( Origin::signed(ACC1), org, ACC1, - vec![1, 2, 3], + bounded_str.clone(), 10 * DOLLARS, 10 * DOLLARS, expiry.unwrap_or(100), FlowProtocol::default(), FlowGovernance::default(), - vec![1, 2, 3], - vec![1, 2, 3], - vec![1, 2, 3], + bounded_str.clone(), + bounded_str.clone(), + bounded_str.clone(), )); let campaign_id = ::Hashing::hash_of(&nonce); for (account_id, contribution) in contributions.iter() { @@ -89,15 +92,16 @@ fn signal_general_proposal_success() { ExtBuilder::default().build().execute_with(|| { let proposal_id: H256 = ::Hashing::hash_of(&Signal::nonce()); let (org_id, _) = create_org_treasury(); + let bounded_str = BoundedVec::truncate_from(vec![1, 2, 3]); System::set_block_number(3); assert_ok!(Signal::general_proposal( Origin::signed(ACC1), org_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid - 3, // start - 15 // expiry + bounded_str.clone(), // title + bounded_str.clone(), // cid + 3, // start + 15 // expiry )); assert_eq!( @@ -122,8 +126,8 @@ fn signal_general_proposal_success() { assert_eq!( >::get(&proposal_id), ProposalMetadata { - title: vec![1, 2, 3], - cid: vec![1, 2, 3], + title: bounded_str.clone(), + cid: bounded_str.clone(), amount: 0 } ); @@ -146,8 +150,8 @@ fn signal_general_proposal_success() { assert_ok!(Signal::general_proposal( Origin::signed(ACC1), org_id, // org_id - vec![2, 3, 4], // title - vec![2, 3, 4], // cid + BoundedVec::truncate_from(vec![2, 3, 4]), // title + BoundedVec::truncate_from(vec![2, 3, 4]), // cid 3, // start 15 // expiry )); @@ -181,6 +185,7 @@ fn signal_general_proposal_error() { System::set_block_number(3); let (org_id, _) = create_org_treasury(); let proposal_id: H256 = ::Hashing::hash_of(&Signal::nonce()); + let bounded_str = BoundedVec::truncate_from(vec![1, 2, 3]); >::insert( proposal_id, @@ -198,22 +203,22 @@ fn signal_general_proposal_error() { Signal::general_proposal( Origin::signed(ACC1), org_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid - 3, // start - 15 // expiry + bounded_str.clone(), // title + bounded_str.clone(), // cid + 3, // start + 15 // expiry ), Error::::ProposalExists ); - let proposal_ids = vec![H256::random(), H256::random()]; + let proposal_ids = BoundedVec::truncate_from(vec![H256::random(), H256::random()]); >::insert(15, proposal_ids); assert_noop!( Signal::general_proposal( Origin::signed(ACC1), org_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 3, // start 15 // expiry ), @@ -224,8 +229,8 @@ fn signal_general_proposal_error() { Signal::general_proposal( Origin::signed(ACC1), org_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 3, // start System::block_number() + >::get() + 1 ), @@ -235,8 +240,8 @@ fn signal_general_proposal_error() { Signal::general_proposal( Origin::signed(ACC1), org_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid System::block_number(), // start System::block_number() // expiry ), @@ -248,8 +253,8 @@ fn signal_general_proposal_error() { Signal::general_proposal( Origin::signed(ACC1), org_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 3, // start 15 // expiry ), @@ -258,7 +263,10 @@ fn signal_general_proposal_error() { assert_ok!(Control::disable_org(Origin::root(), org_id)); assert_noop!( - Signal::general_proposal(Origin::signed(ACC1), org_id, vec![1, 2, 3], vec![1, 2, 3], 3, 15), + Signal::general_proposal( + Origin::signed(ACC1), org_id, + bounded_str.clone(), bounded_str.clone(), 3, 15 + ), Error::::DAOInactive ); @@ -266,8 +274,8 @@ fn signal_general_proposal_error() { Signal::general_proposal( Origin::none(), org_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 3, // start 15 // expiry ), @@ -281,6 +289,7 @@ fn signal_withdraw_proposal_success() { ExtBuilder::default().build().execute_with(|| { let (org_id, _) = create_org_treasury(); let campaign_id = create_campaign(org_id, vec![(ACC2, 15 * DOLLARS)], Some(FlowState::Success), None); + let bounded_str = BoundedVec::truncate_from(vec![1, 2, 3]); System::set_block_number(3); let proposal_id: H256 = ::Hashing::hash_of(&Signal::nonce()); @@ -289,8 +298,8 @@ fn signal_withdraw_proposal_success() { assert_ok!(Signal::withdraw_proposal( Origin::signed(ACC1), campaign_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 10 * DOLLARS, // amount 4, // start 15 // expiry @@ -322,8 +331,8 @@ fn signal_withdraw_proposal_success() { assert_eq!( >::get(&proposal_id), ProposalMetadata { - title: vec![1, 2, 3], - cid: vec![1, 2, 3], + title: bounded_str.clone(), + cid: bounded_str.clone(), amount: 10 * DOLLARS } ); @@ -349,8 +358,8 @@ fn signal_withdraw_proposal_success() { assert_ok!(Signal::general_proposal( Origin::signed(ACC1), org_id, - vec![2, 3, 4], // title - vec![2, 3, 4], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 4, // start 15 // expiry )); @@ -383,6 +392,7 @@ fn signal_withdraw_proposal_error() { ExtBuilder::default().build().execute_with(|| { let (org_id, _) = create_org_treasury(); let campaign_id = create_campaign(org_id, vec![(ACC2, 15 * DOLLARS)], Some(FlowState::Success), None); + let bounded_str = BoundedVec::truncate_from(vec![1, 2, 3]); System::set_block_number(3); let proposal_id: H256 = ::Hashing::hash_of(&Signal::nonce()); @@ -404,8 +414,8 @@ fn signal_withdraw_proposal_error() { Signal::withdraw_proposal( Origin::signed(ACC1), campaign_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 10 * DOLLARS, // amount 4, // start 15 // expiry @@ -413,14 +423,14 @@ fn signal_withdraw_proposal_error() { Error::::ProposalExists ); - let proposal_ids = vec![H256::random(), H256::random()]; + let proposal_ids = BoundedVec::truncate_from(vec![H256::random(), H256::random()]); >::insert(15, proposal_ids); assert_noop!( Signal::withdraw_proposal( Origin::signed(ACC1), campaign_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 10 * DOLLARS, // amount 4, // start 15 // expiry @@ -433,8 +443,8 @@ fn signal_withdraw_proposal_error() { Signal::withdraw_proposal( Origin::signed(ACC1), campaign_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 10 * DOLLARS, // amount 4, // start 15 // expiry @@ -447,8 +457,8 @@ fn signal_withdraw_proposal_error() { Signal::withdraw_proposal( Origin::signed(ACC1), campaign_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 10 * DOLLARS, // amount 4, // start 15 // expiry @@ -460,8 +470,8 @@ fn signal_withdraw_proposal_error() { Signal::withdraw_proposal( Origin::signed(ACC1), campaign_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 10 * DOLLARS, // amount 3, // start 15 // expiry @@ -472,8 +482,8 @@ fn signal_withdraw_proposal_error() { Signal::withdraw_proposal( Origin::signed(ACC1), campaign_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 10 * DOLLARS, // amount 4, // start 4 // expiry @@ -484,8 +494,8 @@ fn signal_withdraw_proposal_error() { Signal::withdraw_proposal( Origin::signed(ACC1), campaign_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 10 * DOLLARS, // amount 4, // start 4 + ProposalTimeLimit::::get() + 1 @@ -497,8 +507,8 @@ fn signal_withdraw_proposal_error() { Signal::withdraw_proposal( Origin::signed(ACC2), campaign_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 10 * DOLLARS, // amount 4, // start 15 @@ -512,8 +522,8 @@ fn signal_withdraw_proposal_error() { Signal::withdraw_proposal( Origin::signed(ACC1), campaign_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 10 * DOLLARS, // amount 4, // start 16 // expiry @@ -525,8 +535,8 @@ fn signal_withdraw_proposal_error() { Signal::withdraw_proposal( Origin::none(), campaign_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 10 * DOLLARS, // amount 4, // start 16 // expiry @@ -738,20 +748,21 @@ fn signal_on_finalize_success() { let proposal_id1: H256 = ::Hashing::hash_of(&0); let proposal_id2: H256 = ::Hashing::hash_of(&1); let proposal_id3: H256 = ::Hashing::hash_of(&2); + let bounded_str = BoundedVec::truncate_from(vec![1, 2, 3]); assert_ok!(Signal::general_proposal( Origin::signed(ACC1), org_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid - start, // start - expiry // expiry + bounded_str.clone(), // title + bounded_str.clone(), // cid + start, // start + expiry // expiry )); assert_ok!(Signal::withdraw_proposal( Origin::signed(ACC1), campaign_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 10, // amount start, // start expiry // expiry @@ -763,7 +774,7 @@ fn signal_on_finalize_success() { assert_ok!(Signal::simple_vote(Origin::signed(i), proposal_id2, i == 5)); } - let mut events_before = System::events().len(); + let events_before = System::events().len(); Signal::on_finalize(start); assert_eq!(System::events().len(), events_before); @@ -793,8 +804,8 @@ fn signal_on_finalize_success() { assert_ok!(Signal::withdraw_proposal( Origin::signed(ACC1), campaign_id, - vec![1, 2, 3], // title - vec![1, 2, 3], // cid + bounded_str.clone(), // title + bounded_str.clone(), // cid 10, // amount 16, // start 17 // expiry @@ -830,19 +841,19 @@ fn signal_on_finalize_success() { ); assert_eq!( events.pop().unwrap().event, - Event::Tokens(TokensEvent::Endowed( - ::PaymentTokenId::get(), - treasury_id, - 0 - )) + Event::Tokens(TokensEvent::Endowed { + currency_id: ::PaymentTokenId::get(), + who: treasury_id, + amount: 0 + }) ); assert_eq!( events.pop().unwrap().event, - Event::Tokens(TokensEvent::Unreserved( - ::PaymentTokenId::get(), - treasury_id, - 10 - )) + Event::Tokens(TokensEvent::Unreserved { + currency_id: ::PaymentTokenId::get(), + who: treasury_id, + amount: 10 + }) ); assert_eq!(>::get(campaign_id), 10); assert_eq!(>::get(proposal_id3), ProposalState::Finalized); diff --git a/signal/src/types.rs b/signal/src/types.rs index 049cbc413..126a49466 100644 --- a/signal/src/types.rs +++ b/signal/src/types.rs @@ -1,10 +1,7 @@ -use frame_support::pallet_prelude::{Decode, Encode}; +use frame_support::pallet_prelude::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; -use sp_std::vec::Vec; -// #[derive(Encode, Decode, Clone, PartialEq, Default, Eq, PartialOrd, Ord, -// TypeInfo)] -#[derive(Encode, Decode, PartialEq, Clone, TypeInfo)] +#[derive(Encode, Decode, PartialEq, Clone, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Debug))] pub enum ProposalState { Init = 0, // waiting for start block @@ -21,7 +18,7 @@ impl Default for ProposalState { } } -#[derive(Encode, Decode, PartialEq, Clone, TypeInfo)] +#[derive(Encode, Decode, PartialEq, Clone, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Debug))] pub enum ProposalType { General = 0, @@ -36,7 +33,7 @@ impl Default for ProposalType { } } -#[derive(Encode, Decode, PartialEq, Clone, TypeInfo)] +#[derive(Encode, Decode, PartialEq, Clone, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Debug))] pub enum VotingType { Simple = 0, // votes across participating votes @@ -52,7 +49,7 @@ impl Default for VotingType { } } -#[derive(Encode, Decode, Default, Clone, PartialEq, TypeInfo)] +#[derive(Encode, Decode, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Debug))] pub struct Proposal { pub proposal_id: Hash, @@ -64,10 +61,10 @@ pub struct Proposal { pub expiry: BlockNumber, } -#[derive(Encode, Decode, Default, Clone, PartialEq, TypeInfo)] +#[derive(Encode, Decode, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(Debug))] -pub struct ProposalMetadata { - pub title: Vec, - pub cid: Vec, +pub struct ProposalMetadata { + pub title: BoundedString, + pub cid: BoundedString, pub amount: Balance, } diff --git a/signal/src/weights.rs b/signal/src/weights.rs index fd064fd76..1f903e1e0 100644 --- a/signal/src/weights.rs +++ b/signal/src/weights.rs @@ -18,12 +18,13 @@ //! Autogenerated weights for gamedao_signal //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-06-22, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 128 +//! DATE: 2022-07-11, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 // Executed Command: // ./target/release/subzero // benchmark +// pallet // --pallet=gamedao_signal // --extrinsic=* // --steps=20 @@ -71,12 +72,12 @@ impl WeightInfo for SubstrateWeight { // Storage: Signal ProposalStates (r:0 w:1) // Storage: Signal ProposalsByOrgIndex (r:0 w:1) fn general_proposal() -> Weight { - (61_370_000 as Weight) + (76_689_000 as Weight) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(16 as Weight)) } fn membership_proposal() -> Weight { - (1_123_000 as Weight) + (6_878_000 as Weight) } // Storage: Flow CampaignState (r:1 w:0) // Storage: Flow CampaignOwner (r:1 w:0) @@ -101,7 +102,7 @@ impl WeightInfo for SubstrateWeight { // Storage: Signal ProposalStates (r:0 w:1) // Storage: Signal ProposalsByOrgIndex (r:0 w:1) fn withdraw_proposal() -> Weight { - (79_144_000 as Weight) + (81_474_000 as Weight) .saturating_add(T::DbWeight::get().reads(13 as Weight)) .saturating_add(T::DbWeight::get().writes(16 as Weight)) } @@ -116,9 +117,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Signal ProposalsByVoter (r:1 w:1) // Storage: Signal ProposalVoters (r:1 w:1) fn simple_vote_general(b: u32, ) -> Weight { - (73_951_000 as Weight) - // Standard Error: 5_000 - .saturating_add((393_000 as Weight).saturating_mul(b as Weight)) + (0 as Weight) + // Standard Error: 1_000 + .saturating_add((196_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -134,9 +135,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Signal ProposalsByVoter (r:1 w:1) // Storage: Signal ProposalVoters (r:1 w:1) fn simple_vote_withdraw(b: u32, ) -> Weight { - (103_869_000 as Weight) - // Standard Error: 6_000 - .saturating_add((457_000 as Weight).saturating_mul(b as Weight)) + (0 as Weight) + // Standard Error: 1_000 + .saturating_add((345_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(11 as Weight)) .saturating_add(T::DbWeight::get().writes(8 as Weight)) } @@ -149,9 +150,9 @@ impl WeightInfo for SubstrateWeight { // Storage: Tokens Accounts (r:1 w:1) // Storage: Signal ProposalStates (r:0 w:1) fn unlock_balance(b: u32, ) -> Weight { - (90_153_000 as Weight) - // Standard Error: 68_000 - .saturating_add((151_000 as Weight).saturating_mul(b as Weight)) + (79_958_000 as Weight) + // Standard Error: 55_000 + .saturating_add((344_000 as Weight).saturating_mul(b as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -179,12 +180,12 @@ impl WeightInfo for () { // Storage: Signal ProposalStates (r:0 w:1) // Storage: Signal ProposalsByOrgIndex (r:0 w:1) fn general_proposal() -> Weight { - (61_370_000 as Weight) + (76_689_000 as Weight) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().writes(16 as Weight)) } fn membership_proposal() -> Weight { - (1_123_000 as Weight) + (6_878_000 as Weight) } // Storage: Flow CampaignState (r:1 w:0) // Storage: Flow CampaignOwner (r:1 w:0) @@ -209,7 +210,7 @@ impl WeightInfo for () { // Storage: Signal ProposalStates (r:0 w:1) // Storage: Signal ProposalsByOrgIndex (r:0 w:1) fn withdraw_proposal() -> Weight { - (79_144_000 as Weight) + (81_474_000 as Weight) .saturating_add(RocksDbWeight::get().reads(13 as Weight)) .saturating_add(RocksDbWeight::get().writes(16 as Weight)) } @@ -224,9 +225,9 @@ impl WeightInfo for () { // Storage: Signal ProposalsByVoter (r:1 w:1) // Storage: Signal ProposalVoters (r:1 w:1) fn simple_vote_general(b: u32, ) -> Weight { - (73_951_000 as Weight) - // Standard Error: 5_000 - .saturating_add((393_000 as Weight).saturating_mul(b as Weight)) + (0 as Weight) + // Standard Error: 1_000 + .saturating_add((196_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(10 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -242,9 +243,9 @@ impl WeightInfo for () { // Storage: Signal ProposalsByVoter (r:1 w:1) // Storage: Signal ProposalVoters (r:1 w:1) fn simple_vote_withdraw(b: u32, ) -> Weight { - (103_869_000 as Weight) - // Standard Error: 6_000 - .saturating_add((457_000 as Weight).saturating_mul(b as Weight)) + (0 as Weight) + // Standard Error: 1_000 + .saturating_add((345_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(11 as Weight)) .saturating_add(RocksDbWeight::get().writes(8 as Weight)) } @@ -257,9 +258,9 @@ impl WeightInfo for () { // Storage: Tokens Accounts (r:1 w:1) // Storage: Signal ProposalStates (r:0 w:1) fn unlock_balance(b: u32, ) -> Weight { - (90_153_000 as Weight) - // Standard Error: 68_000 - .saturating_add((151_000 as Weight).saturating_mul(b as Weight)) + (79_958_000 as Weight) + // Standard Error: 55_000 + .saturating_add((344_000 as Weight).saturating_mul(b as Weight)) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } diff --git a/traits/Cargo.toml b/traits/Cargo.toml index acde971b1..6d0462ad8 100644 --- a/traits/Cargo.toml +++ b/traits/Cargo.toml @@ -16,11 +16,11 @@ repository = "https://github.com/gamedaoco/gamedao-protocol" [dependencies] serde = { version = "1.0.124", optional = true } -codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false, optional = true } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false, optional = true } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.25", default-features = false } [features] default = ["std"] diff --git a/traits/src/lib.rs b/traits/src/lib.rs index 4f69019e3..fd3e3f216 100644 --- a/traits/src/lib.rs +++ b/traits/src/lib.rs @@ -13,14 +13,16 @@ #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(feature = "runtime-benchmarks")] use frame_support::dispatch::DispatchError; +#[cfg(feature = "runtime-benchmarks")] use sp_std::vec::Vec; pub trait ControlTrait { - fn org_controller_account(org_id: &Hash) -> AccountId; - fn org_treasury_account(org_id: &Hash) -> AccountId; + fn org_controller_account(org_id: &Hash) -> Option; + fn org_treasury_account(org_id: &Hash) -> Option; fn is_org_active(org_id: &Hash) -> bool; fn is_org_member_active(org_id: &Hash, accont_id: &AccountId) -> bool; } @@ -36,7 +38,7 @@ pub trait ControlBenchmarkingTrait { /// It is assumed those accounts have enough of currency to pay org joining fee. /// ** Should be used for benchmarking only!!! ** #[cfg(feature = "runtime-benchmarks")] - fn fill_org_with_members(org_id: &Hash, members: &Vec) -> Result<(), DispatchError>; + fn fill_org_with_members(org_id: &Hash, members: Vec) -> Result<(), DispatchError>; } pub trait FlowTrait { @@ -60,7 +62,7 @@ pub trait FlowBenchmarkingTrait { /// It is assumed those accounts have enought currency to contribute /// ** Should be used for benchmarking only!!! ** #[cfg(feature = "runtime-benchmarks")] - fn create_contributions(campaign_id: &Hash, contributors: &Vec) -> Result<(), DispatchError>; + fn create_contributions(campaign_id: &Hash, contributors: Vec) -> Result<(), DispatchError>; /// Trigger campaigns finalization by setting block number to specified value and calling appropriate hooks /// ** Should be used for benchmarking only!!! **