diff --git a/Cargo.lock b/Cargo.lock index b5e975ff2..68d2cc15f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1808,6 +1808,7 @@ dependencies = [ "bifrost-currencies", "bifrost-parachain-staking", "bifrost-primitives", + "bifrost-stable-asset", "bifrost-stable-pool", "bifrost-vtoken-minting", "bifrost-xcm-interface", diff --git a/pallets/slp/Cargo.toml b/pallets/slp/Cargo.toml index 8bc788577..d07ad9dbf 100644 --- a/pallets/slp/Cargo.toml +++ b/pallets/slp/Cargo.toml @@ -33,6 +33,7 @@ bifrost-vtoken-minting = { workspace = true } bifrost-asset-registry = { workspace = true } bifrost-parachain-staking = { workspace = true } bifrost-stable-pool = { workspace = true } +bifrost-stable-asset = { workspace = true } [dev-dependencies] hex = "0.4.3" diff --git a/pallets/slp/src/benchmarking.rs b/pallets/slp/src/benchmarking.rs index f372dbf6e..5d165074d 100644 --- a/pallets/slp/src/benchmarking.rs +++ b/pallets/slp/src/benchmarking.rs @@ -20,15 +20,112 @@ #![cfg(feature = "runtime-benchmarks")] use crate::*; +use bifrost_primitives::{DOT, VDOT, VKSM}; use frame_benchmarking::v2::*; -use frame_support::assert_ok; -use sp_runtime::traits::UniqueSaturatedFrom; +use frame_support::{assert_ok, PalletId}; +use frame_system::RawOrigin as SystemOrigin; +use sp_runtime::traits::{AccountIdConversion, StaticLookup, UniqueSaturatedFrom}; const DELEGATOR1: MultiLocation = MultiLocation { parents: 1, interior: X1(AccountId32 { network: None, id: [1u8; 32] }) }; const DELEGATOR2: MultiLocation = MultiLocation { parents: 1, interior: X1(AccountId32 { network: None, id: [2u8; 32] }) }; +type TokenBalanceOf = <::MultiCurrency as orml_traits::MultiCurrency< + ::AccountId, +>>::Balance; + +pub fn unit(d: u128) -> u128 { + d.saturating_mul(10_u128.pow(12)) +} + +fn init_stable_asset_pool< + T: Config + + bifrost_stable_pool::Config + + pallet_balances::Config + + bifrost_stable_asset::Config, +>() -> Result<(), BenchmarkError> { + let caller: AccountIdOf = whitelisted_caller(); + let account_id = T::Lookup::unlookup(caller.clone()); + pallet_balances::Pallet::::force_set_balance( + SystemOrigin::Root.into(), + account_id, + 10_000_000_000_000_u128, + ) + .unwrap(); + + ::MultiCurrency::deposit( + DOT.into(), + &caller, + ::Balance::from(unit(1_000_000).into()), + )?; + ::MultiCurrency::deposit( + VDOT.into(), + &caller, + ::Balance::from(unit(1_000_000).into()), + )?; + let fee_account: AccountIdOf = account("caller", 2, 2); + pallet_balances::Pallet::::force_set_balance( + SystemOrigin::Root.into(), + T::Lookup::unlookup(caller.clone()), + 10_000_000_000_000_u128, + ) + .unwrap(); + pallet_balances::Pallet::::force_set_balance( + SystemOrigin::Root.into(), + T::Lookup::unlookup(fee_account.clone()), + 10_000_000_000_000_u128, + ) + .unwrap(); + + let coin0 = DOT; + let coin1 = VDOT; + let amounts = vec![ + ::Balance::from(unit(100u128).into()), + ::Balance::from(unit(100u128).into()), + ]; + + let origin = ::ControlOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + + assert_ok!(bifrost_stable_pool::Pallet::::create_pool( + origin.clone() as ::RuntimeOrigin, + vec![coin0.into(), coin1.into()], + vec![1u128.into(), 1u128.into()], + 0u128.into(), + 0u128.into(), + 0u128.into(), + 220u128.into(), + fee_account.clone(), + fee_account.clone(), + 1000000000000u128.into() + )); + assert_ok!(bifrost_stable_pool::Pallet::::edit_token_rate( + origin.clone() as ::RuntimeOrigin, + 0, + vec![ + (DOT.into(), (1u128.into(), 1u128.into())), + (VDOT.into(), (90_000_000u128.into(), 100_000_000u128.into())) + ] + )); + assert_ok!(bifrost_stable_pool::Pallet::::add_liquidity( + SystemOrigin::Signed(caller.clone()).into(), + 0, + amounts, + ::Balance::zero() + )); + + let treasury_account = PalletId(*b"bf/trsry").into_account_truncating(); + // deposit some VDOT to the treasury account + ::MultiCurrency::deposit( + VDOT.into(), + &treasury_account, + ::Balance::from(unit(1_000_000).into()), + )?; + + Ok(()) +} + pub fn set_mins_and_maxs(origin: ::RuntimeOrigin) { let mins_and_maxs = MinimumsMaximums { delegator_bonded_minimum: 0u32.into(), @@ -97,7 +194,9 @@ pub fn init_ongoing_time(origin: ::Runtime assert_ok!(Pallet::::set_currency_delays(origin.clone(), KSM, Some(delay))); } -#[benchmarks(where T: Config + orml_tokens::Config + bifrost_vtoken_minting::Config)] +#[benchmarks(where T: Config + orml_tokens::Config + bifrost_vtoken_minting::Config+ bifrost_stable_pool::Config+ pallet_balances::Config + bifrost_asset_registry::Config)] +// #[benchmarks(where T: Config + bifrost_stable_pool::Config + +// pallet_balances::Config)] mod benchmarks { use super::*; use crate::primitives::{PhalaLedger, SubstrateValidatorsByDelegatorUpdateEntry}; @@ -1083,6 +1182,55 @@ mod benchmarks { Ok(()) } + #[benchmark] + fn convert_treasury_vtoken() -> Result<(), BenchmarkError> { + let origin = ::ControlOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + + init_stable_asset_pool::()?; + + let treasury_account = PalletId(*b"bf/trsry").into_account_truncating(); + assert_eq!( + ::MultiCurrency::free_balance(VDOT, &treasury_account), + TokenBalanceOf::::unique_saturated_from(1_000_0000_0000_0000_000u128) + ); + assert_eq!( + ::MultiCurrency::free_balance(DOT, &treasury_account), + Zero::zero() + ); + + let metadata = AssetMetadata { + name: b"DOT Native Token".to_vec(), + symbol: b"DOT".to_vec(), + decimals: 10, + minimal_balance: Zero::zero(), + }; + // register DOT in registry pallet + assert_ok!(bifrost_asset_registry::Pallet::::register_token_metadata( + origin.clone(), + Box::new(metadata.clone()) + )); + + #[extrinsic_call] + _( + origin as ::RuntimeOrigin, + VDOT, + TokenBalanceOf::::from(10u32), + ); + + // get the VDOT balance of treasury account + assert_eq!( + ::MultiCurrency::free_balance(VDOT, &treasury_account), + TokenBalanceOf::::unique_saturated_from(999_999_999_999_999_990u128) + ); + assert_eq!( + ::MultiCurrency::free_balance(DOT, &treasury_account), + TokenBalanceOf::::from(10u32) + ); + + Ok(()) + } + #[benchmark] fn clean_outdated_validator_boost_list() -> Result<(), BenchmarkError> { let origin = ::ControlOrigin::try_successful_origin() diff --git a/pallets/slp/src/mocks/mock_kusama.rs b/pallets/slp/src/mocks/mock_kusama.rs index 8d461cb68..78bea2c94 100644 --- a/pallets/slp/src/mocks/mock_kusama.rs +++ b/pallets/slp/src/mocks/mock_kusama.rs @@ -33,14 +33,14 @@ use frame_support::{ construct_runtime, ord_parameter_types, pallet_prelude::Get, parameter_types, - traits::{Everything, Nothing, ProcessMessageError}, + traits::{ConstU128, ConstU32, Everything, Nothing, ProcessMessageError}, PalletId, }; use frame_system::{EnsureRoot, EnsureSignedBy}; use hex_literal::hex; use orml_traits::{location::RelativeReserveProvider, parameter_type_with_key}; use parity_scale_codec::{Decode, Encode}; -use sp_core::{bounded::BoundedVec, hashing::blake2_256, ConstU32, H256}; +use sp_core::{bounded::BoundedVec, hashing::blake2_256, H256}; pub use sp_runtime::{testing::Header, Perbill}; use sp_runtime::{ traits::{AccountIdConversion, Convert, TrailingZeroInput}, @@ -74,9 +74,48 @@ construct_runtime!( ParachainStaking: bifrost_parachain_staking, Utility: pallet_utility, PolkadotXcm: pallet_xcm, + StableAsset: bifrost_stable_asset, + StablePool: bifrost_stable_pool, } ); +impl bifrost_stable_pool::Config for Runtime { + type WeightInfo = (); + type ControlOrigin = EnsureSignedBy; + type CurrencyId = CurrencyId; + type MultiCurrency = Currencies; + type StableAsset = StableAsset; + type VtokenMinting = VtokenMinting; + type CurrencyIdConversion = AssetIdMaps; + type CurrencyIdRegister = AssetIdMaps; +} + +pub struct EnsurePoolAssetId; +impl bifrost_stable_asset::traits::ValidateAssetId for EnsurePoolAssetId { + fn validate(_: CurrencyId) -> bool { + true + } +} +parameter_types! { + pub const StableAssetPalletId: PalletId = PalletId(*b"nuts/sta"); +} + +impl bifrost_stable_asset::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type AssetId = CurrencyId; + type Balance = Balance; + type Assets = Currencies; + type PalletId = StableAssetPalletId; + type AtLeast64BitUnsigned = u128; + type FeePrecision = ConstU128<10_000_000_000>; + type APrecision = ConstU128<100>; + type PoolAssetLimit = ConstU32<5>; + type SwapExactOverAmount = ConstU128<100>; + type WeightInfo = (); + type ListingOrigin = EnsureSignedBy; + type EnsurePoolAssetId = EnsurePoolAssetId; +} + parameter_types! { pub const NativeCurrencyId: CurrencyId = BNC; pub const RelayCurrencyId: CurrencyId = KSM; @@ -516,7 +555,7 @@ impl Config for Runtime { type MaxLengthLimit = MaxLengthLimit; type XcmWeightAndFeeHandler = XcmDestWeightAndFee; type ChannelCommission = (); - type StablePoolHandler = (); + type StablePoolHandler = StablePool; type AssetIdMaps = AssetIdMaps; type TreasuryAccount = BifrostTreasuryAccount; }