From 2d3e8616292ccf36e8d1fbee349b0b144db08451 Mon Sep 17 00:00:00 2001 From: Charles Ferrell Date: Thu, 9 Nov 2023 12:31:14 -0500 Subject: [PATCH 01/12] compile init commit Signed-off-by: Charles Ferrell --- Cargo.lock | 5 + pallets/farming/src/lib.rs | 119 ++++++++-------- pallets/pallet-lottery/Cargo.toml | 5 + pallets/pallet-lottery/src/lib.rs | 32 ++++- pallets/pallet-lottery/src/mock.rs | 212 ++++++++++++++++++++++++++++- runtime/calamari/src/lib.rs | 7 + 6 files changed, 320 insertions(+), 60 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f48c82e40..a0396c1fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7002,7 +7002,11 @@ dependencies = [ "log", "manta-collator-selection", "manta-primitives", + "orml-traits", + "pallet-asset-manager", + "pallet-assets", "pallet-balances", + "pallet-farming", "pallet-parachain-staking", "pallet-preimage", "pallet-randomness", @@ -7022,6 +7026,7 @@ dependencies = [ "sp-runtime", "sp-staking", "sp-std", + "xcm", ] [[package]] diff --git a/pallets/farming/src/lib.rs b/pallets/farming/src/lib.rs index 5ea4ee9ca..321af7c2c 100644 --- a/pallets/farming/src/lib.rs +++ b/pallets/farming/src/lib.rs @@ -430,51 +430,7 @@ pub mod pallet { ) -> DispatchResult { let exchanger = ensure_signed(origin)?; - let mut pool_info = Self::pool_infos(pool_id).ok_or(Error::::PoolDoesNotExist)?; - ensure!( - PoolState::state_valid(Action::Deposit, pool_info.state), - Error::::InvalidPoolState - ); - - if let PoolState::Charged = pool_info.state { - let n: BlockNumberFor = frame_system::Pallet::::block_number(); - ensure!( - n >= pool_info.after_block_to_start, - Error::::CanNotDeposit - ); - } - - // basic token proportion * add_value * token_proportion - // if basic token proportion and token_proportion both equals to 100%, then the final amount to transfer is equal to add_value - let native_amount = pool_info.basic_token.1.saturating_reciprocal_mul(add_value); - pool_info.tokens_proportion.iter().try_for_each( - |(token, proportion)| -> DispatchResult { - T::MultiCurrency::transfer( - *token, - &exchanger, - &pool_info.keeper, - *proportion * native_amount, - ) - }, - )?; - Self::add_share(&exchanger, pool_id, &mut pool_info, add_value); - - if let Some((gauge_value, gauge_block)) = gauge_info { - Self::gauge_add( - &exchanger, - pool_info.gauge.ok_or(Error::::GaugePoolNotExist)?, - gauge_value, - gauge_block, - )?; - } - - Self::deposit_event(Event::Deposited { - who: exchanger, - pid: pool_id, - add_value, - gauge_info, - }); - Ok(()) + Self::deposit_farming(exchanger, pool_id, add_value, gauge_info) } /// `Withdraw` operation only remove share and get claim rewards, then update `withdraw_list` of user share info. @@ -555,14 +511,7 @@ pub mod pallet { pub fn withdraw_claim(origin: OriginFor, pool_id: PoolId) -> DispatchResult { let exchanger = ensure_signed(origin)?; - let pool_info = Self::pool_infos(pool_id).ok_or(Error::::PoolDoesNotExist)?; - Self::process_withdraw_list(&exchanger, pool_id, &pool_info, false)?; - - Self::deposit_event(Event::WithdrawClaimed { - who: exchanger, - pid: pool_id, - }); - Ok(()) + Self::withdraw_farming(exchanger, pool_id) } #[pallet::call_index(6)] @@ -942,4 +891,68 @@ impl Pallet { .saturated_into(); total_reward_proportion } + + pub fn deposit_farming( + exchanger: T::AccountId, + pool_id: PoolId, + add_value: BalanceOf, + gauge_info: Option<(BalanceOf, BlockNumberFor)>, + ) -> DispatchResult { + let mut pool_info = Self::pool_infos(pool_id).ok_or(Error::::PoolDoesNotExist)?; + ensure!( + PoolState::state_valid(Action::Deposit, pool_info.state), + Error::::InvalidPoolState + ); + + if let PoolState::Charged = pool_info.state { + let n: BlockNumberFor = frame_system::Pallet::::block_number(); + ensure!( + n >= pool_info.after_block_to_start, + Error::::CanNotDeposit + ); + } + + // basic token proportion * add_value * token_proportion + // if basic token proportion and token_proportion both equals to 100%, then the final amount to transfer is equal to add_value + let native_amount = pool_info.basic_token.1.saturating_reciprocal_mul(add_value); + pool_info.tokens_proportion.iter().try_for_each( + |(token, proportion)| -> DispatchResult { + T::MultiCurrency::transfer( + *token, + &exchanger, + &pool_info.keeper, + *proportion * native_amount, + ) + }, + )?; + Self::add_share(&exchanger, pool_id, &mut pool_info, add_value); + + if let Some((gauge_value, gauge_block)) = gauge_info { + Self::gauge_add( + &exchanger, + pool_info.gauge.ok_or(Error::::GaugePoolNotExist)?, + gauge_value, + gauge_block, + )?; + } + + Self::deposit_event(Event::Deposited { + who: exchanger, + pid: pool_id, + add_value, + gauge_info, + }); + Ok(()) + } + + pub fn withdraw_farming(exchanger: T::AccountId, pool_id: PoolId) -> DispatchResult { + let pool_info = Self::pool_infos(pool_id).ok_or(Error::::PoolDoesNotExist)?; + Self::process_withdraw_list(&exchanger, pool_id, &pool_info, false)?; + + Self::deposit_event(Event::WithdrawClaimed { + who: exchanger, + pid: pool_id, + }); + Ok(()) + } } diff --git a/pallets/pallet-lottery/Cargo.toml b/pallets/pallet-lottery/Cargo.toml index 3e04c15e2..7670c5a10 100644 --- a/pallets/pallet-lottery/Cargo.toml +++ b/pallets/pallet-lottery/Cargo.toml @@ -25,12 +25,14 @@ sp-core = { git = 'https://github.com/paritytech/substrate.git', default-feature sp-io = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" } sp-runtime = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" } sp-std = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" } +orml-traits = { git = "https://github.com/manta-network/open-runtime-module-library.git", branch = "polkadot-v0.9.37", default-features = false } # Self dependencies manta-primitives = { path = "../../primitives/manta", default-features = false } pallet-parachain-staking = { path = '../parachain-staking', default-features = false } runtime-common = { path = "../../runtime/common", default-features = false } session-key-primitives = { path = '../../primitives/session-keys', default-features = false } +pallet-farming = { path = '../farming', default-features = false } # Benchmarking dependencies frame-benchmarking = { git = 'https://github.com/paritytech/substrate.git', branch = "polkadot-v0.9.37", default-features = false, optional = true } @@ -38,8 +40,10 @@ rand = { version = "0.8.5", default-features = false, optional = true } [dev-dependencies] calamari-runtime = { path = "../../runtime/calamari", default-features = false } +pallet-asset-manager = { path = "../asset-manager", default-features = false } lazy_static = "1.4.0" manta-collator-selection = { path = "../collator-selection", default-features = false } +pallet-assets = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" } pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" } pallet-preimage = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" } pallet-randomness = { path = '../randomness', default-features = false } @@ -48,6 +52,7 @@ pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.gi rand = "0.8" similar-asserts = "1.1.0" sp-staking = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" } +xcm = { git = "https://github.com/paritytech/polkadot.git", branch = "release-v0.9.37", default-features = false } [features] default = ["std"] diff --git a/pallets/pallet-lottery/src/lib.rs b/pallets/pallet-lottery/src/lib.rs index cd4cec5d1..866c1eb11 100644 --- a/pallets/pallet-lottery/src/lib.rs +++ b/pallets/pallet-lottery/src/lib.rs @@ -104,6 +104,8 @@ pub mod pallet { PalletId, }; use frame_system::{pallet_prelude::*, RawOrigin}; + use manta_primitives::types::PoolId; + use orml_traits::MultiCurrency; use pallet_parachain_staking::BalanceOf; use sp_arithmetic::traits::SaturatedConversion; use sp_core::U256; @@ -118,7 +120,9 @@ pub mod pallet { pub type CallOf = ::RuntimeCall; #[pallet::config] - pub trait Config: frame_system::Config + pallet_parachain_staking::Config { + pub trait Config: + frame_system::Config + pallet_parachain_staking::Config + pallet_farming::Config + { /// The aggregated `RuntimeCall` type. type RuntimeCall: Parameter + Dispatchable @@ -131,7 +135,18 @@ pub mod pallet { Self::PalletsOrigin, Hash = Self::Hash, >; - // Randomness source to use for determining lottery winner + /// CurrencyId for the JUMBO token + type JumboShrimpCurrencyId: Get<::CurrencyId>; + /// PoolId for JumboShrimp Farming Pool + type PoolId: Get; + /// Helper to convert between Balance types of `MultiCurrency` and `Currency` (most likely equivalent types in runtime) + type BalanceConversion: Copy + + Into< + <::MultiCurrency as MultiCurrency< + ::AccountId, + >>::Balance, + > + From>; + /// Randomness source to use for determining lottery winner type RandomnessSource: Randomness; /// Something that can estimate the cost of sending an extrinsic type EstimateCallFee: frame_support::traits::EstimateCallFee< @@ -394,6 +409,19 @@ pub mod pallet { Error::::PalletMisconfigured }; + let convert_amount: T::BalanceConversion = amount.into(); + ::MultiCurrency::deposit( + T::JumboShrimpCurrencyId::get(), + &caller_account, + convert_amount.into(), + )?; + pallet_farming::Pallet::::deposit_farming( + caller_account.clone(), + T::PoolId::get(), + convert_amount.into(), + None, + )?; + // Transfer funds to pot ::Currency::transfer( &caller_account, diff --git a/pallets/pallet-lottery/src/mock.rs b/pallets/pallet-lottery/src/mock.rs index 279d8a07c..432add599 100644 --- a/pallets/pallet-lottery/src/mock.rs +++ b/pallets/pallet-lottery/src/mock.rs @@ -21,12 +21,24 @@ use crate as pallet_lottery; use crate::{pallet, Config}; use calamari_runtime::currency::KMA; use frame_support::{ - construct_runtime, parameter_types, - traits::{ConstU128, ConstU32, Everything, GenesisBuild, OnFinalize, OnInitialize}, + construct_runtime, ord_parameter_types, + pallet_prelude::*, + parameter_types, + traits::{ + AsEnsureOriginWithArg, ConstU128, ConstU32, EitherOfDiverse, Everything, GenesisBuild, + }, weights::Weight, }; -use frame_system::pallet_prelude::*; -use manta_primitives::types::{BlockNumber, Header}; +use frame_system::{pallet_prelude::*, EnsureNever, EnsureSignedBy}; +use manta_primitives::{ + assets::{ + AssetConfig, AssetIdType, AssetLocation, AssetRegistry, AssetRegistryMetadata, + AssetStorageMetadata, BalanceType, LocationType, NativeAndNonNative, + }, + constants::ASSET_MANAGER_PALLET_ID, + currencies::Currencies, + types::{BlockNumber, CalamariAssetId, Header, PoolId}, +}; use pallet_parachain_staking::{InflationInfo, Range}; use sp_core::H256; @@ -34,10 +46,18 @@ use sp_runtime::{ traits::{BlakeTwo256, Hash, IdentityLookup}, Perbill, Percent, }; +use xcm::{ + prelude::{Parachain, X1}, + v2::MultiLocation, + VersionedMultiLocation, +}; pub type AccountId = u64; pub type Balance = u128; +pub const ALICE: AccountId = 1; +pub const TREASURY_ACCOUNT: AccountId = 10; + type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -56,6 +76,9 @@ construct_runtime!( CollatorSelection: manta_collator_selection::{Pallet, Call, Storage, Config, Event}, Lottery: pallet_lottery::{Pallet, Call, Storage, Event, Config}, Preimage: pallet_preimage::{Pallet, Call, Storage, Event}, + Assets: pallet_assets::{Pallet, Storage, Config, Event}, + AssetManager: pallet_asset_manager::{Pallet, Call, Storage, Event}, + Farming: pallet_farming::{Pallet, Call, Storage, Event} } ); @@ -272,6 +295,179 @@ impl pallet_parachain_staking::Config for Test { type WeightInfo = calamari_runtime::weights::pallet_parachain_staking::SubstrateWeight; // XXX: Maybe use the actual calamari weights? } +parameter_types! { + // Does not really matter as this will be only called by root + pub const AssetDeposit: Balance = 0; + pub const AssetAccountDeposit: Balance = 0; + pub const ApprovalDeposit: Balance = 0; + pub const AssetsStringLimit: u32 = 50; + pub const MetadataDepositBase: Balance = 0; + pub const MetadataDepositPerByte: Balance = 0; +} + +impl pallet_assets::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = CalamariAssetId; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type WeightInfo = pallet_assets::weights::SubstrateWeight; + type RemoveItemsLimit = ConstU32<1000>; + type AssetIdParameter = CalamariAssetId; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); +} + +pub struct MantaAssetRegistry; +impl BalanceType for MantaAssetRegistry { + type Balance = Balance; +} +impl AssetIdType for MantaAssetRegistry { + type AssetId = CalamariAssetId; +} +impl AssetRegistry for MantaAssetRegistry { + type Metadata = AssetStorageMetadata; + type Error = sp_runtime::DispatchError; + + fn create_asset( + asset_id: CalamariAssetId, + metadata: AssetStorageMetadata, + min_balance: Balance, + is_sufficient: bool, + ) -> DispatchResult { + Assets::force_create( + RuntimeOrigin::root(), + asset_id, + AssetManager::account_id(), + is_sufficient, + min_balance, + )?; + + Assets::force_set_metadata( + RuntimeOrigin::root(), + asset_id, + metadata.name, + metadata.symbol, + metadata.decimals, + metadata.is_frozen, + )?; + + Assets::force_asset_status( + RuntimeOrigin::root(), + asset_id, + AssetManager::account_id(), + AssetManager::account_id(), + AssetManager::account_id(), + AssetManager::account_id(), + min_balance, + is_sufficient, + metadata.is_frozen, + ) + } + + fn update_asset_metadata( + asset_id: &CalamariAssetId, + metadata: AssetStorageMetadata, + ) -> DispatchResult { + Assets::force_set_metadata( + RuntimeOrigin::root(), + *asset_id, + metadata.name, + metadata.symbol, + metadata.decimals, + metadata.is_frozen, + ) + } +} + +parameter_types! { + pub const DummyAssetId: CalamariAssetId = 0; + pub const NativeAssetId: CalamariAssetId = 1; + pub const StartNonNativeAssetId: CalamariAssetId = 8; + pub NativeAssetLocation: AssetLocation = AssetLocation( + VersionedMultiLocation::V1(MultiLocation::new(1, X1(Parachain(1024))))); + pub NativeAssetMetadata: AssetRegistryMetadata = AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: b"Calamari".to_vec(), + symbol: b"KMA".to_vec(), + decimals: 12, + is_frozen: false, + }, + min_balance: 1u128, + is_sufficient: true, + }; + pub const AssetManagerPalletId: PalletId = ASSET_MANAGER_PALLET_ID; +} + +/// AssetConfig implementations for this runtime +#[derive(Clone, Eq, PartialEq)] +pub struct MantaAssetConfig; +impl LocationType for MantaAssetConfig { + type Location = AssetLocation; +} +impl AssetIdType for MantaAssetConfig { + type AssetId = CalamariAssetId; +} +impl BalanceType for MantaAssetConfig { + type Balance = Balance; +} +impl AssetConfig for MantaAssetConfig { + type NativeAssetId = NativeAssetId; + type StartNonNativeAssetId = StartNonNativeAssetId; + type NativeAssetLocation = NativeAssetLocation; + type NativeAssetMetadata = NativeAssetMetadata; + type AssetRegistry = MantaAssetRegistry; + type FungibleLedger = NativeAndNonNative; +} + +impl pallet_asset_manager::Config for Test { + type RuntimeEvent = RuntimeEvent; + type AssetId = CalamariAssetId; + type Location = AssetLocation; + type AssetConfig = MantaAssetConfig; + type ModifierOrigin = EnsureRoot; + type SuspenderOrigin = EnsureRoot; + type PalletId = AssetManagerPalletId; + type WeightInfo = (); + type PermissionlessStartId = ConstU128<100>; + type TokenNameMaxLen = ConstU32<100>; + type TokenSymbolMaxLen = ConstU32<100>; + type PermissionlessAssetRegistryCost = ConstU128<1000>; +} + +parameter_types! { + pub const FarmingKeeperPalletId: PalletId = PalletId(*b"bf/fmkpr"); + pub const FarmingRewardIssuerPalletId: PalletId = PalletId(*b"bf/fmrir"); + pub const TreasuryAccount: AccountId = TREASURY_ACCOUNT; +} + +ord_parameter_types! { + pub const Alice: AccountId = ALICE; +} + +type MantaCurrencies = Currencies; + +impl pallet_farming::Config for Test { + type RuntimeEvent = RuntimeEvent; + type CurrencyId = CalamariAssetId; + type MultiCurrency = MantaCurrencies; + type ControlOrigin = EitherOfDiverse, EnsureSignedBy>; + type TreasuryAccount = TreasuryAccount; + type Keeper = FarmingKeeperPalletId; + type RewardIssuer = FarmingRewardIssuerPalletId; + type WeightInfo = (); +} + impl block_author::Config for Test {} use frame_support::PalletId; @@ -285,6 +481,10 @@ parameter_types! { pub DrawingFreezeout: BlockNumber = 5; /// Time in blocks until a collator is done unstaking pub UnstakeLockTime: BlockNumber = LeaveDelayRounds::get() * DefaultBlocksPerRound::get(); + /// JumboShrimp CurrencyId + pub JumboShrimpCurrencyId: CalamariAssetId = 10; + /// Farming PoolId for JUMBO token + pub JumboShrimpPoolId: PoolId = 5; } use frame_support::traits::Currency; @@ -324,6 +524,9 @@ impl Config for Test { type DrawingInterval = DrawingInterval; type DrawingFreezeout = DrawingFreezeout; type UnstakeLockTime = UnstakeLockTime; + type JumboShrimpCurrencyId = JumboShrimpCurrencyId; + type PoolId = JumboShrimpPoolId; + type BalanceConversion = Balance; type WeightInfo = (); } @@ -506,7 +709,6 @@ macro_rules! assert_last_event { #[frame_support::pallet] pub mod block_author { use super::*; - use frame_support::{pallet_prelude::*, traits::Get}; #[pallet::config] pub trait Config: frame_system::Config {} diff --git a/runtime/calamari/src/lib.rs b/runtime/calamari/src/lib.rs index e42236e68..d25bfdbff 100644 --- a/runtime/calamari/src/lib.rs +++ b/runtime/calamari/src/lib.rs @@ -447,6 +447,10 @@ parameter_types! { pub DrawingFreezeout: BlockNumber = prod_or_fast!(1 * DAYS, 1 * MINUTES); /// Time in blocks until a collator is done unstaking pub UnstakeLockTime: BlockNumber = LeaveDelayRounds::get() * DefaultBlocksPerRound::get(); + /// JumboShrimp CurrencyId + pub JumboShrimpCurrencyId: CalamariAssetId = 10; + /// Farming PoolId for JUMBO token + pub JumboShrimpPoolId: PoolId = 5; } impl pallet_lottery::Config for Runtime { type RuntimeCall = RuntimeCall; @@ -460,6 +464,9 @@ impl pallet_lottery::Config for Runtime { type DrawingInterval = DrawingInterval; type DrawingFreezeout = DrawingFreezeout; type UnstakeLockTime = UnstakeLockTime; + type JumboShrimpCurrencyId = JumboShrimpCurrencyId; + type PoolId = JumboShrimpPoolId; + type BalanceConversion = Balance; type WeightInfo = weights::pallet_lottery::SubstrateWeight; } impl pallet_authorship::Config for Runtime { From 2d999779c2480b3c0fe2a86bbea1874d944ae9c4 Mon Sep 17 00:00:00 2001 From: Charles Ferrell Date: Thu, 9 Nov 2023 13:11:02 -0500 Subject: [PATCH 02/12] add withdraw logic Signed-off-by: Charles Ferrell --- pallets/pallet-lottery/src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pallets/pallet-lottery/src/lib.rs b/pallets/pallet-lottery/src/lib.rs index 866c1eb11..fddad954b 100644 --- a/pallets/pallet-lottery/src/lib.rs +++ b/pallets/pallet-lottery/src/lib.rs @@ -409,6 +409,7 @@ pub mod pallet { Error::::PalletMisconfigured }; + // mint JUMBO token and put it in farming pool let convert_amount: T::BalanceConversion = amount.into(); ::MultiCurrency::deposit( T::JumboShrimpCurrencyId::get(), @@ -489,6 +490,15 @@ pub mod pallet { Self::not_in_drawing_freezeout(), Error::::TooCloseToDrawing ); + + let convert_amount: T::BalanceConversion = amount.into(); + pallet_farming::Pallet::::withdraw_farming(caller.clone(), T::PoolId::get())?; + ::MultiCurrency::withdraw( + T::JumboShrimpCurrencyId::get(), + &caller, + convert_amount.into(), + )?; + let now = >::block_number(); log::debug!("Requesting withdraw of {:?} tokens", amount); // Ensure user has enough funds active and mark them as offboarding (remove from `ActiveBalancePerUser`) From 28de7d01b2c01c2aada9d941b29fb469bb605edb Mon Sep 17 00:00:00 2001 From: Charles Ferrell Date: Thu, 9 Nov 2023 19:51:15 -0500 Subject: [PATCH 03/12] fix withdrawals Signed-off-by: Charles Ferrell --- pallets/farming/src/lib.rs | 69 ++++++++++------- pallets/pallet-lottery/src/lib.rs | 6 +- pallets/pallet-lottery/src/mock.rs | 117 +++++++++++++++++++++++++++-- runtime/calamari/src/lib.rs | 4 +- runtime/manta/src/lib.rs | 7 ++ 5 files changed, 168 insertions(+), 35 deletions(-) diff --git a/pallets/farming/src/lib.rs b/pallets/farming/src/lib.rs index 321af7c2c..bfdfa4a8d 100644 --- a/pallets/farming/src/lib.rs +++ b/pallets/farming/src/lib.rs @@ -444,32 +444,7 @@ pub mod pallet { ) -> DispatchResult { let exchanger = ensure_signed(origin)?; - let pool_info = Self::pool_infos(pool_id).ok_or(Error::::PoolDoesNotExist)?; - ensure!( - PoolState::state_valid(Action::Withdraw, pool_info.state), - Error::::InvalidPoolState - ); - - let share_info = Self::shares_and_withdrawn_rewards(pool_id, &exchanger) - .ok_or(Error::::ShareInfoNotExists)?; - ensure!( - share_info.withdraw_list.len() < pool_info.withdraw_limit_count.into(), - Error::::WithdrawLimitCountExceeded - ); - - Self::remove_share( - &exchanger, - pool_id, - remove_value, - pool_info.withdraw_limit_time, - )?; - - Self::deposit_event(Event::Withdrawn { - who: exchanger, - pid: pool_id, - remove_value, - }); - Ok(()) + Self::withdraw_amount(exchanger, pool_id, remove_value) } /// `claim` operation can claim rewards and also un-stake if user share info has `withdraw_list`. @@ -955,4 +930,46 @@ impl Pallet { }); Ok(()) } + + pub fn withdraw_amount( + exchanger: T::AccountId, + pool_id: PoolId, + remove_value: Option>, + ) -> DispatchResult { + let pool_info = Self::pool_infos(pool_id).ok_or(Error::::PoolDoesNotExist)?; + ensure!( + PoolState::state_valid(Action::Withdraw, pool_info.state), + Error::::InvalidPoolState + ); + + let share_info = Self::shares_and_withdrawn_rewards(pool_id, &exchanger) + .ok_or(Error::::ShareInfoNotExists)?; + ensure!( + share_info.withdraw_list.len() < pool_info.withdraw_limit_count.into(), + Error::::WithdrawLimitCountExceeded + ); + + Self::remove_share( + &exchanger, + pool_id, + remove_value, + pool_info.withdraw_limit_time, + )?; + + Self::deposit_event(Event::Withdrawn { + who: exchanger, + pid: pool_id, + remove_value, + }); + Ok(()) + } + + pub fn withdraw_and_unstake( + exchanger: T::AccountId, + pool_id: PoolId, + remove_value: Option>, + ) -> DispatchResult { + Self::withdraw_amount(exchanger.clone(), pool_id, remove_value)?; + Self::withdraw_farming(exchanger, pool_id) + } } diff --git a/pallets/pallet-lottery/src/lib.rs b/pallets/pallet-lottery/src/lib.rs index fddad954b..56c7e2dcc 100644 --- a/pallets/pallet-lottery/src/lib.rs +++ b/pallets/pallet-lottery/src/lib.rs @@ -492,7 +492,11 @@ pub mod pallet { ); let convert_amount: T::BalanceConversion = amount.into(); - pallet_farming::Pallet::::withdraw_farming(caller.clone(), T::PoolId::get())?; + pallet_farming::Pallet::::withdraw_and_unstake( + caller.clone(), + T::PoolId::get(), + Some(convert_amount.into()), + )?; ::MultiCurrency::withdraw( T::JumboShrimpCurrencyId::get(), &caller, diff --git a/pallets/pallet-lottery/src/mock.rs b/pallets/pallet-lottery/src/mock.rs index 432add599..1c6ecd58c 100644 --- a/pallets/pallet-lottery/src/mock.rs +++ b/pallets/pallet-lottery/src/mock.rs @@ -21,7 +21,7 @@ use crate as pallet_lottery; use crate::{pallet, Config}; use calamari_runtime::currency::KMA; use frame_support::{ - construct_runtime, ord_parameter_types, + assert_ok, construct_runtime, ord_parameter_types, pallet_prelude::*, parameter_types, traits::{ @@ -33,7 +33,7 @@ use frame_system::{pallet_prelude::*, EnsureNever, EnsureSignedBy}; use manta_primitives::{ assets::{ AssetConfig, AssetIdType, AssetLocation, AssetRegistry, AssetRegistryMetadata, - AssetStorageMetadata, BalanceType, LocationType, NativeAndNonNative, + AssetStorageMetadata, BalanceType, FungibleLedger, LocationType, NativeAndNonNative, }, constants::ASSET_MANAGER_PALLET_ID, currencies::Currencies, @@ -43,11 +43,11 @@ use pallet_parachain_staking::{InflationInfo, Range}; use sp_core::H256; use sp_runtime::{ - traits::{BlakeTwo256, Hash, IdentityLookup}, + traits::{AccountIdConversion, BlakeTwo256, Hash, IdentityLookup}, Perbill, Percent, }; use xcm::{ - prelude::{Parachain, X1}, + prelude::{Junctions, Parachain, X1}, v2::MultiLocation, VersionedMultiLocation, }; @@ -56,7 +56,10 @@ pub type AccountId = u64; pub type Balance = u128; pub const ALICE: AccountId = 1; +pub const BOB: AccountId = 2; pub const TREASURY_ACCOUNT: AccountId = 10; +pub const JUMBO: Balance = 1_000_000_000_000; +pub const JUMBO_ID: CalamariAssetId = 8; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -482,9 +485,9 @@ parameter_types! { /// Time in blocks until a collator is done unstaking pub UnstakeLockTime: BlockNumber = LeaveDelayRounds::get() * DefaultBlocksPerRound::get(); /// JumboShrimp CurrencyId - pub JumboShrimpCurrencyId: CalamariAssetId = 10; + pub JumboShrimpCurrencyId: CalamariAssetId = JUMBO_ID; /// Farming PoolId for JUMBO token - pub JumboShrimpPoolId: PoolId = 5; + pub JumboShrimpPoolId: PoolId = 0; } use frame_support::traits::Currency; @@ -619,13 +622,115 @@ impl ExtBuilder { } .assimilate_storage(&mut t) .expect("pallet_lottery's storage can be assimilated"); + pallet_asset_manager::GenesisConfig:: { + start_id: >::StartNonNativeAssetId::get(), + } + .assimilate_storage(&mut t) + .expect("pallet_asset_manager storage fails"); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| System::set_block_number(1)); + + ext.execute_with(|| { + let jumbo_asset_metadata = + create_asset_metadata("Jumbo", "JUMBO", 12, 1u128, false, true); + let native_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::new( + 0, + Junctions::Here, + ))); + // registering manta native asset should work. + AssetManager::register_asset( + RuntimeOrigin::root(), + native_location, + jumbo_asset_metadata, + ) + .unwrap(); + + assert_ok!( + >::FungibleLedger::deposit_minting( + JUMBO_ID, + &TREASURY_ACCOUNT, + 1_000 * JUMBO + ) + ); + assert_ok!( + >::FungibleLedger::deposit_minting( + JUMBO_ID, + &ALICE, + 1_000 * JUMBO + ) + ); + assert_ok!( + >::FungibleLedger::deposit_minting( + JUMBO_ID, + &BOB, + 1_000_000 * JUMBO + ) + ); + + init_jumbo_farming(); + }); + ext } } +fn init_jumbo_farming() { + let tokens_proportion = vec![(JUMBO_ID, Perbill::from_percent(100))]; + let tokens = JUMBO; + let basic_rewards = vec![(JUMBO_ID, JUMBO)]; + + assert_ok!(Farming::create_farming_pool( + RuntimeOrigin::signed(ALICE), + tokens_proportion, + basic_rewards, + None, + 0, // min_deposit_to_start + 0, // after_block_to_start + 0, // withdraw_limit_time + 0, // claim_limit_time + 5 // withdraw_limit_count + )); + + let pool_id = 0; + let charge_rewards = vec![(JUMBO_ID, 100 * JUMBO)]; + + assert_ok!(Farming::charge( + RuntimeOrigin::signed(ALICE), + pool_id, + charge_rewards + )); + assert_ok!(Farming::deposit( + RuntimeOrigin::signed(ALICE), + pool_id, + tokens, + None + )); + + let share_info = Farming::shares_and_withdrawn_rewards(pool_id, &ALICE).unwrap(); + assert_eq!(share_info.share, tokens); +} + +pub(crate) fn create_asset_metadata( + name: &str, + symbol: &str, + decimals: u8, + min_balance: u128, + is_frozen: bool, + is_sufficient: bool, +) -> AssetRegistryMetadata { + AssetRegistryMetadata { + metadata: AssetStorageMetadata { + name: name.as_bytes().to_vec(), + symbol: symbol.as_bytes().to_vec(), + decimals, + is_frozen, + }, + min_balance, + is_sufficient, + } +} + pub mod from_bench { /// copied from frame benchmarking use super::*; diff --git a/runtime/calamari/src/lib.rs b/runtime/calamari/src/lib.rs index d25bfdbff..d6c3a4773 100644 --- a/runtime/calamari/src/lib.rs +++ b/runtime/calamari/src/lib.rs @@ -448,9 +448,9 @@ parameter_types! { /// Time in blocks until a collator is done unstaking pub UnstakeLockTime: BlockNumber = LeaveDelayRounds::get() * DefaultBlocksPerRound::get(); /// JumboShrimp CurrencyId - pub JumboShrimpCurrencyId: CalamariAssetId = 10; + pub JumboShrimpCurrencyId: CalamariAssetId = 8; /// Farming PoolId for JUMBO token - pub JumboShrimpPoolId: PoolId = 5; + pub JumboShrimpPoolId: PoolId = 0; } impl pallet_lottery::Config for Runtime { type RuntimeCall = RuntimeCall; diff --git a/runtime/manta/src/lib.rs b/runtime/manta/src/lib.rs index b4410d02b..4acad2813 100644 --- a/runtime/manta/src/lib.rs +++ b/runtime/manta/src/lib.rs @@ -410,6 +410,10 @@ parameter_types! { pub DrawingFreezeout: BlockNumber = prod_or_fast!(1 * DAYS, 1 * MINUTES); /// Time in blocks until a collator is done unstaking pub UnstakeLockTime: BlockNumber = LeaveDelayRounds::get() * DefaultBlocksPerRound::get(); + /// JumboShrimp CurrencyId + pub JumboShrimpCurrencyId: MantaAssetId = 8; + /// Farming PoolId for JUMBO token + pub JumboShrimpPoolId: PoolId = 0; } impl pallet_lottery::Config for Runtime { type RuntimeCall = RuntimeCall; @@ -423,6 +427,9 @@ impl pallet_lottery::Config for Runtime { type DrawingInterval = DrawingInterval; type DrawingFreezeout = DrawingFreezeout; type UnstakeLockTime = UnstakeLockTime; + type JumboShrimpCurrencyId = JumboShrimpCurrencyId; + type PoolId = JumboShrimpPoolId; + type BalanceConversion = Balance; type WeightInfo = weights::pallet_lottery::SubstrateWeight; } From 20e1813af7f09818fbca98db463d89fdaed28951 Mon Sep 17 00:00:00 2001 From: Charles Ferrell Date: Wed, 15 Nov 2023 14:41:20 -0500 Subject: [PATCH 04/12] add enable farming toggle and add tests Signed-off-by: Charles Ferrell --- pallets/pallet-lottery/src/lib.rs | 79 ++++++++++++++++++++--------- pallets/pallet-lottery/src/mock.rs | 15 ++++-- pallets/pallet-lottery/src/tests.rs | 57 +++++++++++++++++++++ runtime/calamari/src/lib.rs | 4 +- runtime/manta/src/lib.rs | 4 +- 5 files changed, 127 insertions(+), 32 deletions(-) diff --git a/pallets/pallet-lottery/src/lib.rs b/pallets/pallet-lottery/src/lib.rs index 56c7e2dcc..afa264732 100644 --- a/pallets/pallet-lottery/src/lib.rs +++ b/pallets/pallet-lottery/src/lib.rs @@ -136,7 +136,7 @@ pub mod pallet { Hash = Self::Hash, >; /// CurrencyId for the JUMBO token - type JumboShrimpCurrencyId: Get<::CurrencyId>; + type JumboFarmingCurrencyID: Get<::CurrencyId>; /// PoolId for JumboShrimp Farming Pool type PoolId: Get; /// Helper to convert between Balance types of `MultiCurrency` and `Currency` (most likely equivalent types in runtime) @@ -280,12 +280,21 @@ pub mod pallet { pub(super) type StakedCollators = StorageMap<_, Blake2_128Concat, T::AccountId, BalanceOf, ValueQuery>; + /// Boolean for the minting of a farming token on `deposit` call + #[pallet::storage] + pub(super) type MintFarmingToken = StorageValue<_, bool, ValueQuery>; + + /// Requires the burning of a farming token when withdrawing from lottery when value is `true` + #[pallet::storage] + pub(super) type DestroyFarmingToken = StorageValue<_, bool, ValueQuery>; + #[pallet::genesis_config] pub struct GenesisConfig { /// amount of token to keep in the pot for paying gas fees pub gas_reserve: BalanceOf, pub min_deposit: BalanceOf, pub min_withdraw: BalanceOf, + pub farming_pool_live: bool, } #[cfg(feature = "std")] @@ -295,6 +304,7 @@ pub mod pallet { min_deposit: 1u32.into(), min_withdraw: 1u32.into(), gas_reserve: 10_000u32.into(), + farming_pool_live: false, } } } @@ -306,6 +316,8 @@ pub mod pallet { GasReserve::::set(self.gas_reserve); MinDeposit::::set(self.min_deposit); MinWithdraw::::set(self.min_withdraw); + MintFarmingToken::::set(self.farming_pool_live); + MintFarmingToken::::set(self.farming_pool_live); } } @@ -409,19 +421,21 @@ pub mod pallet { Error::::PalletMisconfigured }; - // mint JUMBO token and put it in farming pool - let convert_amount: T::BalanceConversion = amount.into(); - ::MultiCurrency::deposit( - T::JumboShrimpCurrencyId::get(), - &caller_account, - convert_amount.into(), - )?; - pallet_farming::Pallet::::deposit_farming( - caller_account.clone(), - T::PoolId::get(), - convert_amount.into(), - None, - )?; + if MintFarmingToken::::get() { + // mint JUMBO token and put it in farming pool + let convert_amount: T::BalanceConversion = amount.into(); + ::MultiCurrency::deposit( + T::JumboFarmingCurrencyID::get(), + &caller_account, + convert_amount.into(), + )?; + pallet_farming::Pallet::::deposit_farming( + caller_account.clone(), + T::PoolId::get(), + convert_amount.into(), + None, + )?; + } // Transfer funds to pot ::Currency::transfer( @@ -491,17 +505,19 @@ pub mod pallet { Error::::TooCloseToDrawing ); - let convert_amount: T::BalanceConversion = amount.into(); - pallet_farming::Pallet::::withdraw_and_unstake( - caller.clone(), - T::PoolId::get(), - Some(convert_amount.into()), - )?; - ::MultiCurrency::withdraw( - T::JumboShrimpCurrencyId::get(), - &caller, - convert_amount.into(), - )?; + if DestroyFarmingToken::::get() { + let convert_amount: T::BalanceConversion = amount.into(); + pallet_farming::Pallet::::withdraw_and_unstake( + caller.clone(), + T::PoolId::get(), + Some(convert_amount.into()), + )?; + ::MultiCurrency::withdraw( + T::JumboFarmingCurrencyID::get(), + &caller, + convert_amount.into(), + )?; + } let now = >::block_number(); log::debug!("Requesting withdraw of {:?} tokens", amount); @@ -891,6 +907,19 @@ pub mod pallet { GasReserve::::set(gas_reserve); Ok(()) } + #[pallet::call_index(12)] + #[pallet::weight(::WeightInfo::set_gas_reserve())] + pub fn set_farming_params( + origin: OriginFor, + mint_farming_token: bool, + burn_farming_token: bool, + ) -> DispatchResult { + T::ManageOrigin::ensure_origin(origin)?; + + MintFarmingToken::::set(mint_farming_token); + DestroyFarmingToken::::set(burn_farming_token); + Ok(()) + } } impl Pallet { diff --git a/pallets/pallet-lottery/src/mock.rs b/pallets/pallet-lottery/src/mock.rs index 1c6ecd58c..a14bfc15b 100644 --- a/pallets/pallet-lottery/src/mock.rs +++ b/pallets/pallet-lottery/src/mock.rs @@ -43,7 +43,7 @@ use pallet_parachain_staking::{InflationInfo, Range}; use sp_core::H256; use sp_runtime::{ - traits::{AccountIdConversion, BlakeTwo256, Hash, IdentityLookup}, + traits::{BlakeTwo256, Hash, IdentityLookup}, Perbill, Percent, }; use xcm::{ @@ -485,7 +485,7 @@ parameter_types! { /// Time in blocks until a collator is done unstaking pub UnstakeLockTime: BlockNumber = LeaveDelayRounds::get() * DefaultBlocksPerRound::get(); /// JumboShrimp CurrencyId - pub JumboShrimpCurrencyId: CalamariAssetId = JUMBO_ID; + pub JumboFarmingCurrencyID: CalamariAssetId = JUMBO_ID; /// Farming PoolId for JUMBO token pub JumboShrimpPoolId: PoolId = 0; } @@ -527,7 +527,7 @@ impl Config for Test { type DrawingInterval = DrawingInterval; type DrawingFreezeout = DrawingFreezeout; type UnstakeLockTime = UnstakeLockTime; - type JumboShrimpCurrencyId = JumboShrimpCurrencyId; + type JumboFarmingCurrencyID = JumboFarmingCurrencyID; type PoolId = JumboShrimpPoolId; type BalanceConversion = Balance; type WeightInfo = (); @@ -544,6 +544,8 @@ pub(crate) struct ExtBuilder { delegations: Vec<(AccountId, AccountId, Balance)>, // inflation config inflation: InflationInfo, + // enable farming + with_farming: bool, } impl Default for ExtBuilder { @@ -571,6 +573,7 @@ impl Default for ExtBuilder { max: Perbill::from_percent(5), }, }, + with_farming: false, } } } @@ -587,6 +590,11 @@ impl ExtBuilder { self } + pub(crate) fn with_farming(mut self) -> Self { + self.with_farming = true; + self + } + pub(crate) fn with_candidates(mut self, collators: Vec<(AccountId, Balance)>) -> Self { self.collators = collators; self @@ -619,6 +627,7 @@ impl ExtBuilder { min_deposit: 5_000 * KMA, min_withdraw: 5_000 * KMA, gas_reserve: 10_000 * KMA, + farming_pool_live: self.with_farming, } .assimilate_storage(&mut t) .expect("pallet_lottery's storage can be assimilated"); diff --git a/pallets/pallet-lottery/src/tests.rs b/pallets/pallet-lottery/src/tests.rs index 2edbdd809..bf5675f91 100644 --- a/pallets/pallet-lottery/src/tests.rs +++ b/pallets/pallet-lottery/src/tests.rs @@ -898,6 +898,7 @@ fn many_deposit_withdrawals_work() { (*EVE, HIGH_BALANCE), ]) .with_funded_lottery_account(HIGH_BALANCE) + .with_farming() .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); @@ -966,3 +967,59 @@ fn reward_collators_for_round(round: u32, collators: &[AccountId]) { pallet_parachain_staking::AwardedPts::::insert(round, c, 20); } } + +#[test] +fn farming_deposit_withdraw() { + let balance = 500_000_000 * UNIT; + let half_balance = 250_000_000 * UNIT; + let quarter_balance = 125_000_000 * UNIT; + ExtBuilder::default() + .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) + .with_candidates(vec![(*BOB, balance)]) + .with_funded_lottery_account(balance) + .with_farming() + .build() + .execute_with(|| { + assert!(HIGH_BALANCE > balance); + assert_eq!(0, Lottery::staked_collators(*BOB)); + assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); + let alice_post_deposit_balance = Balances::free_balance(*ALICE); + assert_eq!(balance, Lottery::staked_collators(*BOB)); + assert_eq!(balance, Lottery::total_pot()); + assert_eq!(balance, Lottery::sum_of_deposits()); + + assert_ok!(Lottery::request_withdraw( + Origin::signed(*ALICE), + half_balance + )); + // surplus = balance - half_balance = half_balance + assert_eq!(half_balance, Lottery::surplus_unstaking_balance()); + + roll_one_block(); + assert_ok!(Lottery::request_withdraw( + Origin::signed(*ALICE), + quarter_balance + )); + assert_eq!(balance, Lottery::staked_collators(*BOB)); + // surplus = half_balance - quarter_balance = quarter_balance + assert_eq!(quarter_balance, Lottery::surplus_unstaking_balance()); + + pallet_parachain_staking::AwardedPts::::insert(2, *BOB, 20); + roll_to_round_begin(3); + // funds should be unlocked now and BOB is finished unstaking, so it's eligible for redepositing + assert_ok!(Lottery::draw_lottery(RawOrigin::Root.into())); + assert_eq!( + alice_post_deposit_balance + half_balance + quarter_balance, + Balances::free_balance(*ALICE) + ); + assert_eq!(0, Lottery::surplus_unstaking_balance()); + assert_eq!(0, Lottery::unlocked_unstaking_funds()); + assert!(Lottery::withdrawal_request_queue().is_empty()); + assert!(crate::UnstakingCollators::::get().is_empty()); + // draw lottery rebalance will restake surplus funds to collators. + assert_eq!(crate::StakedCollators::::iter().count(), 1); + assert_eq!(quarter_balance, Lottery::staked_collators(*BOB)); + assert_eq!(quarter_balance, Lottery::total_pot()); + assert_eq!(quarter_balance, Lottery::sum_of_deposits()); + }); +} diff --git a/runtime/calamari/src/lib.rs b/runtime/calamari/src/lib.rs index d6c3a4773..9080e914f 100644 --- a/runtime/calamari/src/lib.rs +++ b/runtime/calamari/src/lib.rs @@ -448,7 +448,7 @@ parameter_types! { /// Time in blocks until a collator is done unstaking pub UnstakeLockTime: BlockNumber = LeaveDelayRounds::get() * DefaultBlocksPerRound::get(); /// JumboShrimp CurrencyId - pub JumboShrimpCurrencyId: CalamariAssetId = 8; + pub JumboFarmingCurrencyID: CalamariAssetId = 8; /// Farming PoolId for JUMBO token pub JumboShrimpPoolId: PoolId = 0; } @@ -464,7 +464,7 @@ impl pallet_lottery::Config for Runtime { type DrawingInterval = DrawingInterval; type DrawingFreezeout = DrawingFreezeout; type UnstakeLockTime = UnstakeLockTime; - type JumboShrimpCurrencyId = JumboShrimpCurrencyId; + type JumboFarmingCurrencyID = JumboFarmingCurrencyID; type PoolId = JumboShrimpPoolId; type BalanceConversion = Balance; type WeightInfo = weights::pallet_lottery::SubstrateWeight; diff --git a/runtime/manta/src/lib.rs b/runtime/manta/src/lib.rs index 4acad2813..0dcd02dad 100644 --- a/runtime/manta/src/lib.rs +++ b/runtime/manta/src/lib.rs @@ -411,7 +411,7 @@ parameter_types! { /// Time in blocks until a collator is done unstaking pub UnstakeLockTime: BlockNumber = LeaveDelayRounds::get() * DefaultBlocksPerRound::get(); /// JumboShrimp CurrencyId - pub JumboShrimpCurrencyId: MantaAssetId = 8; + pub JumboFarmingCurrencyID: MantaAssetId = 8; /// Farming PoolId for JUMBO token pub JumboShrimpPoolId: PoolId = 0; } @@ -427,7 +427,7 @@ impl pallet_lottery::Config for Runtime { type DrawingInterval = DrawingInterval; type DrawingFreezeout = DrawingFreezeout; type UnstakeLockTime = UnstakeLockTime; - type JumboShrimpCurrencyId = JumboShrimpCurrencyId; + type JumboFarmingCurrencyID = JumboFarmingCurrencyID; type PoolId = JumboShrimpPoolId; type BalanceConversion = Balance; type WeightInfo = weights::pallet_lottery::SubstrateWeight; From b68658e8a7f24710aadc45fdcd877eae2ae3946f Mon Sep 17 00:00:00 2001 From: Charles Ferrell Date: Thu, 16 Nov 2023 19:10:25 -0500 Subject: [PATCH 05/12] add to tests Signed-off-by: Charles Ferrell --- pallets/pallet-lottery/src/mock.rs | 40 +++++++++++++++++++++++------ pallets/pallet-lottery/src/tests.rs | 23 +++++++++++++++-- 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/pallets/pallet-lottery/src/mock.rs b/pallets/pallet-lottery/src/mock.rs index a14bfc15b..dcaf5a0b4 100644 --- a/pallets/pallet-lottery/src/mock.rs +++ b/pallets/pallet-lottery/src/mock.rs @@ -43,7 +43,7 @@ use pallet_parachain_staking::{InflationInfo, Range}; use sp_core::H256; use sp_runtime::{ - traits::{BlakeTwo256, Hash, IdentityLookup}, + traits::{AccountIdConversion, BlakeTwo256, Hash, IdentityLookup}, Perbill, Percent, }; use xcm::{ @@ -59,7 +59,9 @@ pub const ALICE: AccountId = 1; pub const BOB: AccountId = 2; pub const TREASURY_ACCOUNT: AccountId = 10; pub const JUMBO: Balance = 1_000_000_000_000; -pub const JUMBO_ID: CalamariAssetId = 8; +pub const MANTA_ID: CalamariAssetId = 1; +pub const V_MANTA_ID: CalamariAssetId = 8; +pub const JUMBO_ID: CalamariAssetId = 9; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -485,7 +487,7 @@ parameter_types! { /// Time in blocks until a collator is done unstaking pub UnstakeLockTime: BlockNumber = LeaveDelayRounds::get() * DefaultBlocksPerRound::get(); /// JumboShrimp CurrencyId - pub JumboFarmingCurrencyID: CalamariAssetId = JUMBO_ID; + pub JumboFarmingCurrencyID: CalamariAssetId = V_MANTA_ID; /// Farming PoolId for JUMBO token pub JumboShrimpPoolId: PoolId = 0; } @@ -641,13 +643,25 @@ impl ExtBuilder { ext.execute_with(|| System::set_block_number(1)); ext.execute_with(|| { + let v_manta_asset_metadata = + create_asset_metadata("vManta", "vMANTA", 12, 1u128, false, true); let jumbo_asset_metadata = create_asset_metadata("Jumbo", "JUMBO", 12, 1u128, false, true); + let v_manta_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::new( + 1, + Junctions::Here, + ))); let native_location = AssetLocation(VersionedMultiLocation::V1(MultiLocation::new( 0, Junctions::Here, ))); - // registering manta native asset should work. + // register vMANTA and JUMBO asset should work. + AssetManager::register_asset( + RuntimeOrigin::root(), + v_manta_location, + v_manta_asset_metadata, + ) + .unwrap(); AssetManager::register_asset( RuntimeOrigin::root(), native_location, @@ -655,6 +669,14 @@ impl ExtBuilder { ) .unwrap(); + assert_ok!( + >::FungibleLedger::deposit_minting( + V_MANTA_ID, + &TREASURY_ACCOUNT, + 1_000 * JUMBO + ) + ); + assert_ok!( >::FungibleLedger::deposit_minting( JUMBO_ID, @@ -662,6 +684,7 @@ impl ExtBuilder { 1_000 * JUMBO ) ); + assert_ok!( >::FungibleLedger::deposit_minting( JUMBO_ID, @@ -669,11 +692,12 @@ impl ExtBuilder { 1_000 * JUMBO ) ); + assert_ok!( >::FungibleLedger::deposit_minting( - JUMBO_ID, - &BOB, - 1_000_000 * JUMBO + V_MANTA_ID, + &ALICE, + 1_000 * JUMBO ) ); @@ -685,7 +709,7 @@ impl ExtBuilder { } fn init_jumbo_farming() { - let tokens_proportion = vec![(JUMBO_ID, Perbill::from_percent(100))]; + let tokens_proportion = vec![(V_MANTA_ID, Perbill::from_percent(100))]; let tokens = JUMBO; let basic_rewards = vec![(JUMBO_ID, JUMBO)]; diff --git a/pallets/pallet-lottery/src/tests.rs b/pallets/pallet-lottery/src/tests.rs index bf5675f91..7bda1ec29 100644 --- a/pallets/pallet-lottery/src/tests.rs +++ b/pallets/pallet-lottery/src/tests.rs @@ -20,7 +20,7 @@ use crate::{ roll_one_block, roll_to, roll_to_round_begin, roll_to_round_end, AccountId, Balance, Balances, ExtBuilder, Lottery, ParachainStaking, RuntimeOrigin as Origin, System, Test, }, - Config, Error, + Config, DestroyFarmingToken, Error, MintFarmingToken, }; use frame_support::{assert_noop, assert_ok, traits::Currency}; @@ -898,7 +898,6 @@ fn many_deposit_withdrawals_work() { (*EVE, HIGH_BALANCE), ]) .with_funded_lottery_account(HIGH_BALANCE) - .with_farming() .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); @@ -968,6 +967,26 @@ fn reward_collators_for_round(round: u32, collators: &[AccountId]) { } } +#[test] +fn enable_farming_works() { + ExtBuilder::default().build().execute_with(|| { + assert!(!MintFarmingToken::::get()); + assert!(!DestroyFarmingToken::::get()); + assert_noop!( + Lottery::set_farming_params(Origin::signed(*BOB), true, true), + sp_runtime::DispatchError::BadOrigin + ); + + assert_ok!(Lottery::set_farming_params(Origin::root(), true, false)); + assert!(MintFarmingToken::::get()); + assert!(!DestroyFarmingToken::::get()); + + assert_ok!(Lottery::set_farming_params(Origin::root(), false, true)); + assert!(!MintFarmingToken::::get()); + assert!(DestroyFarmingToken::::get()); + }); +} + #[test] fn farming_deposit_withdraw() { let balance = 500_000_000 * UNIT; From c06b0e77c9e35634f690a8418100da41d312056d Mon Sep 17 00:00:00 2001 From: Charles Ferrell Date: Thu, 16 Nov 2023 19:18:57 -0500 Subject: [PATCH 06/12] taplo fmt Signed-off-by: Charles Ferrell --- pallets/pallet-lottery/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pallets/pallet-lottery/Cargo.toml b/pallets/pallet-lottery/Cargo.toml index 7670c5a10..62b6438db 100644 --- a/pallets/pallet-lottery/Cargo.toml +++ b/pallets/pallet-lottery/Cargo.toml @@ -18,6 +18,7 @@ scale-info = { version = "2.1.2", default-features = false, features = ["derive" # Substrate dependencies frame-support = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" } frame-system = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" } +orml-traits = { git = "https://github.com/manta-network/open-runtime-module-library.git", branch = "polkadot-v0.9.37", default-features = false } sp-api = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" } sp-arithmetic = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" } sp-blockchain = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37", optional = true } @@ -25,14 +26,13 @@ sp-core = { git = 'https://github.com/paritytech/substrate.git', default-feature sp-io = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" } sp-runtime = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" } sp-std = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" } -orml-traits = { git = "https://github.com/manta-network/open-runtime-module-library.git", branch = "polkadot-v0.9.37", default-features = false } # Self dependencies manta-primitives = { path = "../../primitives/manta", default-features = false } +pallet-farming = { path = '../farming', default-features = false } pallet-parachain-staking = { path = '../parachain-staking', default-features = false } runtime-common = { path = "../../runtime/common", default-features = false } session-key-primitives = { path = '../../primitives/session-keys', default-features = false } -pallet-farming = { path = '../farming', default-features = false } # Benchmarking dependencies frame-benchmarking = { git = 'https://github.com/paritytech/substrate.git', branch = "polkadot-v0.9.37", default-features = false, optional = true } @@ -40,9 +40,9 @@ rand = { version = "0.8.5", default-features = false, optional = true } [dev-dependencies] calamari-runtime = { path = "../../runtime/calamari", default-features = false } -pallet-asset-manager = { path = "../asset-manager", default-features = false } lazy_static = "1.4.0" manta-collator-selection = { path = "../collator-selection", default-features = false } +pallet-asset-manager = { path = "../asset-manager", default-features = false } pallet-assets = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" } pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" } pallet-preimage = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" } From d546116cb3d4e6d071d47cf23913edb570fa1b09 Mon Sep 17 00:00:00 2001 From: Charles Ferrell Date: Fri, 17 Nov 2023 18:42:28 -0500 Subject: [PATCH 07/12] make farming params dynamic via governance Signed-off-by: Charles Ferrell --- Cargo.lock | 1 + node/src/chain_specs/calamari.rs | 1 + node/src/chain_specs/manta/mod.rs | 1 + pallets/pallet-lottery/Cargo.toml | 3 ++ pallets/pallet-lottery/src/lib.rs | 61 +++++++++++++++++++---------- pallets/pallet-lottery/src/mock.rs | 22 +++++++---- pallets/pallet-lottery/src/tests.rs | 36 ++++++++++++----- runtime/calamari/src/lib.rs | 6 --- runtime/manta/src/lib.rs | 6 --- 9 files changed, 87 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a0396c1fc..5d8a6a67c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7016,6 +7016,7 @@ dependencies = [ "rand 0.8.5", "runtime-common", "scale-info", + "serde", "session-key-primitives", "similar-asserts", "sp-api", diff --git a/node/src/chain_specs/calamari.rs b/node/src/chain_specs/calamari.rs index f8ad38a72..3f7685d4e 100644 --- a/node/src/chain_specs/calamari.rs +++ b/node/src/chain_specs/calamari.rs @@ -238,6 +238,7 @@ fn calamari_dev_genesis( min_deposit: 5_000 * KMA, min_withdraw: 5_000 * KMA, gas_reserve: 10_000 * KMA, + farming_pool_params: Default::default(), }, } } diff --git a/node/src/chain_specs/manta/mod.rs b/node/src/chain_specs/manta/mod.rs index e26fa7601..1211d32f9 100644 --- a/node/src/chain_specs/manta/mod.rs +++ b/node/src/chain_specs/manta/mod.rs @@ -130,6 +130,7 @@ fn manta_devnet_genesis(genesis_collators: Vec) -> GenesisConfig { min_deposit: 500 * MANTA, min_withdraw: 10 * MANTA, gas_reserve: 1_000 * MANTA, + farming_pool_params: Default::default(), }, parachain_info: manta_runtime::ParachainInfoConfig { parachain_id: MANTA_PARACHAIN_ID.into(), diff --git a/pallets/pallet-lottery/Cargo.toml b/pallets/pallet-lottery/Cargo.toml index 62b6438db..93a9e5430 100644 --- a/pallets/pallet-lottery/Cargo.toml +++ b/pallets/pallet-lottery/Cargo.toml @@ -14,6 +14,7 @@ function_name = "0.3" jsonrpsee = { version = "0.16.2", features = ["server", "macros"], optional = true } log = { version = "0.4.0", default-features = false } scale-info = { version = "2.1.2", default-features = false, features = ["derive"] } +serde = { version = "1.0.136", default-features = false, optional = true } # Substrate dependencies frame-support = { git = 'https://github.com/paritytech/substrate.git', default-features = false, branch = "polkadot-v0.9.37" } @@ -80,6 +81,8 @@ std = [ 'frame-benchmarking/std', "frame-support/std", "frame-system/std", + "serde/std", + "pallet-farming/std", ] try-runtime = [ "frame-support/try-runtime", diff --git a/pallets/pallet-lottery/src/lib.rs b/pallets/pallet-lottery/src/lib.rs index afa264732..23f1dcc06 100644 --- a/pallets/pallet-lottery/src/lib.rs +++ b/pallets/pallet-lottery/src/lib.rs @@ -107,6 +107,8 @@ pub mod pallet { use manta_primitives::types::PoolId; use orml_traits::MultiCurrency; use pallet_parachain_staking::BalanceOf; + #[cfg(feature = "std")] + use serde::{Deserialize, Serialize}; use sp_arithmetic::traits::SaturatedConversion; use sp_core::U256; use sp_runtime::{ @@ -135,10 +137,6 @@ pub mod pallet { Self::PalletsOrigin, Hash = Self::Hash, >; - /// CurrencyId for the JUMBO token - type JumboFarmingCurrencyID: Get<::CurrencyId>; - /// PoolId for JumboShrimp Farming Pool - type PoolId: Get; /// Helper to convert between Balance types of `MultiCurrency` and `Currency` (most likely equivalent types in runtime) type BalanceConversion: Copy + Into< @@ -280,13 +278,20 @@ pub mod pallet { pub(super) type StakedCollators = StorageMap<_, Blake2_128Concat, T::AccountId, BalanceOf, ValueQuery>; - /// Boolean for the minting of a farming token on `deposit` call - #[pallet::storage] - pub(super) type MintFarmingToken = StorageValue<_, bool, ValueQuery>; + #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] + #[derive(Clone, Copy, Encode, Decode, TypeInfo, Default)] + pub struct FarmingParams { + pub mint_farming_token: bool, + pub destroy_farming_token: bool, + pub pool_id: PoolId, + pub currency_id: T, + } - /// Requires the burning of a farming token when withdrawing from lottery when value is `true` + pub type FarmingParamsOf = FarmingParams<::CurrencyId>; + + /// Boolean for the minting of a farming token on `deposit` call #[pallet::storage] - pub(super) type DestroyFarmingToken = StorageValue<_, bool, ValueQuery>; + pub(super) type FarmingParameters = StorageValue<_, FarmingParamsOf, ValueQuery>; #[pallet::genesis_config] pub struct GenesisConfig { @@ -294,7 +299,7 @@ pub mod pallet { pub gas_reserve: BalanceOf, pub min_deposit: BalanceOf, pub min_withdraw: BalanceOf, - pub farming_pool_live: bool, + pub farming_pool_params: FarmingParamsOf, } #[cfg(feature = "std")] @@ -304,7 +309,12 @@ pub mod pallet { min_deposit: 1u32.into(), min_withdraw: 1u32.into(), gas_reserve: 10_000u32.into(), - farming_pool_live: false, + farming_pool_params: FarmingParamsOf:: { + mint_farming_token: false, + destroy_farming_token: false, + pool_id: 0, + currency_id: ::CurrencyId::default(), + }, } } } @@ -316,8 +326,7 @@ pub mod pallet { GasReserve::::set(self.gas_reserve); MinDeposit::::set(self.min_deposit); MinWithdraw::::set(self.min_withdraw); - MintFarmingToken::::set(self.farming_pool_live); - MintFarmingToken::::set(self.farming_pool_live); + FarmingParameters::::set(self.farming_pool_params); } } @@ -421,17 +430,18 @@ pub mod pallet { Error::::PalletMisconfigured }; - if MintFarmingToken::::get() { + let farming_params = FarmingParameters::::get(); + if farming_params.mint_farming_token { // mint JUMBO token and put it in farming pool let convert_amount: T::BalanceConversion = amount.into(); ::MultiCurrency::deposit( - T::JumboFarmingCurrencyID::get(), + farming_params.currency_id, &caller_account, convert_amount.into(), )?; pallet_farming::Pallet::::deposit_farming( caller_account.clone(), - T::PoolId::get(), + farming_params.pool_id, convert_amount.into(), None, )?; @@ -505,15 +515,16 @@ pub mod pallet { Error::::TooCloseToDrawing ); - if DestroyFarmingToken::::get() { + let farming_params = FarmingParameters::::get(); + if farming_params.destroy_farming_token { let convert_amount: T::BalanceConversion = amount.into(); pallet_farming::Pallet::::withdraw_and_unstake( caller.clone(), - T::PoolId::get(), + farming_params.pool_id, Some(convert_amount.into()), )?; ::MultiCurrency::withdraw( - T::JumboFarmingCurrencyID::get(), + farming_params.currency_id, &caller, convert_amount.into(), )?; @@ -913,11 +924,19 @@ pub mod pallet { origin: OriginFor, mint_farming_token: bool, burn_farming_token: bool, + pool_id: PoolId, + currency_id: ::CurrencyId, ) -> DispatchResult { T::ManageOrigin::ensure_origin(origin)?; - MintFarmingToken::::set(mint_farming_token); - DestroyFarmingToken::::set(burn_farming_token); + let farming_params = FarmingParamsOf:: { + mint_farming_token, + destroy_farming_token: burn_farming_token, + pool_id, + currency_id, + }; + FarmingParameters::::set(farming_params); + Ok(()) } } diff --git a/pallets/pallet-lottery/src/mock.rs b/pallets/pallet-lottery/src/mock.rs index dcaf5a0b4..a25d08349 100644 --- a/pallets/pallet-lottery/src/mock.rs +++ b/pallets/pallet-lottery/src/mock.rs @@ -18,7 +18,7 @@ use core::marker::PhantomData; use crate as pallet_lottery; -use crate::{pallet, Config}; +use crate::{pallet, Config, FarmingParamsOf}; use calamari_runtime::currency::KMA; use frame_support::{ assert_ok, construct_runtime, ord_parameter_types, @@ -43,7 +43,7 @@ use pallet_parachain_staking::{InflationInfo, Range}; use sp_core::H256; use sp_runtime::{ - traits::{AccountIdConversion, BlakeTwo256, Hash, IdentityLookup}, + traits::{BlakeTwo256, Hash, IdentityLookup}, Perbill, Percent, }; use xcm::{ @@ -56,10 +56,8 @@ pub type AccountId = u64; pub type Balance = u128; pub const ALICE: AccountId = 1; -pub const BOB: AccountId = 2; pub const TREASURY_ACCOUNT: AccountId = 10; pub const JUMBO: Balance = 1_000_000_000_000; -pub const MANTA_ID: CalamariAssetId = 1; pub const V_MANTA_ID: CalamariAssetId = 8; pub const JUMBO_ID: CalamariAssetId = 9; @@ -529,8 +527,6 @@ impl Config for Test { type DrawingInterval = DrawingInterval; type DrawingFreezeout = DrawingFreezeout; type UnstakeLockTime = UnstakeLockTime; - type JumboFarmingCurrencyID = JumboFarmingCurrencyID; - type PoolId = JumboShrimpPoolId; type BalanceConversion = Balance; type WeightInfo = (); } @@ -625,11 +621,23 @@ impl ExtBuilder { } .assimilate_storage(&mut t) .expect("Parachain Staking's storage can be assimilated"); + + let farming_params = if self.with_farming { + FarmingParamsOf:: { + mint_farming_token: true, + destroy_farming_token: true, + pool_id: 0, + currency_id: 8, + } + } else { + FarmingParamsOf::::default() + }; + pallet_lottery::GenesisConfig:: { min_deposit: 5_000 * KMA, min_withdraw: 5_000 * KMA, gas_reserve: 10_000 * KMA, - farming_pool_live: self.with_farming, + farming_pool_params: farming_params, } .assimilate_storage(&mut t) .expect("pallet_lottery's storage can be assimilated"); diff --git a/pallets/pallet-lottery/src/tests.rs b/pallets/pallet-lottery/src/tests.rs index 7bda1ec29..41bd3c9d4 100644 --- a/pallets/pallet-lottery/src/tests.rs +++ b/pallets/pallet-lottery/src/tests.rs @@ -20,7 +20,7 @@ use crate::{ roll_one_block, roll_to, roll_to_round_begin, roll_to_round_end, AccountId, Balance, Balances, ExtBuilder, Lottery, ParachainStaking, RuntimeOrigin as Origin, System, Test, }, - Config, DestroyFarmingToken, Error, MintFarmingToken, + Config, Error, FarmingParameters, }; use frame_support::{assert_noop, assert_ok, traits::Currency}; @@ -970,20 +970,36 @@ fn reward_collators_for_round(round: u32, collators: &[AccountId]) { #[test] fn enable_farming_works() { ExtBuilder::default().build().execute_with(|| { - assert!(!MintFarmingToken::::get()); - assert!(!DestroyFarmingToken::::get()); + let farming_params = FarmingParameters::::get(); + assert!(!farming_params.mint_farming_token); + assert!(!farming_params.destroy_farming_token); + assert_eq!(farming_params.currency_id, 0); + assert_eq!(farming_params.pool_id, 0); + assert_noop!( - Lottery::set_farming_params(Origin::signed(*BOB), true, true), + Lottery::set_farming_params(Origin::signed(*BOB), true, true, 1, 1), sp_runtime::DispatchError::BadOrigin ); - assert_ok!(Lottery::set_farming_params(Origin::root(), true, false)); - assert!(MintFarmingToken::::get()); - assert!(!DestroyFarmingToken::::get()); + let farming_params = FarmingParameters::::get(); + assert!(!farming_params.mint_farming_token); + assert!(!farming_params.destroy_farming_token); + assert_eq!(farming_params.currency_id, 0); + assert_eq!(farming_params.pool_id, 0); + + assert_ok!(Lottery::set_farming_params( + Origin::root(), + true, + true, + 1, + 1 + )); - assert_ok!(Lottery::set_farming_params(Origin::root(), false, true)); - assert!(!MintFarmingToken::::get()); - assert!(DestroyFarmingToken::::get()); + let farming_params = FarmingParameters::::get(); + assert!(farming_params.mint_farming_token); + assert!(farming_params.destroy_farming_token); + assert_eq!(farming_params.currency_id, 1); + assert_eq!(farming_params.pool_id, 1); }); } diff --git a/runtime/calamari/src/lib.rs b/runtime/calamari/src/lib.rs index 9080e914f..e71cefd03 100644 --- a/runtime/calamari/src/lib.rs +++ b/runtime/calamari/src/lib.rs @@ -447,10 +447,6 @@ parameter_types! { pub DrawingFreezeout: BlockNumber = prod_or_fast!(1 * DAYS, 1 * MINUTES); /// Time in blocks until a collator is done unstaking pub UnstakeLockTime: BlockNumber = LeaveDelayRounds::get() * DefaultBlocksPerRound::get(); - /// JumboShrimp CurrencyId - pub JumboFarmingCurrencyID: CalamariAssetId = 8; - /// Farming PoolId for JUMBO token - pub JumboShrimpPoolId: PoolId = 0; } impl pallet_lottery::Config for Runtime { type RuntimeCall = RuntimeCall; @@ -464,8 +460,6 @@ impl pallet_lottery::Config for Runtime { type DrawingInterval = DrawingInterval; type DrawingFreezeout = DrawingFreezeout; type UnstakeLockTime = UnstakeLockTime; - type JumboFarmingCurrencyID = JumboFarmingCurrencyID; - type PoolId = JumboShrimpPoolId; type BalanceConversion = Balance; type WeightInfo = weights::pallet_lottery::SubstrateWeight; } diff --git a/runtime/manta/src/lib.rs b/runtime/manta/src/lib.rs index 0dcd02dad..3ce56d419 100644 --- a/runtime/manta/src/lib.rs +++ b/runtime/manta/src/lib.rs @@ -410,10 +410,6 @@ parameter_types! { pub DrawingFreezeout: BlockNumber = prod_or_fast!(1 * DAYS, 1 * MINUTES); /// Time in blocks until a collator is done unstaking pub UnstakeLockTime: BlockNumber = LeaveDelayRounds::get() * DefaultBlocksPerRound::get(); - /// JumboShrimp CurrencyId - pub JumboFarmingCurrencyID: MantaAssetId = 8; - /// Farming PoolId for JUMBO token - pub JumboShrimpPoolId: PoolId = 0; } impl pallet_lottery::Config for Runtime { type RuntimeCall = RuntimeCall; @@ -427,8 +423,6 @@ impl pallet_lottery::Config for Runtime { type DrawingInterval = DrawingInterval; type DrawingFreezeout = DrawingFreezeout; type UnstakeLockTime = UnstakeLockTime; - type JumboFarmingCurrencyID = JumboFarmingCurrencyID; - type PoolId = JumboShrimpPoolId; type BalanceConversion = Balance; type WeightInfo = weights::pallet_lottery::SubstrateWeight; } From cfa5224807373f757f4fd3a8110db98edeada729 Mon Sep 17 00:00:00 2001 From: Charles Ferrell Date: Fri, 17 Nov 2023 19:14:22 -0500 Subject: [PATCH 08/12] tests and refactor lazy static out Signed-off-by: Charles Ferrell --- Cargo.lock | 1 - pallets/pallet-lottery/Cargo.toml | 1 - pallets/pallet-lottery/src/mock.rs | 30 +-- pallets/pallet-lottery/src/tests.rs | 382 ++++++++++++++-------------- 4 files changed, 191 insertions(+), 223 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5d8a6a67c..050ff5c73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6998,7 +6998,6 @@ dependencies = [ "frame-system", "function_name", "jsonrpsee", - "lazy_static", "log", "manta-collator-selection", "manta-primitives", diff --git a/pallets/pallet-lottery/Cargo.toml b/pallets/pallet-lottery/Cargo.toml index 93a9e5430..f27b6df4d 100644 --- a/pallets/pallet-lottery/Cargo.toml +++ b/pallets/pallet-lottery/Cargo.toml @@ -41,7 +41,6 @@ rand = { version = "0.8.5", default-features = false, optional = true } [dev-dependencies] calamari-runtime = { path = "../../runtime/calamari", default-features = false } -lazy_static = "1.4.0" manta-collator-selection = { path = "../collator-selection", default-features = false } pallet-asset-manager = { path = "../asset-manager", default-features = false } pallet-assets = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.37" } diff --git a/pallets/pallet-lottery/src/mock.rs b/pallets/pallet-lottery/src/mock.rs index a25d08349..28c12fe45 100644 --- a/pallets/pallet-lottery/src/mock.rs +++ b/pallets/pallet-lottery/src/mock.rs @@ -37,7 +37,7 @@ use manta_primitives::{ }, constants::ASSET_MANAGER_PALLET_ID, currencies::Currencies, - types::{BlockNumber, CalamariAssetId, Header, PoolId}, + types::{BlockNumber, CalamariAssetId, Header}, }; use pallet_parachain_staking::{InflationInfo, Range}; use sp_core::H256; @@ -56,6 +56,10 @@ pub type AccountId = u64; pub type Balance = u128; pub const ALICE: AccountId = 1; +pub const BOB: AccountId = 2; +pub const CHARLIE: AccountId = 3; +pub const DAVE: AccountId = 4; +pub const EVE: AccountId = 5; pub const TREASURY_ACCOUNT: AccountId = 10; pub const JUMBO: Balance = 1_000_000_000_000; pub const V_MANTA_ID: CalamariAssetId = 8; @@ -484,10 +488,6 @@ parameter_types! { pub DrawingFreezeout: BlockNumber = 5; /// Time in blocks until a collator is done unstaking pub UnstakeLockTime: BlockNumber = LeaveDelayRounds::get() * DefaultBlocksPerRound::get(); - /// JumboShrimp CurrencyId - pub JumboFarmingCurrencyID: CalamariAssetId = V_MANTA_ID; - /// Farming PoolId for JUMBO token - pub JumboShrimpPoolId: PoolId = 0; } use frame_support::traits::Currency; @@ -677,22 +677,6 @@ impl ExtBuilder { ) .unwrap(); - assert_ok!( - >::FungibleLedger::deposit_minting( - V_MANTA_ID, - &TREASURY_ACCOUNT, - 1_000 * JUMBO - ) - ); - - assert_ok!( - >::FungibleLedger::deposit_minting( - JUMBO_ID, - &TREASURY_ACCOUNT, - 1_000 * JUMBO - ) - ); - assert_ok!( >::FungibleLedger::deposit_minting( JUMBO_ID, @@ -703,9 +687,7 @@ impl ExtBuilder { assert_ok!( >::FungibleLedger::deposit_minting( - V_MANTA_ID, - &ALICE, - 1_000 * JUMBO + V_MANTA_ID, &ALICE, JUMBO ) ); diff --git a/pallets/pallet-lottery/src/tests.rs b/pallets/pallet-lottery/src/tests.rs index 41bd3c9d4..d9fbe9fd0 100644 --- a/pallets/pallet-lottery/src/tests.rs +++ b/pallets/pallet-lottery/src/tests.rs @@ -17,8 +17,9 @@ use crate::{ assert_last_event, mock::{ - roll_one_block, roll_to, roll_to_round_begin, roll_to_round_end, AccountId, Balance, - Balances, ExtBuilder, Lottery, ParachainStaking, RuntimeOrigin as Origin, System, Test, + roll_one_block, roll_to, roll_to_round_begin, roll_to_round_end, AccountId, Assets, + Balance, Balances, ExtBuilder, Lottery, ParachainStaking, RuntimeOrigin as Origin, System, + Test, ALICE, BOB, CHARLIE, DAVE, EVE, TREASURY_ACCOUNT, V_MANTA_ID, }, Config, Error, FarmingParameters, }; @@ -26,14 +27,6 @@ use crate::{ use frame_support::{assert_noop, assert_ok, traits::Currency}; use frame_system::RawOrigin; -lazy_static::lazy_static! { - pub(crate) static ref ALICE: AccountId = 1; - pub(crate) static ref BOB: AccountId = 2; - pub(crate) static ref CHARLIE: AccountId =3; - pub(crate) static ref DAVE: AccountId =4; - pub(crate) static ref EVE: AccountId =5; -} - const UNIT: Balance = 1_000_000_000_000; const HIGH_BALANCE: Balance = 1_000_000_000 * UNIT; @@ -120,13 +113,13 @@ fn restarting_funded_lottery_should_work() { fn depositing_and_withdrawing_in_freezeout_should_not_work() { let balance = 300_000_000 * UNIT; ExtBuilder::default() - .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) - .with_candidates(vec![(*BOB, balance)]) + .with_balances(vec![(ALICE, HIGH_BALANCE), (BOB, HIGH_BALANCE)]) + .with_candidates(vec![(BOB, balance)]) .with_funded_lottery_account(HIGH_BALANCE) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); assert_eq!(Lottery::sum_of_deposits(), balance); assert_eq!(Lottery::total_pot(), balance); assert_ok!(Lottery::start_lottery(RawOrigin::Root.into(),)); @@ -136,11 +129,11 @@ fn depositing_and_withdrawing_in_freezeout_should_not_work() { ); assert!(!Lottery::not_in_drawing_freezeout()); assert_noop!( - Lottery::deposit(Origin::signed(*ALICE), balance), + Lottery::deposit(Origin::signed(ALICE), balance), Error::::TooCloseToDrawing ); assert_noop!( - Lottery::request_withdraw(Origin::signed(*ALICE), balance), + Lottery::request_withdraw(Origin::signed(ALICE), balance), Error::::TooCloseToDrawing ); assert_eq!(Lottery::sum_of_deposits(), balance); @@ -152,32 +145,32 @@ fn depositing_and_withdrawing_in_freezeout_should_not_work() { fn depositing_and_withdrawing_should_work() { let balance = 500_000_000 * UNIT; ExtBuilder::default() - .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) - .with_candidates(vec![(*BOB, balance)]) + .with_balances(vec![(ALICE, HIGH_BALANCE), (BOB, HIGH_BALANCE)]) + .with_candidates(vec![(BOB, balance)]) .with_funded_lottery_account(HIGH_BALANCE) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); assert_last_event!(crate::mock::RuntimeEvent::Lottery( crate::Event::Deposited { - account: *ALICE, + account: ALICE, amount: balance } )); - assert_eq!(Lottery::active_balance_per_user(*ALICE), balance); + assert_eq!(Lottery::active_balance_per_user(ALICE), balance); assert_eq!(Lottery::sum_of_deposits(), balance); assert_eq!(Lottery::total_pot(), balance); - assert_ok!(Lottery::request_withdraw(Origin::signed(*ALICE), balance)); + assert_ok!(Lottery::request_withdraw(Origin::signed(ALICE), balance)); assert_last_event!(crate::mock::RuntimeEvent::Lottery( crate::Event::ScheduledWithdraw { - account: *ALICE, + account: ALICE, amount: balance } )); assert_eq!(Lottery::sum_of_deposits(), balance); - assert_eq!(Lottery::active_balance_per_user(*ALICE), 0); + assert_eq!(Lottery::active_balance_per_user(ALICE), 0); assert_eq!(Lottery::total_pot(), 0); assert_eq!(Lottery::withdrawal_request_queue().len(), 1); assert_eq!(Lottery::surplus_unstaking_balance(), 0); @@ -189,54 +182,54 @@ fn depositing_and_withdrawing_partial_in_one_block_should_work() { let balance = 500_000_000 * UNIT; let half_balance = 250_000_000 * UNIT; ExtBuilder::default() - .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) - .with_candidates(vec![(*BOB, balance)]) + .with_balances(vec![(ALICE, HIGH_BALANCE), (BOB, HIGH_BALANCE)]) + .with_candidates(vec![(BOB, balance)]) .with_funded_lottery_account(HIGH_BALANCE) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); - assert_eq!(Lottery::active_balance_per_user(*ALICE), balance); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); + assert_eq!(Lottery::active_balance_per_user(ALICE), balance); assert_eq!(Lottery::sum_of_deposits(), balance); assert_eq!(Lottery::total_pot(), balance); - assert_eq!(Lottery::staked_collators(*BOB), balance); + assert_eq!(Lottery::staked_collators(BOB), balance); assert_eq!(crate::UnstakingCollators::::get().len(), 0); assert_ok!(Lottery::request_withdraw( - Origin::signed(*ALICE), + Origin::signed(ALICE), half_balance )); assert_eq!(Lottery::sum_of_deposits(), balance); - assert_eq!(Lottery::active_balance_per_user(*ALICE), half_balance); + assert_eq!(Lottery::active_balance_per_user(ALICE), half_balance); assert_eq!(Lottery::total_pot(), half_balance); assert_eq!(Lottery::withdrawal_request_queue().len(), 1); assert_eq!(Lottery::surplus_unstaking_balance(), half_balance); assert_eq!(crate::UnstakingCollators::::get().len(), 1); - assert_eq!(Lottery::staked_collators(*BOB), balance); + assert_eq!(Lottery::staked_collators(BOB), balance); assert_ok!(Lottery::request_withdraw( - Origin::signed(*ALICE), + Origin::signed(ALICE), half_balance )); assert_eq!(Lottery::sum_of_deposits(), balance); - assert_eq!(Lottery::active_balance_per_user(*ALICE), 0); + assert_eq!(Lottery::active_balance_per_user(ALICE), 0); assert_eq!(Lottery::total_pot(), 0); assert_eq!(Lottery::withdrawal_request_queue().len(), 2); assert_eq!(Lottery::surplus_unstaking_balance(), 0); - assert_eq!(Lottery::staked_collators(*BOB), balance); + assert_eq!(Lottery::staked_collators(BOB), balance); assert_eq!(crate::UnstakingCollators::::get().len(), 1); assert_noop!( - Lottery::request_withdraw(Origin::signed(*ALICE), half_balance), + Lottery::request_withdraw(Origin::signed(ALICE), half_balance), Error::::NoDepositForAccount ); assert_noop!( - Lottery::deposit(Origin::signed(*ALICE), half_balance), + Lottery::deposit(Origin::signed(ALICE), half_balance), Error::::NoCollatorForDeposit ); assert_noop!( - Lottery::deposit(Origin::signed(*BOB), half_balance), + Lottery::deposit(Origin::signed(BOB), half_balance), Error::::NoCollatorForDeposit ); }); @@ -246,25 +239,25 @@ fn depositing_and_withdrawing_partial_in_one_block_should_work() { fn processing_withdrawing_leaves_correct_balance_with_user() { let balance = 500_000_000 * UNIT; ExtBuilder::default() - .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) - .with_candidates(vec![(*BOB, balance)]) + .with_balances(vec![(ALICE, HIGH_BALANCE), (BOB, HIGH_BALANCE)]) + .with_candidates(vec![(BOB, balance)]) .with_funded_lottery_account(HIGH_BALANCE) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); - let alice_starting_balance = Balances::free_balance(*ALICE); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); + let alice_starting_balance = Balances::free_balance(ALICE); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); assert_eq!( - Balances::free_balance(*ALICE), + Balances::free_balance(ALICE), alice_starting_balance - balance ); assert_eq!(Lottery::sum_of_deposits(), balance); assert_eq!(Lottery::total_pot(), balance); - assert_ok!(Lottery::request_withdraw(Origin::signed(*ALICE), balance)); + assert_ok!(Lottery::request_withdraw(Origin::signed(ALICE), balance)); assert_eq!(Lottery::sum_of_deposits(), balance); assert_eq!(Lottery::total_pot(), 0); - let alice_balance_after_request = Balances::free_balance(*ALICE); + let alice_balance_after_request = Balances::free_balance(ALICE); assert_eq!( alice_balance_after_request, alice_starting_balance - balance @@ -275,10 +268,10 @@ fn processing_withdrawing_leaves_correct_balance_with_user() { assert_ok!(Lottery::process_matured_withdrawals(RawOrigin::Root.into())); assert_eq!(Lottery::sum_of_deposits(), 0); assert_eq!( - Balances::free_balance(*ALICE), + Balances::free_balance(ALICE), alice_balance_after_request + balance ); - assert_eq!(Balances::free_balance(*ALICE), alice_starting_balance); + assert_eq!(Balances::free_balance(ALICE), alice_starting_balance); assert_eq!(Lottery::withdrawal_request_queue().len(), 0); assert_eq!(Lottery::unlocked_unstaking_funds(), 0); }); @@ -289,16 +282,16 @@ fn multiple_request_withdraw_processing_withdrawing_leaves_correct_balance_with_ let balance = 500_000_000 * UNIT; let one = 100_000_000 * UNIT; ExtBuilder::default() - .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) - .with_candidates(vec![(*BOB, balance)]) + .with_balances(vec![(ALICE, HIGH_BALANCE), (BOB, HIGH_BALANCE)]) + .with_candidates(vec![(BOB, balance)]) .with_funded_lottery_account(HIGH_BALANCE) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); - let alice_starting_balance = Balances::free_balance(*ALICE); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); + let alice_starting_balance = Balances::free_balance(ALICE); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); assert_eq!( - Balances::free_balance(*ALICE), + Balances::free_balance(ALICE), alice_starting_balance - balance ); assert_eq!(Lottery::sum_of_deposits(), balance); @@ -306,13 +299,13 @@ fn multiple_request_withdraw_processing_withdrawing_leaves_correct_balance_with_ // request withdraw 5 times for i in 1..6 { - assert_ok!(Lottery::request_withdraw(Origin::signed(*ALICE), one)); + assert_ok!(Lottery::request_withdraw(Origin::signed(ALICE), one)); assert_eq!(Lottery::total_pot(), balance - i * one); } assert_eq!(Lottery::sum_of_deposits(), balance); assert_eq!(Lottery::total_pot(), 0); - let alice_balance_after_request = Balances::free_balance(*ALICE); + let alice_balance_after_request = Balances::free_balance(ALICE); assert_eq!( alice_balance_after_request, alice_starting_balance - balance @@ -323,10 +316,10 @@ fn multiple_request_withdraw_processing_withdrawing_leaves_correct_balance_with_ assert_ok!(Lottery::process_matured_withdrawals(RawOrigin::Root.into())); assert_eq!(Lottery::sum_of_deposits(), 0); assert_eq!( - Balances::free_balance(*ALICE), + Balances::free_balance(ALICE), alice_balance_after_request + balance ); - assert_eq!(Balances::free_balance(*ALICE), alice_starting_balance); + assert_eq!(Balances::free_balance(ALICE), alice_starting_balance); assert_eq!(Lottery::withdrawal_request_queue().len(), 0); assert_eq!(Lottery::unlocked_unstaking_funds(), 0); }); @@ -336,24 +329,24 @@ fn multiple_request_withdraw_processing_withdrawing_leaves_correct_balance_with_ fn double_processing_withdrawals_does_not_double_pay() { let balance = 500_000_000 * UNIT; ExtBuilder::default() - .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) - .with_candidates(vec![(*BOB, balance)]) + .with_balances(vec![(ALICE, HIGH_BALANCE), (BOB, HIGH_BALANCE)]) + .with_candidates(vec![(BOB, balance)]) .with_funded_lottery_account(HIGH_BALANCE) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); - assert_ok!(Lottery::request_withdraw(Origin::signed(*ALICE), balance)); - let alice_balance_after_request = Balances::free_balance(*ALICE); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); + assert_ok!(Lottery::request_withdraw(Origin::signed(ALICE), balance)); + let alice_balance_after_request = Balances::free_balance(ALICE); roll_to_round_begin(3); assert_ok!(Lottery::process_matured_withdrawals(RawOrigin::Root.into())); assert_eq!( - Balances::free_balance(*ALICE), + Balances::free_balance(ALICE), alice_balance_after_request + balance ); assert_ok!(Lottery::process_matured_withdrawals(RawOrigin::Root.into())); assert_eq!( - Balances::free_balance(*ALICE), + Balances::free_balance(ALICE), alice_balance_after_request + balance ); }); @@ -366,63 +359,59 @@ fn deposit_staking_to_one_underallocated_collator_works() { let balance6 = 60_000_000 * UNIT; ExtBuilder::default() .with_balances(vec![ - (*ALICE, HIGH_BALANCE), - (*BOB, HIGH_BALANCE), - (*CHARLIE, HIGH_BALANCE), + (ALICE, HIGH_BALANCE), + (BOB, HIGH_BALANCE), + (CHARLIE, HIGH_BALANCE), ]) .with_candidates(vec![ - (*ALICE, balance4), - (*BOB, balance5), - (*CHARLIE, balance6), + (ALICE, balance4), + (BOB, balance5), + (CHARLIE, balance6), ]) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance6 + balance5 + balance4); assert_eq!( - ParachainStaking::candidate_info(*ALICE) + ParachainStaking::candidate_info(ALICE) .unwrap() .total_counted, balance4 ); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance6)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance6)); // Median = 50k, ALICE is the only underallocated collator, gets all token assert_eq!( - ParachainStaking::candidate_info(*ALICE) + ParachainStaking::candidate_info(ALICE) .unwrap() .total_counted, balance4 + balance6 ); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance5)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance5)); // Median = 60k, BOB is the only underallocated, gets all token assert_eq!( - ParachainStaking::candidate_info(*BOB) - .unwrap() - .total_counted, + ParachainStaking::candidate_info(BOB).unwrap().total_counted, balance5 + balance5 ); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance4)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance4)); // Median = 100k CHARLIE is the only underallocated, gets all token assert_eq!( - ParachainStaking::candidate_info(*CHARLIE) + ParachainStaking::candidate_info(CHARLIE) .unwrap() .total_counted, balance6 + balance4 ); // Now all 3 tie at 100k, there is no underallocation, deposit is given randomly - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance6)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance6)); assert!( - (ParachainStaking::candidate_info(*ALICE) + (ParachainStaking::candidate_info(ALICE) .unwrap() .total_counted == balance4 + balance6 + balance6) - || (ParachainStaking::candidate_info(*BOB) - .unwrap() - .total_counted + || (ParachainStaking::candidate_info(BOB).unwrap().total_counted == balance5 + balance5 + balance6) - || (ParachainStaking::candidate_info(*CHARLIE) + || (ParachainStaking::candidate_info(CHARLIE) .unwrap() .total_counted == balance6 + balance4 + balance6), @@ -434,42 +423,40 @@ fn deposit_staking_to_one_underallocated_collator_works() { fn unstaking_works_with_zero_collators_left() { let balance = 50_000_000 * UNIT; ExtBuilder::default() - .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) - .with_candidates(vec![(*ALICE, balance), (*BOB, balance)]) + .with_balances(vec![(ALICE, HIGH_BALANCE), (BOB, HIGH_BALANCE)]) + .with_candidates(vec![(ALICE, balance), (BOB, balance)]) .with_funded_lottery_account(HIGH_BALANCE) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); assert_eq!( - ParachainStaking::candidate_info(*ALICE) + ParachainStaking::candidate_info(ALICE) .unwrap() .total_counted, balance ); assert_eq!(crate::StakedCollators::::iter().count(), 0); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); assert_eq!(crate::StakedCollators::::iter().count(), 2); - assert_eq!(Balances::free_balance(*ALICE), HIGH_BALANCE - 2 * balance); + assert_eq!(Balances::free_balance(ALICE), HIGH_BALANCE - 2 * balance); assert_eq!( Balances::free_balance(crate::Pallet::::account_id()), HIGH_BALANCE + 2 * balance ); assert_eq!( - ParachainStaking::candidate_info(*ALICE) + ParachainStaking::candidate_info(ALICE) .unwrap() .total_counted, balance * 2 ); assert_eq!( - ParachainStaking::candidate_info(*BOB) - .unwrap() - .total_counted, + ParachainStaking::candidate_info(BOB).unwrap().total_counted, balance * 2 ); assert_ok!(Lottery::request_withdraw( - Origin::signed(*ALICE), + Origin::signed(ALICE), balance * 2 )); assert_eq!(crate::StakedCollators::::iter().count(), 2); @@ -484,7 +471,7 @@ fn unstaking_works_with_zero_collators_left() { assert_eq!(Lottery::withdrawal_request_queue().len(), 0); assert_eq!(Lottery::surplus_unstaking_balance(), 0); assert_eq!(Lottery::unlocked_unstaking_funds(), 0); - assert_eq!(Balances::free_balance(*ALICE), HIGH_BALANCE); + assert_eq!(Balances::free_balance(ALICE), HIGH_BALANCE); assert_eq!( Balances::free_balance(crate::Pallet::::account_id()), HIGH_BALANCE @@ -497,10 +484,10 @@ fn winner_distribution_should_be_equality_with_equal_deposits() { let balance = 500_000_000 * UNIT; ExtBuilder::default() .with_balances(vec![ - (*ALICE, HIGH_BALANCE), - (*BOB, HIGH_BALANCE), + (ALICE, HIGH_BALANCE), + (BOB, HIGH_BALANCE), ]) - .with_candidates(vec![(*BOB, balance)]) + .with_candidates(vec![(BOB, balance)]) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); @@ -559,34 +546,34 @@ fn winner_distribution_should_be_equality_with_equal_deposits() { fn depsiting_to_one_collator_multiple_times_in_one_block_should_work() { let balance = 50_000_000 * UNIT; ExtBuilder::default() - .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) - .with_candidates(vec![(*BOB, balance)]) + .with_balances(vec![(ALICE, HIGH_BALANCE), (BOB, HIGH_BALANCE)]) + .with_candidates(vec![(BOB, balance)]) .with_funded_lottery_account(HIGH_BALANCE) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); - assert_eq!(Lottery::staked_collators(*BOB), 0); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); - assert_eq!(Lottery::staked_collators(*BOB), balance); + assert_eq!(Lottery::staked_collators(BOB), 0); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); + assert_eq!(Lottery::staked_collators(BOB), balance); assert_last_event!(crate::mock::RuntimeEvent::Lottery( crate::Event::Deposited { - account: *ALICE, + account: ALICE, amount: balance } )); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); - assert_eq!(Lottery::staked_collators(*BOB), 2 * balance); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); + assert_eq!(Lottery::staked_collators(BOB), 2 * balance); assert_last_event!(crate::mock::RuntimeEvent::Lottery( crate::Event::Deposited { - account: *ALICE, + account: ALICE, amount: balance } )); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); - assert_eq!(Lottery::staked_collators(*BOB), 3 * balance); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); + assert_eq!(Lottery::staked_collators(BOB), 3 * balance); assert_last_event!(crate::mock::RuntimeEvent::Lottery( crate::Event::Deposited { - account: *ALICE, + account: ALICE, amount: balance } )); @@ -599,34 +586,34 @@ fn depsiting_to_two_collator_multiple_times_in_one_block_should_work() { let balance = 50_000_000 * UNIT; let balance1 = 20_000_000 * UNIT; ExtBuilder::default() - .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) - .with_candidates(vec![(*ALICE, balance1), (*BOB, balance)]) + .with_balances(vec![(ALICE, HIGH_BALANCE), (BOB, HIGH_BALANCE)]) + .with_candidates(vec![(ALICE, balance1), (BOB, balance)]) .with_funded_lottery_account(HIGH_BALANCE) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); - assert_eq!(Lottery::staked_collators(*BOB), 0); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance1)); - assert_eq!(Lottery::staked_collators(*ALICE), balance1); + assert_eq!(Lottery::staked_collators(BOB), 0); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance1)); + assert_eq!(Lottery::staked_collators(ALICE), balance1); assert_last_event!(crate::mock::RuntimeEvent::Lottery( crate::Event::Deposited { - account: *ALICE, + account: ALICE, amount: balance1 } )); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance1)); - assert_eq!(Lottery::staked_collators(*ALICE), 2 * balance1); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance1)); + assert_eq!(Lottery::staked_collators(ALICE), 2 * balance1); assert_last_event!(crate::mock::RuntimeEvent::Lottery( crate::Event::Deposited { - account: *ALICE, + account: ALICE, amount: balance1 } )); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance1)); - assert_eq!(Lottery::staked_collators(*BOB), balance1); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance1)); + assert_eq!(Lottery::staked_collators(BOB), balance1); assert_last_event!(crate::mock::RuntimeEvent::Lottery( crate::Event::Deposited { - account: *ALICE, + account: ALICE, amount: balance1 } )); @@ -638,24 +625,24 @@ fn depsiting_to_two_collator_multiple_times_in_one_block_should_work() { fn deposit_withdraw_deposit_to_new_joined_collator_works() { let balance = 50_000_000 * UNIT; ExtBuilder::default() - .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) - .with_candidates(vec![(*BOB, balance)]) + .with_balances(vec![(ALICE, HIGH_BALANCE), (BOB, HIGH_BALANCE)]) + .with_candidates(vec![(BOB, balance)]) .with_funded_lottery_account(HIGH_BALANCE) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); - assert_eq!(Lottery::staked_collators(*BOB), 0); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); - assert_eq!(Lottery::staked_collators(*BOB), balance); + assert_eq!(Lottery::staked_collators(BOB), 0); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); + assert_eq!(Lottery::staked_collators(BOB), balance); - assert_ok!(Lottery::request_withdraw(Origin::signed(*ALICE), balance)); - assert_eq!(Lottery::staked_collators(*BOB), balance); + assert_ok!(Lottery::request_withdraw(Origin::signed(ALICE), balance)); + assert_eq!(Lottery::staked_collators(BOB), balance); assert_eq!(Lottery::withdrawal_request_queue().len(), 1); assert_eq!(ParachainStaking::selected_candidates().len(), 1); // join a new collator because BOB is now ineligible to receive deposits assert_noop!( - Lottery::deposit(Origin::signed(*ALICE), balance), + Lottery::deposit(Origin::signed(ALICE), balance), Error::::NoCollatorForDeposit ); let (new_collator, _) = crate::mock::from_bench::create_funded_user::( @@ -675,7 +662,7 @@ fn deposit_withdraw_deposit_to_new_joined_collator_works() { assert_eq!(ParachainStaking::selected_candidates()[1], new_collator); // pretend the collator got some rewards pallet_parachain_staking::AwardedPts::::insert(1, new_collator, 20); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); assert_eq!(Lottery::staked_collators(new_collator), balance); }); } @@ -686,21 +673,21 @@ fn deposit_withdraw_partial_draw_lottery_works() { let half_balance = 250_000_000 * UNIT; let quarter_balance = 125_000_000 * UNIT; ExtBuilder::default() - .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) - .with_candidates(vec![(*BOB, balance)]) + .with_balances(vec![(ALICE, HIGH_BALANCE), (BOB, HIGH_BALANCE)]) + .with_candidates(vec![(BOB, balance)]) .with_funded_lottery_account(balance) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); - assert_eq!(0, Lottery::staked_collators(*BOB)); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); - let alice_post_deposit_balance = Balances::free_balance(*ALICE); - assert_eq!(balance, Lottery::staked_collators(*BOB)); + assert_eq!(0, Lottery::staked_collators(BOB)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); + let alice_post_deposit_balance = Balances::free_balance(ALICE); + assert_eq!(balance, Lottery::staked_collators(BOB)); assert_eq!(balance, Lottery::total_pot()); assert_eq!(balance, Lottery::sum_of_deposits()); assert_ok!(Lottery::request_withdraw( - Origin::signed(*ALICE), + Origin::signed(ALICE), half_balance )); // surplus = balance - half_balance = half_balance @@ -708,20 +695,20 @@ fn deposit_withdraw_partial_draw_lottery_works() { roll_one_block(); assert_ok!(Lottery::request_withdraw( - Origin::signed(*ALICE), + Origin::signed(ALICE), quarter_balance )); - assert_eq!(balance, Lottery::staked_collators(*BOB)); + assert_eq!(balance, Lottery::staked_collators(BOB)); // surplus = half_balance - quarter_balance = quarter_balance assert_eq!(quarter_balance, Lottery::surplus_unstaking_balance()); - pallet_parachain_staking::AwardedPts::::insert(2, *BOB, 20); + pallet_parachain_staking::AwardedPts::::insert(2, BOB, 20); roll_to_round_begin(3); // funds should be unlocked now and BOB is finished unstaking, so it's eligible for redepositing assert_ok!(Lottery::draw_lottery(RawOrigin::Root.into())); assert_eq!( alice_post_deposit_balance + half_balance + quarter_balance, - Balances::free_balance(*ALICE) + Balances::free_balance(ALICE) ); assert_eq!(0, Lottery::surplus_unstaking_balance()); assert_eq!(0, Lottery::unlocked_unstaking_funds()); @@ -729,7 +716,7 @@ fn deposit_withdraw_partial_draw_lottery_works() { assert!(crate::UnstakingCollators::::get().is_empty()); // draw lottery rebalance will restake surplus funds to collators. assert_eq!(crate::StakedCollators::::iter().count(), 1); - assert_eq!(quarter_balance, Lottery::staked_collators(*BOB)); + assert_eq!(quarter_balance, Lottery::staked_collators(BOB)); assert_eq!(quarter_balance, Lottery::total_pot()); assert_eq!(quarter_balance, Lottery::sum_of_deposits()); }); @@ -741,8 +728,8 @@ fn multiround_withdraw_partial_deposit_works() { let half_balance = 250_000_000 * UNIT; let quarter_balance = 125_000_000 * UNIT; ExtBuilder::default() - .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) - .with_candidates(vec![(*BOB, balance)]) + .with_balances(vec![(ALICE, HIGH_BALANCE), (BOB, HIGH_BALANCE)]) + .with_candidates(vec![(BOB, balance)]) .with_funded_lottery_account(balance) .build() .execute_with(|| { @@ -751,38 +738,38 @@ fn multiround_withdraw_partial_deposit_works() { assert!( ::LeaveCandidatesDelay::get() == 1u32 ); - assert_eq!(0, Lottery::staked_collators(*BOB)); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); - let alice_post_deposit_balance = Balances::free_balance(*ALICE); - assert_eq!(balance, Lottery::staked_collators(*BOB)); + assert_eq!(0, Lottery::staked_collators(BOB)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); + let alice_post_deposit_balance = Balances::free_balance(ALICE); + assert_eq!(balance, Lottery::staked_collators(BOB)); assert_eq!(balance, Lottery::total_pot()); assert_eq!(balance, Lottery::sum_of_deposits()); roll_one_block(); // ensure this unlocks *after* round 3 start assert_ok!(Lottery::request_withdraw( - Origin::signed(*ALICE), + Origin::signed(ALICE), half_balance )); - assert_eq!(balance, Lottery::staked_collators(*BOB)); + assert_eq!(balance, Lottery::staked_collators(BOB)); assert_eq!(1, Lottery::withdrawal_request_queue().len()); assert_eq!(half_balance, Lottery::surplus_unstaking_balance()); // withdrawing funds are still locked roll_to_round_begin(2); roll_one_block(); // ensure this unlocks *after* round 3 start - pallet_parachain_staking::AwardedPts::::insert(1, *BOB, 20); + pallet_parachain_staking::AwardedPts::::insert(1, BOB, 20); assert_ok!(Lottery::request_withdraw( - Origin::signed(*ALICE), + Origin::signed(ALICE), quarter_balance )); - assert_eq!(balance, Lottery::staked_collators(*BOB)); + assert_eq!(balance, Lottery::staked_collators(BOB)); assert_eq!(2, Lottery::withdrawal_request_queue().len()); assert_eq!( half_balance - quarter_balance, Lottery::surplus_unstaking_balance() ); assert_ok!(Lottery::draw_lottery(RawOrigin::Root.into())); - assert_eq!(balance, Lottery::staked_collators(*BOB)); + assert_eq!(balance, Lottery::staked_collators(BOB)); assert_eq!( half_balance - quarter_balance, Lottery::surplus_unstaking_balance() @@ -792,28 +779,28 @@ fn multiround_withdraw_partial_deposit_works() { // collator becomes unstaked on draw_lottery, must keep quarter for withdrawal, can restake other quarter roll_to_round_begin(3); - pallet_parachain_staking::AwardedPts::::insert(2, *BOB, 20); + pallet_parachain_staking::AwardedPts::::insert(2, BOB, 20); assert_ok!(Lottery::draw_lottery(RawOrigin::Root.into())); // balance - half - quarter - assert_eq!(quarter_balance, Lottery::staked_collators(*BOB)); + assert_eq!(quarter_balance, Lottery::staked_collators(BOB)); assert_eq!(quarter_balance, Lottery::unlocked_unstaking_funds()); assert_eq!(0, Lottery::surplus_unstaking_balance()); assert_eq!( alice_post_deposit_balance + half_balance, - Balances::free_balance(*ALICE) + Balances::free_balance(ALICE) ); assert_eq!(1, Lottery::withdrawal_request_queue().len()); assert!(crate::UnstakingCollators::::get().is_empty()); roll_to_round_begin(4); - pallet_parachain_staking::AwardedPts::::insert(3, *BOB, 20); + pallet_parachain_staking::AwardedPts::::insert(3, BOB, 20); // second withdrawal can be paid out at new round assert_ok!(Lottery::draw_lottery(RawOrigin::Root.into())); assert_eq!( alice_post_deposit_balance + half_balance + quarter_balance, - Balances::free_balance(*ALICE) + Balances::free_balance(ALICE) ); - assert_eq!(quarter_balance, Lottery::staked_collators(*BOB)); + assert_eq!(quarter_balance, Lottery::staked_collators(BOB)); assert_eq!(0, Lottery::surplus_unstaking_balance()); assert_eq!(0, Lottery::unlocked_unstaking_funds()); assert!(Lottery::withdrawal_request_queue().is_empty()); @@ -827,19 +814,19 @@ fn multiround_withdraw_partial_with_two_collators_works() { let quarter_balance = 125_000_000 * UNIT; ExtBuilder::default() .with_balances(vec![ - (*ALICE, HIGH_BALANCE), - (*BOB, HIGH_BALANCE), - (*CHARLIE, HIGH_BALANCE), + (ALICE, HIGH_BALANCE), + (BOB, HIGH_BALANCE), + (CHARLIE, HIGH_BALANCE), ]) - .with_candidates(vec![(*BOB, balance), (*CHARLIE, balance)]) + .with_candidates(vec![(BOB, balance), (CHARLIE, balance)]) .with_funded_lottery_account(reserve) // minimally fund lottery .build() .execute_with(|| { assert_eq!(reserve, Lottery::gas_reserve()); // XXX: Cant use getter in the ExtBuilder - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); assert_eq!(crate::StakedCollators::::iter().count(), 1); assert_ok!(Lottery::request_withdraw( - Origin::signed(*ALICE), + Origin::signed(ALICE), quarter_balance )); @@ -847,11 +834,11 @@ fn multiround_withdraw_partial_with_two_collators_works() { assert_ok!(Lottery::draw_lottery(RawOrigin::Root.into())); roll_one_block(); assert_ok!(Lottery::request_withdraw( - Origin::signed(*ALICE), + Origin::signed(ALICE), quarter_balance )); assert_ok!(Lottery::request_withdraw( - Origin::signed(*ALICE), + Origin::signed(ALICE), quarter_balance )); assert_eq!(3, Lottery::withdrawal_request_queue().len()); @@ -859,16 +846,16 @@ fn multiround_withdraw_partial_with_two_collators_works() { assert_eq!(crate::UnstakingCollators::::get().len(), 1); roll_to_round_begin(3); - pallet_parachain_staking::AwardedPts::::insert(3, *BOB, 20); - pallet_parachain_staking::AwardedPts::::insert(3, *CHARLIE, 20); + pallet_parachain_staking::AwardedPts::::insert(3, BOB, 20); + pallet_parachain_staking::AwardedPts::::insert(3, CHARLIE, 20); assert_ok!(Lottery::draw_lottery(RawOrigin::Root.into())); assert_eq!(2, Lottery::withdrawal_request_queue().len()); assert_eq!(crate::StakedCollators::::iter().count(), 0); assert_eq!(crate::UnstakingCollators::::get().len(), 0); roll_to_round_begin(4); - pallet_parachain_staking::AwardedPts::::insert(4, *BOB, 20); - pallet_parachain_staking::AwardedPts::::insert(4, *CHARLIE, 20); + pallet_parachain_staking::AwardedPts::::insert(4, BOB, 20); + pallet_parachain_staking::AwardedPts::::insert(4, CHARLIE, 20); assert_ok!(Lottery::draw_lottery(RawOrigin::Root.into())); assert_eq!(0, Lottery::unlocked_unstaking_funds()); assert_eq!(0, Lottery::surplus_unstaking_balance()); @@ -884,24 +871,24 @@ fn many_deposit_withdrawals_work() { let mut round_count = 2; ExtBuilder::default() .with_balances(vec![ - (*ALICE, HIGH_BALANCE), - (*BOB, HIGH_BALANCE), - (*CHARLIE, HIGH_BALANCE), - (*DAVE, HIGH_BALANCE), - (*EVE, HIGH_BALANCE), + (ALICE, HIGH_BALANCE), + (BOB, HIGH_BALANCE), + (CHARLIE, HIGH_BALANCE), + (DAVE, HIGH_BALANCE), + (EVE, HIGH_BALANCE), ]) .with_candidates(vec![ - (*ALICE, HIGH_BALANCE), - (*BOB, HIGH_BALANCE), - (*CHARLIE, HIGH_BALANCE), - (*DAVE, HIGH_BALANCE), - (*EVE, HIGH_BALANCE), + (ALICE, HIGH_BALANCE), + (BOB, HIGH_BALANCE), + (CHARLIE, HIGH_BALANCE), + (DAVE, HIGH_BALANCE), + (EVE, HIGH_BALANCE), ]) .with_funded_lottery_account(HIGH_BALANCE) .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); - let all_collators = &[*ALICE, *BOB, *CHARLIE, *DAVE, *EVE]; + let all_collators = &[ALICE, BOB, CHARLIE, DAVE, EVE]; reward_collators_for_round(round_count - 1, all_collators); roll_to_round_end(1); assert_ok!(Lottery::start_lottery(RawOrigin::Root.into())); @@ -977,7 +964,7 @@ fn enable_farming_works() { assert_eq!(farming_params.pool_id, 0); assert_noop!( - Lottery::set_farming_params(Origin::signed(*BOB), true, true, 1, 1), + Lottery::set_farming_params(Origin::signed(BOB), true, true, 1, 1), sp_runtime::DispatchError::BadOrigin ); @@ -1009,22 +996,23 @@ fn farming_deposit_withdraw() { let half_balance = 250_000_000 * UNIT; let quarter_balance = 125_000_000 * UNIT; ExtBuilder::default() - .with_balances(vec![(*ALICE, HIGH_BALANCE), (*BOB, HIGH_BALANCE)]) - .with_candidates(vec![(*BOB, balance)]) + .with_balances(vec![(ALICE, HIGH_BALANCE), (BOB, HIGH_BALANCE)]) + .with_candidates(vec![(BOB, balance)]) .with_funded_lottery_account(balance) .with_farming() .build() .execute_with(|| { assert!(HIGH_BALANCE > balance); - assert_eq!(0, Lottery::staked_collators(*BOB)); - assert_ok!(Lottery::deposit(Origin::signed(*ALICE), balance)); - let alice_post_deposit_balance = Balances::free_balance(*ALICE); - assert_eq!(balance, Lottery::staked_collators(*BOB)); + assert_eq!(0, Lottery::staked_collators(BOB)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); + let alice_post_deposit_balance = Balances::free_balance(ALICE); + assert_eq!(balance, Lottery::staked_collators(BOB)); assert_eq!(balance, Lottery::total_pot()); assert_eq!(balance, Lottery::sum_of_deposits()); + assert_eq!(balance, Assets::balance(V_MANTA_ID, ALICE)); assert_ok!(Lottery::request_withdraw( - Origin::signed(*ALICE), + Origin::signed(ALICE), half_balance )); // surplus = balance - half_balance = half_balance @@ -1032,20 +1020,20 @@ fn farming_deposit_withdraw() { roll_one_block(); assert_ok!(Lottery::request_withdraw( - Origin::signed(*ALICE), + Origin::signed(ALICE), quarter_balance )); - assert_eq!(balance, Lottery::staked_collators(*BOB)); + assert_eq!(balance, Lottery::staked_collators(BOB)); // surplus = half_balance - quarter_balance = quarter_balance assert_eq!(quarter_balance, Lottery::surplus_unstaking_balance()); - pallet_parachain_staking::AwardedPts::::insert(2, *BOB, 20); + pallet_parachain_staking::AwardedPts::::insert(2, BOB, 20); roll_to_round_begin(3); // funds should be unlocked now and BOB is finished unstaking, so it's eligible for redepositing assert_ok!(Lottery::draw_lottery(RawOrigin::Root.into())); assert_eq!( alice_post_deposit_balance + half_balance + quarter_balance, - Balances::free_balance(*ALICE) + Balances::free_balance(ALICE) ); assert_eq!(0, Lottery::surplus_unstaking_balance()); assert_eq!(0, Lottery::unlocked_unstaking_funds()); @@ -1053,7 +1041,7 @@ fn farming_deposit_withdraw() { assert!(crate::UnstakingCollators::::get().is_empty()); // draw lottery rebalance will restake surplus funds to collators. assert_eq!(crate::StakedCollators::::iter().count(), 1); - assert_eq!(quarter_balance, Lottery::staked_collators(*BOB)); + assert_eq!(quarter_balance, Lottery::staked_collators(BOB)); assert_eq!(quarter_balance, Lottery::total_pot()); assert_eq!(quarter_balance, Lottery::sum_of_deposits()); }); From eb17f950abaec096446f2d59f354e19e7e9cc86f Mon Sep 17 00:00:00 2001 From: Charles Ferrell Date: Sat, 18 Nov 2023 22:09:30 -0500 Subject: [PATCH 09/12] add to tests Signed-off-by: Charles Ferrell --- pallets/pallet-lottery/src/mock.rs | 9 +++++++-- pallets/pallet-lottery/src/tests.rs | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/pallets/pallet-lottery/src/mock.rs b/pallets/pallet-lottery/src/mock.rs index 28c12fe45..40438c63a 100644 --- a/pallets/pallet-lottery/src/mock.rs +++ b/pallets/pallet-lottery/src/mock.rs @@ -61,7 +61,10 @@ pub const CHARLIE: AccountId = 3; pub const DAVE: AccountId = 4; pub const EVE: AccountId = 5; pub const TREASURY_ACCOUNT: AccountId = 10; + pub const JUMBO: Balance = 1_000_000_000_000; +pub const INIT_JUMBO_AMOUNT: Balance = 1_000 * JUMBO; +pub const INIT_V_MANTA_AMOUNT: Balance = JUMBO; pub const V_MANTA_ID: CalamariAssetId = 8; pub const JUMBO_ID: CalamariAssetId = 9; @@ -681,13 +684,15 @@ impl ExtBuilder { >::FungibleLedger::deposit_minting( JUMBO_ID, &ALICE, - 1_000 * JUMBO + INIT_JUMBO_AMOUNT, ) ); assert_ok!( >::FungibleLedger::deposit_minting( - V_MANTA_ID, &ALICE, JUMBO + V_MANTA_ID, + &ALICE, + INIT_V_MANTA_AMOUNT ) ); diff --git a/pallets/pallet-lottery/src/tests.rs b/pallets/pallet-lottery/src/tests.rs index d9fbe9fd0..1a55f469f 100644 --- a/pallets/pallet-lottery/src/tests.rs +++ b/pallets/pallet-lottery/src/tests.rs @@ -19,7 +19,8 @@ use crate::{ mock::{ roll_one_block, roll_to, roll_to_round_begin, roll_to_round_end, AccountId, Assets, Balance, Balances, ExtBuilder, Lottery, ParachainStaking, RuntimeOrigin as Origin, System, - Test, ALICE, BOB, CHARLIE, DAVE, EVE, TREASURY_ACCOUNT, V_MANTA_ID, + Test, ALICE, BOB, CHARLIE, DAVE, EVE, INIT_JUMBO_AMOUNT, INIT_V_MANTA_AMOUNT, JUMBO_ID, + TREASURY_ACCOUNT, V_MANTA_ID, }, Config, Error, FarmingParameters, }; @@ -1002,6 +1003,9 @@ fn farming_deposit_withdraw() { .with_farming() .build() .execute_with(|| { + assert_eq!(INIT_JUMBO_AMOUNT, Assets::total_supply(JUMBO_ID)); + assert_eq!(INIT_V_MANTA_AMOUNT, Assets::total_supply(V_MANTA_ID)); + assert!(HIGH_BALANCE > balance); assert_eq!(0, Lottery::staked_collators(BOB)); assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); @@ -1009,7 +1013,14 @@ fn farming_deposit_withdraw() { assert_eq!(balance, Lottery::staked_collators(BOB)); assert_eq!(balance, Lottery::total_pot()); assert_eq!(balance, Lottery::sum_of_deposits()); - assert_eq!(balance, Assets::balance(V_MANTA_ID, ALICE)); + + // asset accounting is correct + assert_eq!(INIT_JUMBO_AMOUNT, Assets::total_supply(JUMBO_ID)); + assert_eq!( + balance + INIT_V_MANTA_AMOUNT, + Assets::total_supply(V_MANTA_ID) + ); + assert_eq!(0, Assets::balance(V_MANTA_ID, ALICE)); assert_ok!(Lottery::request_withdraw( Origin::signed(ALICE), From ed041c222faf896e43310ec8c29ea7b83161ce1f Mon Sep 17 00:00:00 2001 From: Charles Ferrell Date: Sun, 19 Nov 2023 15:31:09 -0500 Subject: [PATCH 10/12] add tests for deposit and withdraw edge cases Signed-off-by: Charles Ferrell --- pallets/pallet-lottery/src/mock.rs | 6 +- pallets/pallet-lottery/src/tests.rs | 90 ++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/pallets/pallet-lottery/src/mock.rs b/pallets/pallet-lottery/src/mock.rs index 40438c63a..5cfe5b198 100644 --- a/pallets/pallet-lottery/src/mock.rs +++ b/pallets/pallet-lottery/src/mock.rs @@ -37,7 +37,7 @@ use manta_primitives::{ }, constants::ASSET_MANAGER_PALLET_ID, currencies::Currencies, - types::{BlockNumber, CalamariAssetId, Header}, + types::{BlockNumber, CalamariAssetId, Header, PoolId}, }; use pallet_parachain_staking::{InflationInfo, Range}; use sp_core::H256; @@ -63,11 +63,13 @@ pub const EVE: AccountId = 5; pub const TREASURY_ACCOUNT: AccountId = 10; pub const JUMBO: Balance = 1_000_000_000_000; -pub const INIT_JUMBO_AMOUNT: Balance = 1_000 * JUMBO; +pub const INIT_JUMBO_AMOUNT: Balance = 100 * JUMBO; pub const INIT_V_MANTA_AMOUNT: Balance = JUMBO; pub const V_MANTA_ID: CalamariAssetId = 8; pub const JUMBO_ID: CalamariAssetId = 9; +pub const POOL_ID: PoolId = 0; + type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; diff --git a/pallets/pallet-lottery/src/tests.rs b/pallets/pallet-lottery/src/tests.rs index 1a55f469f..80ec05164 100644 --- a/pallets/pallet-lottery/src/tests.rs +++ b/pallets/pallet-lottery/src/tests.rs @@ -18,9 +18,9 @@ use crate::{ assert_last_event, mock::{ roll_one_block, roll_to, roll_to_round_begin, roll_to_round_end, AccountId, Assets, - Balance, Balances, ExtBuilder, Lottery, ParachainStaking, RuntimeOrigin as Origin, System, - Test, ALICE, BOB, CHARLIE, DAVE, EVE, INIT_JUMBO_AMOUNT, INIT_V_MANTA_AMOUNT, JUMBO_ID, - TREASURY_ACCOUNT, V_MANTA_ID, + Balance, Balances, ExtBuilder, Farming, Lottery, ParachainStaking, RuntimeOrigin as Origin, + System, Test, ALICE, BOB, CHARLIE, DAVE, EVE, INIT_JUMBO_AMOUNT, INIT_V_MANTA_AMOUNT, + JUMBO_ID, POOL_ID, V_MANTA_ID, }, Config, Error, FarmingParameters, }; @@ -1029,6 +1029,14 @@ fn farming_deposit_withdraw() { // surplus = balance - half_balance = half_balance assert_eq!(half_balance, Lottery::surplus_unstaking_balance()); + assert_eq!( + half_balance + INIT_V_MANTA_AMOUNT, + Assets::total_supply(V_MANTA_ID) + ); + // no rewards when no time has past + assert_eq!(0, Assets::balance(JUMBO_ID, ALICE)); + assert_eq!(0, Assets::balance(JUMBO_ID, ALICE)); + roll_one_block(); assert_ok!(Lottery::request_withdraw( Origin::signed(ALICE), @@ -1038,6 +1046,14 @@ fn farming_deposit_withdraw() { // surplus = half_balance - quarter_balance = quarter_balance assert_eq!(quarter_balance, Lottery::surplus_unstaking_balance()); + assert_eq!( + quarter_balance + INIT_V_MANTA_AMOUNT, + Assets::total_supply(V_MANTA_ID) + ); + // no rewards when no time has past + assert_eq!(0, Assets::balance(V_MANTA_ID, ALICE)); + assert_eq!(0, Assets::balance(JUMBO_ID, ALICE)); + pallet_parachain_staking::AwardedPts::::insert(2, BOB, 20); roll_to_round_begin(3); // funds should be unlocked now and BOB is finished unstaking, so it's eligible for redepositing @@ -1055,5 +1071,73 @@ fn farming_deposit_withdraw() { assert_eq!(quarter_balance, Lottery::staked_collators(BOB)); assert_eq!(quarter_balance, Lottery::total_pot()); assert_eq!(quarter_balance, Lottery::sum_of_deposits()); + + assert_eq!( + quarter_balance + INIT_V_MANTA_AMOUNT, + Assets::total_supply(V_MANTA_ID) + ); + // no rewards when no time has past + assert_eq!(0, Assets::balance(V_MANTA_ID, ALICE)); + assert_eq!(0, Assets::balance(JUMBO_ID, ALICE)); + }); +} + +#[test] +fn fails_withdrawing_more_than_vmanta() { + let balance = 500_000_000 * UNIT; + let half_balance = 250_000_000 * UNIT; + ExtBuilder::default() + .with_balances(vec![ + (ALICE, HIGH_BALANCE), + (BOB, HIGH_BALANCE), + (CHARLIE, HIGH_BALANCE), + ]) + .with_candidates(vec![(BOB, balance)]) + .with_funded_lottery_account(balance) + .with_farming() + .build() + .execute_with(|| { + assert_ok!(Lottery::deposit(Origin::signed(CHARLIE), balance)); + assert_ok!(Lottery::deposit(Origin::signed(ALICE), balance)); + + assert_eq!( + (balance * 2) + INIT_V_MANTA_AMOUNT, + Assets::total_supply(V_MANTA_ID) + ); + assert_eq!(0, Assets::balance(V_MANTA_ID, CHARLIE)); + assert_ok!(Farming::withdraw( + Origin::signed(CHARLIE), + POOL_ID, + Some(half_balance) + )); + assert_ok!(Farming::withdraw_claim(Origin::signed(CHARLIE), POOL_ID)); + assert_eq!(half_balance, Assets::balance(V_MANTA_ID, CHARLIE)); + assert_eq!( + (balance * 2) + INIT_V_MANTA_AMOUNT, + Assets::total_supply(V_MANTA_ID) + ); + + assert_ok!(Assets::transfer( + Origin::signed(CHARLIE), + V_MANTA_ID, + ALICE, + half_balance + )); + assert_noop!( + Lottery::request_withdraw(Origin::signed(CHARLIE), balance), + pallet_assets::Error::::BalanceLow + ); + assert_eq!(0, Assets::balance(V_MANTA_ID, CHARLIE)); + + assert_ok!(Assets::transfer( + Origin::signed(ALICE), + V_MANTA_ID, + CHARLIE, + half_balance + )); + // will work if V_MANTA is not in farming pool but is in user account + assert_ok!(Lottery::request_withdraw(Origin::signed(CHARLIE), balance)); + // no leftover V_MANTA + assert_eq!(0, Assets::balance(V_MANTA_ID, CHARLIE)); }); } From 830ea22c675fbd358c3e727169f93609fb4540a3 Mon Sep 17 00:00:00 2001 From: Charles Ferrell Date: Sun, 19 Nov 2023 15:32:45 -0500 Subject: [PATCH 11/12] clippy Signed-off-by: Charles Ferrell --- pallets/pallet-lottery/src/mock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/pallet-lottery/src/mock.rs b/pallets/pallet-lottery/src/mock.rs index 5cfe5b198..d5b975233 100644 --- a/pallets/pallet-lottery/src/mock.rs +++ b/pallets/pallet-lottery/src/mock.rs @@ -737,7 +737,7 @@ fn init_jumbo_farming() { None )); - let share_info = Farming::shares_and_withdrawn_rewards(pool_id, &ALICE).unwrap(); + let share_info = Farming::shares_and_withdrawn_rewards(pool_id, ALICE).unwrap(); assert_eq!(share_info.share, tokens); } From 5637965b2f56594245b63b7627c86ccd5d43bfd8 Mon Sep 17 00:00:00 2001 From: Charles Ferrell Date: Sun, 19 Nov 2023 21:30:23 -0500 Subject: [PATCH 12/12] fix tx diff test Signed-off-by: Charles Ferrell --- runtime/calamari/src/diff_tx_fees.rs | 16 +++++++++++++++- runtime/manta/src/diff_tx_fees.rs | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/runtime/calamari/src/diff_tx_fees.rs b/runtime/calamari/src/diff_tx_fees.rs index ecfd8794d..f3ea710c7 100644 --- a/runtime/calamari/src/diff_tx_fees.rs +++ b/runtime/calamari/src/diff_tx_fees.rs @@ -2791,7 +2791,7 @@ fn calculate_all_current_extrinsic_tx_fee() -> ( { assert_eq!( crate::RuntimeCall::get_call_names("Lottery").len(), - 12, + 13, "Please update new extrinsic here." ); t.execute_with(|| { @@ -2915,6 +2915,20 @@ fn calculate_all_current_extrinsic_tx_fee() -> ( dispatch_info, call_len, )); + + let call = crate::RuntimeCall::Lottery(pallet_lottery::Call::set_farming_params { + mint_farming_token: true, + burn_farming_token: true, + pool_id: 0, + currency_id: 1, + }); + let (dispatch_info, call_len) = get_call_details(&call); + calamari_runtime_calls.push(( + "pallet_lottery", + "set_farming_params", + dispatch_info, + call_len, + )); }); } diff --git a/runtime/manta/src/diff_tx_fees.rs b/runtime/manta/src/diff_tx_fees.rs index dcf596c0a..b81926263 100644 --- a/runtime/manta/src/diff_tx_fees.rs +++ b/runtime/manta/src/diff_tx_fees.rs @@ -2778,7 +2778,7 @@ fn calculate_all_current_extrinsic_tx_fee() -> ( { assert_eq!( crate::RuntimeCall::get_call_names("Lottery").len(), - 12, + 13, "Please update new extrinsic here." ); t.execute_with(|| { @@ -2902,6 +2902,20 @@ fn calculate_all_current_extrinsic_tx_fee() -> ( dispatch_info, call_len, )); + + let call = crate::RuntimeCall::Lottery(pallet_lottery::Call::set_farming_params { + mint_farming_token: true, + burn_farming_token: true, + pool_id: 0, + currency_id: 1, + }); + let (dispatch_info, call_len) = get_call_details(&call); + calamari_runtime_calls.push(( + "pallet_lottery", + "set_farming_params", + dispatch_info, + call_len, + )); }); }