diff --git a/libs/common-types/Cargo.toml b/libs/common-types/Cargo.toml index a0e24bca..a7e0681a 100644 --- a/libs/common-types/Cargo.toml +++ b/libs/common-types/Cargo.toml @@ -41,6 +41,9 @@ std = [ 'sp-std/std', 'xcm/std', ] + +runtime-benchmarks = [] + try-runtime = [ "common-traits/try-runtime", "frame-support/try-runtime", diff --git a/libs/common-types/src/tokens.rs b/libs/common-types/src/tokens.rs index 060318b8..bd74a9eb 100644 --- a/libs/common-types/src/tokens.rs +++ b/libs/common-types/src/tokens.rs @@ -31,6 +31,76 @@ pub enum CurrencyId { ForeignAsset(ForeignAssetId), } +#[derive( + Clone, + Copy, + PartialOrd, + Ord, + PartialEq, + Eq, + Debug, + Encode, + Decode, + TypeInfo, + MaxEncodedLen, + Serialize, + Deserialize, +)] +pub enum ForeignAssetId { + ETH, + USDT, +} + +#[derive( + Clone, + Copy, + PartialOrd, + Ord, + PartialEq, + Eq, + Debug, + Encode, + Decode, + TypeInfo, + MaxEncodedLen, + Serialize, + Deserialize, +)] +/// The foreign owned account describes the chain +pub enum ForeignOwnedAccount { + TRON([u8; 22]), + ETH([u8; 20]), +} + +impl ForeignOwnedAccount { + /// Here we can define which currencies per network we support + /// For example when given a TRON account we can use this to see if the account + /// and the currency are compatible. + pub fn ensure_supported_currency(&self, currency: CurrencyId) -> bool { + match currency { + CurrencyId::Native => false, + CurrencyId::KSM => false, + CurrencyId::AUSD => false, + CurrencyId::KAR => false, + CurrencyId::MGX => false, + CurrencyId::ForeignAsset(asset) => match &self { + ForeignOwnedAccount::TRON(_) => match asset { + ForeignAssetId::ETH => false, + ForeignAssetId::USDT => true, + }, + ForeignOwnedAccount::ETH(_) => match asset { + ForeignAssetId::ETH => true, + ForeignAssetId::USDT => true, + }, + }, + } + } + #[cfg(feature = "runtime-benchmarks")] + pub fn get_supported_currency_eoa_combo() -> (ForeignOwnedAccount, CurrencyId) { + (ForeignOwnedAccount::ETH(Default::default()), CurrencyId::ForeignAsset(ForeignAssetId::ETH)) + } +} + pub mod currency_decimals { pub const NATIVE: u32 = 12; pub const AUSD: u32 = 12; @@ -39,16 +109,6 @@ pub mod currency_decimals { pub const MGX: u32 = 18; } -// A way to generate different currencies from a number. -// Can be used in tests/benchmarks to generate different currencies. -impl From for CurrencyId { - fn from(value: u32) -> Self { - CurrencyId::ForeignAsset(value) - } -} - -pub type ForeignAssetId = u32; - #[derive( Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, Encode, Decode, TypeInfo, MaxEncodedLen, )] diff --git a/pallets/briefs/Cargo.toml b/pallets/briefs/Cargo.toml index b5d3f858..a48b1879 100644 --- a/pallets/briefs/Cargo.toml +++ b/pallets/briefs/Cargo.toml @@ -83,6 +83,7 @@ std = [ runtime-benchmarks = [ "common-runtime/runtime-benchmarks", + "common-types/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "pallet-deposits/runtime-benchmarks", diff --git a/pallets/briefs/src/benchmarking.rs b/pallets/briefs/src/benchmarking.rs index 250f1889..f3052d39 100644 --- a/pallets/briefs/src/benchmarking.rs +++ b/pallets/briefs/src/benchmarking.rs @@ -4,7 +4,7 @@ use super::*; use crate::test_utils::gen_hash; use crate::Pallet as Briefs; use crate::{BoundedBriefOwners, BoundedProposedMilestones}; -use common_types::CurrencyId; +use common_types::{CurrencyId, ForeignOwnedAccount}; use frame_benchmarking::v2::*; use frame_support::{assert_ok, traits::Get}; use frame_system::{EventRecord, RawOrigin}; @@ -22,14 +22,15 @@ mod benchmarks { #[benchmark] fn create_brief() { - let brief_owners = get_max_brief_owners::(); + let (eoa, currency_id) = ForeignOwnedAccount::get_supported_currency_eoa_combo(); + let brief_owners = get_max_brief_owners::(currency_id); let caller: T::AccountId = brief_owners[0].clone(); - let applicant = create_account_id::("applicant", 1); + let applicant = create_account_id::("applicant", 1, currency_id); let budget = 10_000u32.into(); let initial_contribution = 5_000u32.into(); let brief_id = gen_hash(1); let milestones = get_max_milestones::(); - // (origin, brief_owners, applicant, budget, initial_contribution, brief_id, currency_id, milestones) + // (origin, brief_owners, applicant, budget, initial_contribution, brief_id, currency_id, milestones, Option) #[extrinsic_call] create_brief( @@ -39,17 +40,19 @@ mod benchmarks { budget, initial_contribution, brief_id, - CurrencyId::Native, + currency_id, milestones, + Some(eoa) ); assert_last_event::(Event::::BriefSubmitted(caller, brief_id).into()); } #[benchmark] fn contribute_to_brief() { - let brief_owners = get_max_brief_owners::(); + let currency_id = CurrencyId::Native; + let brief_owners = get_max_brief_owners::(currency_id); let caller: T::AccountId = brief_owners[0].clone(); - let applicant: T::AccountId = create_account_id::("applicant", 1); + let applicant: T::AccountId = create_account_id::("applicant", 1, currency_id); let budget = 10_000_000_000_000u128.saturated_into(); let initial_contribution = 5_000_000_000_000u128.saturated_into(); let contribution = 5_000_000_000_000u128.saturated_into(); @@ -62,8 +65,9 @@ mod benchmarks { budget, initial_contribution, brief_id, - CurrencyId::Native, - milestones + currency_id, + milestones, + None, )); let brief_owner: T::AccountId = brief_owners[0].clone(); // (brief_owner, brief_id, contribution) @@ -78,13 +82,16 @@ mod benchmarks { #[benchmark] fn commence_work() { - let brief_owners = get_max_brief_owners::(); + let currency_id = CurrencyId::Native; + let brief_owners = get_max_brief_owners::(currency_id); let caller: T::AccountId = brief_owners[0].clone(); - let applicant: T::AccountId = create_account_id::("applicant", 1); + let applicant: T::AccountId = create_account_id::("applicant", 1, currency_id); let budget = 10_000_000_000_000u128.saturated_into(); let initial_contribution = 5_000_000_000_000u128.saturated_into(); let brief_id = gen_hash(1); let milestones = get_max_milestones::(); + + assert_ok!(Briefs::::create_brief( RawOrigin::Signed(caller).into(), brief_owners, @@ -92,8 +99,9 @@ mod benchmarks { budget, initial_contribution, brief_id, - CurrencyId::Native, - milestones + currency_id, + milestones, + None, )); // (origin, brief_id) #[extrinsic_call] @@ -103,9 +111,10 @@ mod benchmarks { #[benchmark] fn cancel_brief() { - let brief_owners = get_max_brief_owners::(); + let currency_id = CurrencyId::Native; + let brief_owners = get_max_brief_owners::(currency_id); let caller: T::AccountId = brief_owners[0].clone(); - let applicant: T::AccountId = create_account_id::("applicant", 1); + let applicant: T::AccountId = create_account_id::("applicant", 1, currency_id); let budget = 10_000_000_000_000u128.saturated_into(); let initial_contribution = 5_000_000_000_000u128.saturated_into(); let brief_id = gen_hash(1); @@ -117,8 +126,9 @@ mod benchmarks { budget, initial_contribution, brief_id, - CurrencyId::Native, - milestones + currency_id, + milestones, + None, )); // (origin, brief_id) #[extrinsic_call] @@ -133,11 +143,11 @@ mod benchmarks { ); } -fn create_account_id(suri: &'static str, n: u32) -> T::AccountId { +fn create_account_id(suri: &'static str, n: u32, currency_id: CurrencyId) -> T::AccountId { let user = account(suri, n, SEED); let initial_balance = 1_000_000_000_000_000u128; assert_ok!(T::RMultiCurrency::deposit( - CurrencyId::Native, + currency_id, &user, initial_balance.saturated_into() )); @@ -152,21 +162,21 @@ fn assert_last_event(generic_event: ::RuntimeEvent) { assert_eq!(event, &system_event); } -fn get_brief_owners(mut n: u32) -> BoundedBriefOwners { +fn get_brief_owners(mut n: u32, currency: CurrencyId) -> BoundedBriefOwners { let max = ::MaxBriefOwners::get(); if n > max { n = max; } (0..n) - .map(|i| create_account_id::("brief_owner", i)) + .map(|i| create_account_id::("brief_owner", i, currency)) .collect::>() .try_into() .expect("qed") } -fn get_max_brief_owners() -> BoundedBriefOwners { +fn get_max_brief_owners(currency_id: CurrencyId) -> BoundedBriefOwners { let max_brief_owners: u32 = ::MaxBriefOwners::get(); - get_brief_owners::(max_brief_owners) + get_brief_owners::(max_brief_owners, currency_id) } fn get_milestones(mut n: u32) -> BoundedProposedMilestones { diff --git a/pallets/briefs/src/integration_tests.rs b/pallets/briefs/src/integration_tests.rs index 02073748..c43eb534 100644 --- a/pallets/briefs/src/integration_tests.rs +++ b/pallets/briefs/src/integration_tests.rs @@ -22,6 +22,7 @@ fn create_proposal_from_brief() { brief_id, CurrencyId::Native, get_milestones(10), + None, ); assert_ok!(BriefsMod::commence_work( diff --git a/pallets/briefs/src/lib.rs b/pallets/briefs/src/lib.rs index 88588a5f..6748e243 100644 --- a/pallets/briefs/src/lib.rs +++ b/pallets/briefs/src/lib.rs @@ -5,6 +5,8 @@ pub use pallet::*; pub mod weights; pub use weights::*; +pub mod migrations; + #[cfg(test)] mod mock; @@ -57,12 +59,12 @@ pub mod pallet { BalanceOf, AccountIdOf, >>::StorageItem; - type DepositIdOf = + pub(crate) type DepositIdOf = <::DepositHandler as DepositHandler, AccountIdOf>>::DepositId; pub type BriefHash = H256; - const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); + const STORAGE_VERSION: StorageVersion = StorageVersion::new(3); #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] @@ -152,6 +154,10 @@ pub mod pallet { MilestonesTotalPercentageMustEqual100, /// too many milestones here mate fixed with https://github.com/ImbueNetwork/imbue/issues/267 TooManyMilestones, + /// If youre using a foreign currency then you need an external_owned_address. + EoaRequiredForForeignCurrencies, + /// Currency is not supported for this external address. + CurrencyAccountComboNotSupported, } #[pallet::call] @@ -170,6 +176,7 @@ pub mod pallet { brief_id: BriefHash, currency_id: CurrencyId, milestones: BoundedProposedMilestones, + external_owned_address: Option, ) -> DispatchResult { let who = ensure_signed(origin)?; @@ -178,6 +185,19 @@ pub mod pallet { Error::::BriefAlreadyExists ); + if let CurrencyId::ForeignAsset(_) = currency_id { + ensure!( + external_owned_address.is_some(), + Error::::EoaRequiredForForeignCurrencies + ); + } + if let Some(eoa) = external_owned_address { + ensure!( + eoa.ensure_supported_currency(currency_id), + Error::::CurrencyAccountComboNotSupported + ); + } + let total_percentage = milestones .iter() .fold(Percent::zero(), |acc: Percent, ms: &ProposedMilestone| { @@ -230,6 +250,7 @@ pub mod pallet { applicant, milestones, deposit_id, + external_owned_address, ); Briefs::::insert(brief_id, brief); @@ -325,6 +346,7 @@ pub mod pallet { .try_into() .map_err(|_| Error::::TooManyMilestones)?, FundingPath::TakeFromReserved, + brief.eoa, )?; BriefContributions::::remove(brief_id); @@ -371,6 +393,7 @@ pub mod pallet { pub applicant: AccountIdOf, pub milestones: BoundedProposedMilestones, pub deposit_id: DepositIdOf, + pub eoa: Option, } impl Pallet { @@ -397,6 +420,7 @@ pub mod pallet { applicant: AccountIdOf, milestones: BoundedProposedMilestones, deposit_id: DepositIdOf, + eoa: Option, ) -> Self { Self { created_at, @@ -406,6 +430,7 @@ pub mod pallet { applicant, milestones, deposit_id, + eoa, } } } diff --git a/pallets/briefs/src/migrations.rs b/pallets/briefs/src/migrations.rs index 97112c50..8c527918 100644 --- a/pallets/briefs/src/migrations.rs +++ b/pallets/briefs/src/migrations.rs @@ -35,7 +35,7 @@ mod v0 { } #[storage_alias] - pub type Briefs = + pub type BriefsV0 = CountedStorageMap, Blake2_128Concat, BriefHash, v0::BriefDataV0, OptionQuery>; } @@ -45,9 +45,10 @@ mod v0 { #[allow(dead_code)] pub(crate) mod v1 { use super::*; + pub fn migrate_to_v1(weight: &mut Weight) { if v2::StorageVersion::::get() == v2::Release::V0 { - crate::Briefs::::translate(|_, brief: v0::BriefDataV0| { + v0::BriefsV0::::drain().for_each(|(key, brief)| { *weight += T::DbWeight::get().reads_writes(2, 1); let maybe_milestones: Result, _> = brief .milestones @@ -67,9 +68,9 @@ pub(crate) mod v1 { if let Ok(milestones) = maybe_milestones { if milestones.len() != brief.milestones.len() { - return None; + return (); } - Some(crate::BriefData { + let migrated = v2::BriefDataV2 { brief_owners: brief.brief_owners, budget: brief.budget, currency_id: brief.currency_id, @@ -78,9 +79,10 @@ pub(crate) mod v1 { milestones, // A deposit_id of U32::Max is skipped and not returned. deposit_id: u32::MAX.into(), - }) - } else { - None + }; + + v2::BriefsV2::::insert(key, migrated); + } }) } @@ -91,14 +93,30 @@ pub(crate) mod v1 { pub mod v2 { use super::*; + #[storage_alias] + pub type BriefsV2 = + CountedStorageMap, Blake2_128Concat, BriefHash, BriefDataV2, OptionQuery>; + + #[derive(Encode, Decode, PartialEq, Eq, Clone, Debug, MaxEncodedLen, TypeInfo)] + #[scale_info(skip_type_params(T))] + pub struct BriefDataV2 { + pub brief_owners: BoundedBriefOwners, + pub budget: BalanceOf, + pub currency_id: CurrencyId, + pub created_at: BlockNumberFor, + pub applicant: AccountIdOf, + pub milestones: BoundedProposedMilestones, + pub deposit_id: crate::DepositIdOf, + } + #[storage_alias] pub type StorageVersion = StorageValue, Release, ValueQuery>; #[derive(Encode, Decode, TypeInfo, PartialEq, MaxEncodedLen, Default)] #[repr(u32)] pub enum Release { - V0, #[default] + V0, V1, } @@ -147,6 +165,65 @@ pub mod v2 { } } +pub mod v3 { + use super::*; + + pub struct MigrateToV3(T); + impl OnRuntimeUpgrade for MigrateToV3 { + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, TryRuntimeError> { + let onchain = Pallet::::on_chain_storage_version(); + ensure!( + onchain == 2, + "onchain must be version 2 to run the migration." + ); + Ok( as Default>::default()) + } + + fn on_runtime_upgrade() -> Weight { + let current = Pallet::::current_storage_version(); + let onchain = Pallet::::on_chain_storage_version(); + let mut weight: Weight = Default::default(); + if current == 3 && onchain == 2 { + v2::BriefsV2::::drain().for_each(|(key, brief)| { + let migrated_brief = BriefData { + created_at: brief.created_at, + brief_owners: brief.brief_owners, + budget: brief.budget, + currency_id: brief.currency_id, + applicant: brief.applicant, + milestones: brief.milestones, + deposit_id: brief.deposit_id, + eoa: None, + }; + + T::DbWeight::get().reads_writes(2, 2); + crate::Briefs::::insert(key, migrated_brief); + }); + + current.put::>(); + + log::warn!("v3 has been successfully applied"); + weight = weight + T::DbWeight::get().reads_writes(2, 1); + } else { + log::warn!("Skipping v3, should be removed"); + weight = weight + T::DbWeight::get().reads(1); + } + weight + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_state: Vec) -> Result<(), TryRuntimeError> { + frame_support::ensure!( + Pallet::::on_chain_storage_version() == 3, + "v3 has not been applied" + ); + + Ok(()) + } + } +} + #[cfg(test)] mod test { use super::*; @@ -183,11 +260,11 @@ mod test { milestones, }; let key: H256 = [1; 32].into(); - v0::Briefs::::insert(key, &old_brief); + v0::BriefsV0::::insert(key, &old_brief); let mut weight: Weight = Default::default(); v1::migrate_to_v1::(&mut weight); - let new_brief = crate::Briefs::::get(key).expect("should exist."); + let new_brief = v2::BriefsV2::::get(key).expect("should exist."); assert_eq!(new_brief.deposit_id, u32::MAX as u64); assert_eq!( new_brief.milestones[0].percentage_to_unlock, diff --git a/pallets/briefs/src/tests.rs b/pallets/briefs/src/tests.rs index 8470dfe3..498479be 100644 --- a/pallets/briefs/src/tests.rs +++ b/pallets/briefs/src/tests.rs @@ -32,6 +32,7 @@ fn create_brief_brief_owner_overflow() { gen_hash(1), CurrencyId::Native, get_milestones(10), + None, ), Error::::TooManyBriefOwners ); @@ -50,6 +51,7 @@ fn create_brief_with_no_contribution_ok() { gen_hash(1), CurrencyId::Native, get_milestones(10), + None, )); }); } @@ -70,6 +72,7 @@ fn create_brief_no_contribution_and_contribute() { brief_id, CurrencyId::Native, get_milestones(10), + None, )); (0..5).for_each(|_| { @@ -111,6 +114,7 @@ fn contribute_to_brief_not_brief_owner() { brief_id, CurrencyId::Native, get_milestones(10), + None, )); assert_noop!( @@ -139,6 +143,7 @@ fn contribute_to_brief_more_than_total_ok() { brief_id, CurrencyId::Native, get_milestones(10), + None, )); assert_ok!(BriefsMod::contribute_to_brief( RuntimeOrigin::signed(BOB), @@ -163,6 +168,7 @@ fn create_brief_already_exists() { brief_id, CurrencyId::Native, get_milestones(10), + None, )); assert_noop!( @@ -175,6 +181,7 @@ fn create_brief_already_exists() { brief_id, CurrencyId::Native, get_milestones(10), + None, ), Error::::BriefAlreadyExists ); @@ -196,6 +203,7 @@ fn only_applicant_can_start_work() { brief_id, CurrencyId::Native, get_milestones(10), + None, )); assert_noop!( @@ -225,6 +233,7 @@ fn initial_contribution_and_extra_contribution_aggregates() { brief_id, CurrencyId::Native, get_milestones(10), + None, )); assert_ok!(BriefsMod::contribute_to_brief( @@ -261,6 +270,7 @@ fn reserved_funds_are_transferred_to_project_kitty() { brief_id, CurrencyId::Native, get_milestones(10), + None, ); assert_ok!(BriefsMod::commence_work( @@ -293,6 +303,7 @@ fn cancel_brief_works() { brief_id, CurrencyId::Native, get_milestones(10), + None, )); assert_ok!(BriefsMod::contribute_to_brief( @@ -359,6 +370,7 @@ fn cancel_brief_not_brief_owner() { brief_id, CurrencyId::Native, get_milestones(10), + None, )); assert_noop!( diff --git a/pallets/grants/Cargo.toml b/pallets/grants/Cargo.toml index cb52826f..39ab5182 100644 --- a/pallets/grants/Cargo.toml +++ b/pallets/grants/Cargo.toml @@ -69,6 +69,7 @@ std = [ ] runtime-benchmarks = [ "common-runtime/runtime-benchmarks", + "common-types/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", diff --git a/pallets/grants/src/benchmarking.rs b/pallets/grants/src/benchmarking.rs index 0c8450b7..eafa9410 100644 --- a/pallets/grants/src/benchmarking.rs +++ b/pallets/grants/src/benchmarking.rs @@ -5,7 +5,7 @@ use super::*; use crate::test_utils::gen_grant_id; use crate::Pallet as Grants; use crate::{BoundedApprovers, BoundedPMilestones, Config}; -use common_types::{CurrencyId, TreasuryOrigin}; +use common_types::{CurrencyId, TreasuryOrigin, ForeignOwnedAccount}; use frame_benchmarking::v2::*; use frame_support::{assert_ok, traits::Get}; use frame_system::pallet_prelude::BlockNumberFor; @@ -27,6 +27,7 @@ mod benchmarks { fn create_and_convert() { let submitter: T::AccountId = create_account_id::("submitter", 1); let grant_id = gen_grant_id(1); + let (eoa, currency_id) = ForeignOwnedAccount::get_supported_currency_eoa_combo(); let approvers = get_approvers::(::MaxApprovers::get()); let milestones = get_milestones::(::MaxMilestonesPerGrant::get()); let amount_requested = 1_000_000u32.into(); @@ -36,10 +37,11 @@ mod benchmarks { RawOrigin::Signed(submitter), milestones, approvers, - CurrencyId::Native, + currency_id, amount_requested, TreasuryOrigin::Kusama, grant_id, + Some(eoa), ); } impl_benchmark_test_suite!(Grants, crate::mock::new_test_ext(), crate::mock::Test); diff --git a/pallets/grants/src/integration_tests.rs b/pallets/grants/src/integration_tests.rs index e37a9d41..f9230bd0 100644 --- a/pallets/grants/src/integration_tests.rs +++ b/pallets/grants/src/integration_tests.rs @@ -19,6 +19,7 @@ fn create_proposal_from_grant() { contribution_value, TreasuryOrigin::Imbue, grant_id, + None, )); assert!(Projects::::get(1).is_some()); }); diff --git a/pallets/grants/src/lib.rs b/pallets/grants/src/lib.rs index 38cce62d..54ee327b 100644 --- a/pallets/grants/src/lib.rs +++ b/pallets/grants/src/lib.rs @@ -101,6 +101,10 @@ pub mod pallet { InvalidTreasuryOrigin, /// Too many approvers TooManyApprovers, + /// If youre using a foreign currency then you need an external_owned_address. + EoaRequiredForForeignCurrencies, + /// Currency is not supported for this external address. + CurrencyAccountComboNotSupported, } #[pallet::call] @@ -116,9 +120,23 @@ pub mod pallet { amount_requested: BalanceOf, treasury_origin: TreasuryOrigin, grant_id: GrantId, + external_owned_address: Option, ) -> DispatchResultWithPostInfo { let submitter = ensure_signed(origin)?; + if let CurrencyId::ForeignAsset(_) = currency_id { + ensure!( + external_owned_address.is_some(), + Error::::EoaRequiredForForeignCurrencies + ); + } + if let Some(eoa) = external_owned_address { + ensure!( + eoa.ensure_supported_currency(currency_id), + Error::::CurrencyAccountComboNotSupported + ); + } + let percentage_sum = proposed_milestones .iter() .fold(Default::default(), |acc: Percent, x| { @@ -168,6 +186,7 @@ pub mod pallet { .try_into() .map_err(|_| Error::::TooManyApprovers)?, pallet_proposals::FundingPath::WaitForFunding, + external_owned_address, )?; GrantsSubmittedBy::::insert(&submitter, grant_id, ()); diff --git a/pallets/grants/src/tests.rs b/pallets/grants/src/tests.rs index 6f853241..402c2360 100644 --- a/pallets/grants/src/tests.rs +++ b/pallets/grants/src/tests.rs @@ -24,7 +24,8 @@ fn ensure_milestone_percent_equal_100() { CurrencyId::Native, 10_000u32.into(), TreasuryOrigin::Kusama, - Default::default() + Default::default(), + None, ), Error::::MustSumTo100 ); @@ -48,6 +49,7 @@ fn create_grant_already_exists() { 10_000u32.into(), TreasuryOrigin::Kusama, grant_id, + None, ); assert_noop!( Grant::create_and_convert( @@ -57,7 +59,8 @@ fn create_grant_already_exists() { CurrencyId::Native, 10_000u32.into(), TreasuryOrigin::Kusama, - grant_id + grant_id, + None, ), Error::::GrantAlreadyExists ); diff --git a/pallets/proposals/src/lib.rs b/pallets/proposals/src/lib.rs index 057e3f01..752c2299 100644 --- a/pallets/proposals/src/lib.rs +++ b/pallets/proposals/src/lib.rs @@ -640,6 +640,7 @@ pub mod pallet { >, jury: BoundedVec, Self::MaxJuryMembers>, on_creation_funding: FundingPath, + eoa: Option, ) -> Result<(), DispatchError> { let project_key = crate::ProjectCount::::get().saturating_add(1); @@ -696,6 +697,7 @@ pub mod pallet { .map_err(|_| Error::::TooManyJuryMembers)?, on_creation_funding, refunded_funds: Zero::zero(), + external_owned_address: eoa, }; let individual_votes = ImmutableIndividualVotes::new(bounded_milestone_keys); @@ -858,6 +860,8 @@ pub struct Project { pub on_creation_funding: FundingPath, /// The amount of funds refunded. pub refunded_funds: BalanceOf, + /// The payment address used when the currency_id is of type foreign. + pub external_owned_address: Option, } /// For deriving the location of an account. diff --git a/pallets/proposals/src/migration.rs b/pallets/proposals/src/migration.rs index ce142def..33946a6d 100644 --- a/pallets/proposals/src/migration.rs +++ b/pallets/proposals/src/migration.rs @@ -776,7 +776,7 @@ pub mod v7 { }); ensure!( - Pallet::::current_storage_version() == 7, + Pallet::::on_chain_storage_version() == 7, "Storage version should be v7 after the migration" ); @@ -855,9 +855,10 @@ pub mod v7 { jury: jury.try_into().expect("contributions bound is larger than jury bound, reduce contribution bound or increase jury bound."), on_creation_funding, refunded_funds: Zero::zero(), + external_owned_address: None, }; - *weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); + *weight = weight.saturating_add(T::DbWeight::get().reads_writes(2, 2)); crate::Projects::::insert(key, migrated_project); }); } diff --git a/pallets/proposals/src/test_utils.rs b/pallets/proposals/src/test_utils.rs index f669b915..eceece11 100644 --- a/pallets/proposals/src/test_utils.rs +++ b/pallets/proposals/src/test_utils.rs @@ -88,6 +88,7 @@ pub fn create_and_fund_project( refund_locations, BoundedVec::new(), FundingPath::TakeFromReserved, + None, )?; Ok(ProjectCount::::get()) @@ -113,6 +114,7 @@ pub fn _create_project_awaiting_funding( vec![(Locality::Foreign(treasury_account), Percent::from_parts(100u8))].try_into().map_err(|_|Error::::TooManyRefundLocations)?, BoundedVec::new(), FundingPath::WaitForFunding, + None, )?; Ok(ProjectCount::::get()) diff --git a/pallets/proposals/src/traits.rs b/pallets/proposals/src/traits.rs index 1b9b2426..f8dda4ab 100644 --- a/pallets/proposals/src/traits.rs +++ b/pallets/proposals/src/traits.rs @@ -30,6 +30,7 @@ pub trait IntoProposal { >, jury: BoundedVec, on_creation_funding: FundingPath, + eoa: Option, ) -> Result<(), DispatchError>; /// Use when the contributors are the refund locations. diff --git a/runtime/imbue-kusama/src/lib.rs b/runtime/imbue-kusama/src/lib.rs index 0b7e9425..1087e827 100644 --- a/runtime/imbue-kusama/src/lib.rs +++ b/runtime/imbue-kusama/src/lib.rs @@ -181,6 +181,7 @@ pub mod migrations { use super::*; /// Unreleased migrations. Add new ones here: pub type Unreleased = ( + pallet_briefs::migrations::v3::MigrateToV3, pallet_fellowship::migration::v0::MigrateInitial, pallet_balances::migration::MigrateToTrackInactive, pallet_collator_selection::migration::v1::MigrateToV1,