From f515451073718f220504f089a6e7c5843e3349c3 Mon Sep 17 00:00:00 2001 From: hqwangningbo <2536935847@qq.com> Date: Mon, 9 Sep 2024 16:34:33 +0800 Subject: [PATCH] Add more slp v2 docs --- .../slp-v2/src/astar_dapp_staking/impls.rs | 8 +- pallets/slp-v2/src/common/impls.rs | 8 +- pallets/slp-v2/src/common/types/kusama.rs | 4 +- pallets/slp-v2/src/common/types/mod.rs | 21 +- pallets/slp-v2/src/common/types/polkadot.rs | 6 +- pallets/slp-v2/src/lib.rs | 179 +++++++++++++++--- pallets/slp-v2/src/tests.rs | 8 +- 7 files changed, 187 insertions(+), 47 deletions(-) diff --git a/pallets/slp-v2/src/astar_dapp_staking/impls.rs b/pallets/slp-v2/src/astar_dapp_staking/impls.rs index 16ba479863..ba4a1fe018 100644 --- a/pallets/slp-v2/src/astar_dapp_staking/impls.rs +++ b/pallets/slp-v2/src/astar_dapp_staking/impls.rs @@ -132,7 +132,7 @@ impl Pallet { let (query_id, xcm_message) = Self::get_query_id_and_xcm_message(call, delegator_index, &pending_status)?; if let Some(query_id) = query_id { - let pending_status = pending_status.clone().ok_or(Error::::MissingXcmFee)?; + let pending_status = pending_status.clone().ok_or(Error::::XcmFeeNotFound)?; PendingStatusByQueryId::::insert(query_id, pending_status.clone()); } Self::send_xcm_message(ASTAR_DAPP_STAKING, xcm_message)?; @@ -208,13 +208,13 @@ impl Pallet { let currency_id = ASTAR_DAPP_STAKING.info().currency_id; let current_time_unit = T::VtokenMinting::get_ongoing_time_unit(currency_id) - .ok_or(Error::::TimeUnitNotExist)?; + .ok_or(Error::::TimeUnitNotFound)?; let configuration = ConfigurationByStakingProtocol::::get(ASTAR_DAPP_STAKING) .ok_or(Error::::ConfigurationNotFound)?; let unlock_time = current_time_unit .add(configuration.unlock_period) - .ok_or(Error::::TimeUnitNotExist)?; + .ok_or(Error::::TimeUnitNotFound)?; pending_ledger .unlocking .try_push(AstarUnlockingRecord { amount, unlock_time }) @@ -226,7 +226,7 @@ impl Pallet { let currency_id = ASTAR_DAPP_STAKING.info().currency_id; let current_time_unit = T::VtokenMinting::get_ongoing_time_unit(currency_id) - .ok_or(Error::::TimeUnitNotExist)?; + .ok_or(Error::::TimeUnitNotFound)?; pending_ledger.unlocking.retain(|record| { current_time_unit.cmp(&record.unlock_time) != Ordering::Greater }); diff --git a/pallets/slp-v2/src/common/impls.rs b/pallets/slp-v2/src/common/impls.rs index 98778661ed..679aead72d 100644 --- a/pallets/slp-v2/src/common/impls.rs +++ b/pallets/slp-v2/src/common/impls.rs @@ -208,7 +208,7 @@ impl Pallet { staking_protocol: &StakingProtocol, amount: Balance, ) -> Result, Error> { - let polkadot_xcm_pallet_index = staking_protocol.info().polkadot_xcm_pallet_index; + let xcm_pallet_index = staking_protocol.info().xcm_pallet_index; let bifrost_dest_location = staking_protocol.info().bifrost_dest_location; let (entrance_account, _) = T::VtokenMinting::get_entrance_and_exit_accounts(); let account_id = entrance_account @@ -219,7 +219,7 @@ impl Pallet { let fee_asset_item = 0u32; let weight_limit = WeightLimit::Unlimited; - let mut calldata = polkadot_xcm_pallet_index.encode(); + let mut calldata = xcm_pallet_index.encode(); calldata.extend(LIMITED_RESERVE_TRANSFER_ASSETS_CALL_INDEX.encode()); // bifrost_dest_location calldata.extend(VersionedLocation::V4(bifrost_dest_location).encode()); @@ -299,8 +299,8 @@ impl Pallet { let dest_location = staking_protocol.info().remote_dest_location; let (ticket, _price) = T::XcmSender::validate(&mut Some(dest_location), &mut Some(xcm_message)) - .map_err(|_| Error::::ErrorValidating)?; - T::XcmSender::deliver(ticket).map_err(|_| Error::::ErrorDelivering)?; + .map_err(|_| Error::::ValidatingFailed)?; + T::XcmSender::deliver(ticket).map_err(|_| Error::::DeliveringFailed)?; Ok(()) } diff --git a/pallets/slp-v2/src/common/types/kusama.rs b/pallets/slp-v2/src/common/types/kusama.rs index 21a23dae7f..06d4c6e133 100644 --- a/pallets/slp-v2/src/common/types/kusama.rs +++ b/pallets/slp-v2/src/common/types/kusama.rs @@ -45,7 +45,7 @@ impl StakingProtocol { match self { StakingProtocol::MoonriverParachainStaking => StakingProtocolInfo { utility_pallet_index: 30, - polkadot_xcm_pallet_index: 103, + xcm_pallet_index: 103, currency_id: MOVR, unlock_period: TimeUnit::Round(28), remote_fee_location: Location::new(0, [PalletInstance(10)]), @@ -61,7 +61,7 @@ impl StakingProtocol { }, StakingProtocol::KusamaStaking => StakingProtocolInfo { utility_pallet_index: 24, - polkadot_xcm_pallet_index: 99, + xcm_pallet_index: 99, currency_id: KSM, unlock_period: TimeUnit::Era(28), remote_fee_location: Location::here(), diff --git a/pallets/slp-v2/src/common/types/mod.rs b/pallets/slp-v2/src/common/types/mod.rs index 5ba0f8fdc4..9bff6ae28e 100644 --- a/pallets/slp-v2/src/common/types/mod.rs +++ b/pallets/slp-v2/src/common/types/mod.rs @@ -27,29 +27,48 @@ use xcm::v4::{Location, Weight}; pub type DelegatorIndex = u16; /// Pallet index in remote chain. pub type PalletIndex = u8; +/// As derivative call index pub const AS_DERIVATIVE_CALL_INDEX: u8 = 1; +/// Reserve transfer assets call index pub const LIMITED_RESERVE_TRANSFER_ASSETS_CALL_INDEX: u8 = 8; +/// Configuration of the protocol #[derive(Encode, Decode, MaxEncodedLen, Default, Clone, Debug, PartialEq, Eq, TypeInfo)] pub struct ProtocolConfiguration { + /// Xcm fee for the task pub xcm_task_fee: XcmFee, + /// Protocol fee rate pub protocol_fee_rate: Permill, + /// Unlock period pub unlock_period: TimeUnit, + /// Staking Protocol operator pub operator: AccountId, + /// Max update token exchange rate pub max_update_token_exchange_rate: Permill, + /// Update time unit interval pub update_time_unit_interval: BlockNumber, + /// Update exchange rate interval pub update_exchange_rate_interval: BlockNumber, } +/// Staking protocol information #[derive(Encode, Decode, MaxEncodedLen, Default, Clone, Debug, PartialEq, Eq, TypeInfo)] pub struct StakingProtocolInfo { + /// Utility pallet index pub utility_pallet_index: PalletIndex, - pub polkadot_xcm_pallet_index: PalletIndex, + /// Xcm pallet index + pub xcm_pallet_index: PalletIndex, + /// Currency Id for Staking Protocol pub currency_id: CurrencyId, + /// Unlock period pub unlock_period: TimeUnit, + /// Remote chain supports fee location. pub remote_fee_location: Location, + /// Remote chain supports refund location. pub remote_refund_beneficiary: Location, + /// Dest location for remote chain pub remote_dest_location: Location, + /// Bifrost dest location pub bifrost_dest_location: Location, } diff --git a/pallets/slp-v2/src/common/types/polkadot.rs b/pallets/slp-v2/src/common/types/polkadot.rs index 86811140ce..d906d85124 100644 --- a/pallets/slp-v2/src/common/types/polkadot.rs +++ b/pallets/slp-v2/src/common/types/polkadot.rs @@ -51,7 +51,7 @@ impl StakingProtocol { match self { StakingProtocol::AstarDappStaking => StakingProtocolInfo { utility_pallet_index: 11, - polkadot_xcm_pallet_index: 51, + xcm_pallet_index: 51, currency_id: ASTR, unlock_period: TimeUnit::Era(9), remote_fee_location: Location::here(), @@ -67,7 +67,7 @@ impl StakingProtocol { }, StakingProtocol::MoonbeamParachainStaking => StakingProtocolInfo { utility_pallet_index: 30, - polkadot_xcm_pallet_index: 103, + xcm_pallet_index: 103, currency_id: GLMR, unlock_period: TimeUnit::Round(28), remote_fee_location: Location::new(0, [PalletInstance(10)]), @@ -83,7 +83,7 @@ impl StakingProtocol { }, StakingProtocol::PolkadotStaking => StakingProtocolInfo { utility_pallet_index: 26, - polkadot_xcm_pallet_index: 99, + xcm_pallet_index: 99, currency_id: DOT, unlock_period: TimeUnit::Era(28), remote_fee_location: Location::here(), diff --git a/pallets/slp-v2/src/lib.rs b/pallets/slp-v2/src/lib.rs index c1a5454619..f05edfa534 100644 --- a/pallets/slp-v2/src/lib.rs +++ b/pallets/slp-v2/src/lib.rs @@ -105,7 +105,7 @@ pub mod pallet { #[pallet::pallet] pub struct Pallet(_); - /// Operator for different staking protocols. + /// Configuration for different staking protocols. #[pallet::storage] pub type ConfigurationByStakingProtocol = StorageMap< _, @@ -193,55 +193,96 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { + /// Add a delegator to the staking protocol. AddDelegator { + /// Slp supports staking protocols. staking_protocol: StakingProtocol, + /// Delegator index. delegator_index: DelegatorIndex, + /// Delegator account. delegator: Delegator, }, + /// Remove a delegator from the staking protocol. RemoveDelegator { + /// Slp supports staking protocols. staking_protocol: StakingProtocol, + /// Delegator index. delegator_index: DelegatorIndex, + /// Delegator account. delegator: Delegator, }, + /// Add a validator to the staking protocol. AddValidator { + /// Slp supports staking protocols. staking_protocol: StakingProtocol, + /// Delegator account. delegator: Delegator, + /// Validator account. validator: Validator, }, + /// Remove a validator from the staking protocol. RemoveValidator { + /// Slp supports staking protocols. staking_protocol: StakingProtocol, + /// Delegator account. delegator: Delegator, + /// Validator account. validator: Validator, }, + /// Set configuration for a specific staking protocol. SetConfiguration { + /// Slp supports staking protocols. staking_protocol: StakingProtocol, + /// The staking protocol configuration. configuration: ProtocolConfiguration, }, + /// Set ledger for a specific delegator. SetLedger { + /// Slp supports staking protocols. staking_protocol: StakingProtocol, + /// Delegator account. delegator: Delegator, + /// Ledger. ledger: Ledger, }, + /// Send xcm task. SendXcmTask { + /// Xcm Message Query id. query_id: Option, + /// Delegator account. delegator: Delegator, + /// Xcm task. task: XcmTask, + /// Pending confirmation status. pending_status: Option>, + /// Destination. dest_location: Location, }, + /// Xcm task response received. NotifyResponseReceived { + /// Xcm responder. responder: Location, + /// Pending confirmation status. pending_status: PendingStatus, }, + /// Time unit updated. TimeUnitUpdated { + /// Slp supports staking protocols. staking_protocol: StakingProtocol, + /// Time unit. time_unit: TimeUnit, }, + /// Token exchange rate updated. TokenExchangeRateUpdated { + /// Slp supports staking protocols. staking_protocol: StakingProtocol, + /// Delegator account. delegator: Delegator, + /// The type of token that the fee is charged to protocol_fee_currency_id: CurrencyId, + /// The amount of the fee charged to the protocol protocol_fee: Balance, + /// Amount of exchange rates updated amount: Balance, }, } @@ -250,6 +291,10 @@ pub mod pallet { pub enum Error { /// Delegator index has exceeded the maximum allowed value of 65535. DelegatorIndexOverflow, + /// The maximum number of validators has been reached. + ValidatorsOverflow, + /// UnlockRecordOverflow + UnlockRecordOverflow, /// The staking protocol is not supported. UnsupportedStakingProtocol, /// The delegator index was not found. @@ -262,44 +307,36 @@ pub mod pallet { LedgerNotFound, /// The validator was not found. ValidatorNotFound, + /// Missing XCM fee value. + XcmFeeNotFound, + /// Missing pending status. + PendingStatusNotFound, + /// The specified time unit does not exist. + TimeUnitNotFound, /// The delegator already exists. DelegatorAlreadyExists, /// The delegator index already exists. DelegatorIndexAlreadyExists, /// The validator already exists. ValidatorAlreadyExists, - /// The maximum number of validators has been reached. - ValidatorsTooMuch, /// Failed to derive the derivative account ID. DerivativeAccountIdFailed, - /// Missing XCM fee value. - MissingXcmFee, - /// Missing pending status. - MissingPendingStatus, - /// Missing query ID. - MissingQueryId, /// Error during validation. - ErrorValidating, + ValidatingFailed, /// Error during delivery. - ErrorDelivering, - /// The specified time unit does not exist. - TimeUnitNotExist, - /// The specified time unit is too short. - UpdateOngoingTimeUnitIntervalTooShort, - /// The specified token exchange rate is too short. - UpdateTokenExchangeRateIntervalTooShort, + DeliveringFailed, + /// calculate protocol fee failed. + CalculateProtocolFeeFailed, + /// IncreaseTokenPoolFailed + IncreaseTokenPoolFailed, + /// The update interval is too short. + UpdateIntervalTooShort, /// The specified token exchange rate amount is too large. UpdateTokenExchangeRateAmountTooLarge, /// Invalid parameter. InvalidParameter, - /// calculate protocol fee failed. - CalculateProtocolFeeFailed, /// Not authorized. NotAuthorized, - /// IncreaseTokenPoolError - IncreaseTokenPoolError, - /// UnlockRecordOverflow - UnlockRecordOverflow, } #[pallet::hooks] @@ -308,6 +345,12 @@ pub mod pallet { #[pallet::call] impl Pallet { /// Set the XCM fee for a specific XCM task. + /// + /// Can only be called by governance + /// + /// Parameters + /// - `staking_protocol`: Slp supports staking protocols. + /// - `configuration`: The staking protocol configuration. #[pallet::call_index(0)] #[pallet::weight(::WeightInfo::set_protocol_configuration())] pub fn set_protocol_configuration( @@ -334,6 +377,13 @@ pub mod pallet { } /// Add a delegator to the staking protocol. + /// + /// Can only be called by governance + /// + /// Parameters + /// - `staking_protocol`: Slp supports staking protocols. + /// - `delegator`: If delegator is None, the delegator will be derived from sovereign + /// account. #[pallet::call_index(1)] #[pallet::weight(::WeightInfo::add_delegator())] pub fn add_delegator( @@ -346,6 +396,12 @@ pub mod pallet { } /// Remove a delegator from the staking protocol. + /// + /// Can only be called by governance + /// + /// Parameters + /// - `staking_protocol`: Slp supports staking protocols. + /// - `delegator`: Delegator that need to be removed. #[pallet::call_index(2)] #[pallet::weight(::WeightInfo::remove_delegator())] pub fn remove_delegator( @@ -358,6 +414,13 @@ pub mod pallet { } /// Add a validator to the staking protocol. + /// + /// Can only be called by governance + /// + /// Parameters + /// - `staking_protocol`: Slp supports staking protocols. + /// - `delegator`: Select the delegator which is existed. + /// - `validator`: Validator that need to be added. #[pallet::call_index(3)] #[pallet::weight(::WeightInfo::add_validator())] pub fn add_validator( @@ -374,7 +437,7 @@ pub mod pallet { ensure!(!validators.contains(&validator), Error::::ValidatorAlreadyExists); validators .try_push(validator.clone()) - .map_err(|_| Error::::ValidatorsTooMuch)?; + .map_err(|_| Error::::ValidatorsOverflow)?; Self::deposit_event(Event::::AddValidator { staking_protocol, delegator, @@ -386,6 +449,13 @@ pub mod pallet { } /// Remove a validator from the staking protocol. + /// + /// Can only be called by governance + /// + /// Parameters + /// - `staking_protocol`: Slp supports staking protocols. + /// - `delegator`: Select the delegator which is existed. + /// - `validator`: Validator that need to be removed. #[pallet::call_index(4)] #[pallet::weight(::WeightInfo::remove_validator())] pub fn remove_validator( @@ -412,6 +482,13 @@ pub mod pallet { } /// Set the update token exchange rate limit for a specific staking protocol. + /// + /// Can only be called by governance. + /// + /// Parameters + /// - `staking_protocol`: Slp supports staking protocols. + /// - `delegator`: Select the delegator which is existed. + /// - `ledger`: Ledger that need to be set. #[pallet::call_index(5)] #[pallet::weight(::WeightInfo::set_ledger())] pub fn set_ledger( @@ -446,6 +523,13 @@ pub mod pallet { } /// Transfer the staking token to remote chain. + /// Transfer the free balance of the Entrance Account to the selected delegator. + /// + /// Can be called by governance or staking protocol operator. + /// + /// Parameters + /// - `staking_protocol`: Slp supports staking protocols. + /// - `delegator`: Select the delegator which is existed. #[pallet::call_index(6)] #[pallet::weight(::WeightInfo::transfer_to())] pub fn transfer_to( @@ -458,6 +542,14 @@ pub mod pallet { } /// Transfer the staking token back from remote chain. + /// Transfer the amount of tokens from the selected delegator back to the entrance account. + /// + /// Can be called by governance or staking protocol operator. + /// + /// Parameters + /// - `staking_protocol`: Slp supports staking protocols. + /// - `delegator`: Select the delegator which is existed. + /// - `amount`: The amount of tokens to transfer back. #[pallet::call_index(7)] #[pallet::weight(::WeightInfo::transfer_back())] pub fn transfer_back( @@ -471,6 +563,15 @@ pub mod pallet { } /// Update the ongoing time unit for a specific staking protocol. + /// Update frequency controlled by update_time_unit_interval. + /// Less than update_time_unit_interval will report an error. + /// + /// Can be called by governance or staking protocol operator. + /// + /// Parameters + /// - `staking_protocol`: Slp supports staking protocols. + /// - `time_uint_option`: If time_uint is None, the ongoing time unit will be increased by + /// one. Otherwise, the ongoing time unit will be updated to the specified time unit. #[pallet::call_index(8)] #[pallet::weight(::WeightInfo::update_ongoing_time_unit())] pub fn update_ongoing_time_unit( @@ -488,7 +589,7 @@ pub mod pallet { LastUpdateOngoingTimeUnitBlockNumber::::get(staking_protocol); ensure!( current_block_number >= last_update_block_number + update_interval, - Error::::UpdateOngoingTimeUnitIntervalTooShort + Error::::UpdateIntervalTooShort ); let currency_id = staking_protocol.info().currency_id; @@ -497,7 +598,7 @@ pub mod pallet { Some(time_unit) => time_unit, None => { let current_time_unit = T::VtokenMinting::get_ongoing_time_unit(currency_id) - .ok_or(Error::::TimeUnitNotExist)?; + .ok_or(Error::::TimeUnitNotFound)?; current_time_unit.add_one() }, }; @@ -511,6 +612,15 @@ pub mod pallet { } /// Update the token exchange rate for a specific staking protocol. + /// Update frequency controlled by update_exchange_rate_interval. + /// Amount max update for token pool * max_update_token_exchange_rate. + /// + /// Can be called by governance or staking protocol operator. + /// + /// Parameters + /// - `staking_protocol`: Slp supports staking protocols. + /// - `delegator`: Select the delegator which is existed. + /// - `amount`: The amount of tokens to update the token exchange rate. #[pallet::call_index(9)] #[pallet::weight(::WeightInfo::update_token_exchange_rate())] pub fn update_token_exchange_rate( @@ -539,7 +649,7 @@ pub mod pallet { ); ensure!( current_block_number >= last_update_block_number + update_interval, - Error::::UpdateTokenExchangeRateIntervalTooShort + Error::::UpdateIntervalTooShort ); let pool_token_amount = T::VtokenMinting::get_token_pool(currency_id); let max_amount = max_update_permill.mul_floor(pool_token_amount); @@ -568,7 +678,7 @@ pub mod pallet { // Update the token exchange rate. T::VtokenMinting::increase_token_pool(currency_id, amount) - .map_err(|_| Error::::IncreaseTokenPoolError)?; + .map_err(|_| Error::::IncreaseTokenPoolFailed)?; LedgerByStakingProtocolAndDelegator::::mutate( staking_protocol, delegator.clone(), @@ -597,6 +707,14 @@ pub mod pallet { Ok(().into()) } + /// Manipulate a delegator to perform Dapp staking related operations. + /// + /// Can be called by governance or staking protocol operator. + /// + /// Parameters + /// - `staking_protocol`: Slp supports staking protocols. + /// - `delegator`: Select the delegator which is existed. + /// - `task`: The Dapp staking task. #[cfg(feature = "polkadot")] #[pallet::call_index(10)] #[pallet::weight(::WeightInfo::astar_dapp_staking())] @@ -609,6 +727,9 @@ pub mod pallet { Self::do_dapp_staking(delegator, task) } + /// Processing Xcm message execution results. + /// + /// Can be called by governance or xcm origin. #[cfg(feature = "polkadot")] #[pallet::call_index(11)] #[pallet::weight(::WeightInfo::notify_astar_dapp_staking())] @@ -619,7 +740,7 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let responder = Self::ensure_governance_or_xcm_response(origin)?; let pending_status = PendingStatusByQueryId::::get(query_id) - .ok_or(Error::::MissingPendingStatus)?; + .ok_or(Error::::PendingStatusNotFound)?; if Response::DispatchResult(MaybeErrorCode::Success) == response { Self::do_notify_astar_dapp_staking(responder, pending_status)?; }; diff --git a/pallets/slp-v2/src/tests.rs b/pallets/slp-v2/src/tests.rs index 49d626fbfc..c3357beaf8 100644 --- a/pallets/slp-v2/src/tests.rs +++ b/pallets/slp-v2/src/tests.rs @@ -772,7 +772,7 @@ fn update_ongoing_time_unit_update_interval_too_short() { staking_protocol, Some(TimeUnit::Era(1)) ), - SlpV2Error::::UpdateOngoingTimeUnitIntervalTooShort + SlpV2Error::::UpdateIntervalTooShort ); RelaychainDataProvider::set_block_number(100); @@ -780,7 +780,7 @@ fn update_ongoing_time_unit_update_interval_too_short() { // Ok assert_noop!( SlpV2::update_ongoing_time_unit(RuntimeOrigin::root(), staking_protocol, None), - SlpV2Error::::TimeUnitNotExist + SlpV2Error::::TimeUnitNotFound ); assert_ok!(SlpV2::update_ongoing_time_unit( @@ -794,7 +794,7 @@ fn update_ongoing_time_unit_update_interval_too_short() { // => Error assert_noop!( SlpV2::update_ongoing_time_unit(RuntimeOrigin::root(), staking_protocol, None), - SlpV2Error::::UpdateOngoingTimeUnitIntervalTooShort + SlpV2Error::::UpdateIntervalTooShort ); RelaychainDataProvider::set_block_number(200); // current relaychain block number 200 = update_interval 100 + last update block number 100 @@ -920,7 +920,7 @@ fn update_token_exchange_rate_limt_error() { delegator.clone(), amount ), - SlpV2Error::::UpdateTokenExchangeRateIntervalTooShort + SlpV2Error::::UpdateIntervalTooShort ); RelaychainDataProvider::set_block_number(101);