diff --git a/pallets/channel-commission/src/lib.rs b/pallets/channel-commission/src/lib.rs index 12a5688fc..709f237a3 100644 --- a/pallets/channel-commission/src/lib.rs +++ b/pallets/channel-commission/src/lib.rs @@ -24,6 +24,7 @@ extern crate alloc; use alloc::{vec, vec::Vec}; use bifrost_primitives::{ CurrencyId, CurrencyIdExt, SlpHostingFeeProvider, VTokenMintRedeemProvider, + VtokenMintingInterface, }; use frame_support::{pallet_prelude::*, PalletId}; use frame_system::pallet_prelude::*; @@ -88,26 +89,46 @@ pub mod pallet { type NameLengthLimit: Get; /// The current block number provider. type BlockNumberProvider: BlockNumberProvider>; + /// The interface to call VtokenMinting module functions. + type VtokenMintingInterface: VtokenMintingInterface< + AccountIdOf, + CurrencyId, + BalanceOf, + >; } #[pallet::error] pub enum Error { + /// Overflow error, indicating that a mathematical operation exceeded the allowed numeric range. Overflow, + /// Error indicating that the provided channel name exceeds the maximum allowed length. ChannelNameTooLong, + /// Conversion error, indicating a failure during a type conversion operation. ConversionError, + /// Error indicating that the specified channel does not exist in storage. ChannelNotExist, + /// Transfer error, indicating that a fund transfer operation has failed. TransferError, + /// Error indicating that the vToken is not configured for commission calculations. VtokenNotConfiguredForCommission, + /// Invalid commission rate, indicating that the provided commission rate is out of range or malformed. InvalidCommissionRate, + /// Error indicating that the commission token has already been set and cannot be reconfigured. CommissionTokenAlreadySet, + /// Invalid vToken, indicating that the provided vToken is invalid or unrecognized. InvalidVtoken, /// Error indicating that no changes were made during a modification operation. + /// This means that a modification request was issued but did not result in any actual changes. NoChangesMade, - /// Represents an error that occurs when a division operation encounters a divisor of zero. + /// Error indicating a division operation encountered a divisor of zero. /// This is a critical error, as division by zero is undefined and cannot be performed. DivisionByZero, - /// Error indicating that the removal operation was not completed successfully. + /// Error indicating that the removal operation was not successfully completed. + /// This means an attempt to remove a resource or record did not succeed. RemovalNotComplete, + /// Error indicating a failure during token-to-vToken conversion via exchange rate calculation. + /// This can occur when the conversion formula encounters an unexpected condition or invalid input. + TokenToVtokenConversionFailed, } #[pallet::event] @@ -1027,6 +1048,13 @@ impl SlpHostingFeeProvider, AccountIdOf> .to_vtoken() .map_err(|_| Error::::ConversionError)?; + let vtoken_amount = T::VtokenMintingInterface::get_v_currency_amount_by_currency_amount( + staking_token, + vtoken, + amount, + ) + .map_err(|_| Error::::TokenToVtokenConversionFailed)?; + // If the vtoken is configured for commission, record the hosting fee if let Some(commission_token) = CommissionTokens::::get(vtoken) { PeriodTotalCommissions::::mutate( @@ -1034,7 +1062,7 @@ impl SlpHostingFeeProvider, AccountIdOf> |total_commission| -> Result<(), Error> { let sum_up_amount = total_commission .1 - .checked_add(&amount) + .checked_add(&vtoken_amount) .ok_or(Error::::Overflow)?; total_commission.1 = sum_up_amount; diff --git a/pallets/channel-commission/src/mock.rs b/pallets/channel-commission/src/mock.rs index 09616e4a7..6a9b86b4f 100644 --- a/pallets/channel-commission/src/mock.rs +++ b/pallets/channel-commission/src/mock.rs @@ -19,17 +19,20 @@ #![cfg(test)] #![allow(non_upper_case_globals)] +use crate as bifrost_channel_commission; use crate::mock::sp_api_hidden_includes_construct_runtime::hidden_include::traits::OnInitialize; use bifrost_primitives::{ currency::{ASG, BNC, KSM}, - CommissionPalletId, CurrencyId, + CommissionPalletId, CurrencyId, MockXcmTransfer, MoonbeamChainId, RedeemType, + VTokenSupplyProvider, VtokenMintingInterface, +}; +use frame_support::dispatch::DispatchResultWithPostInfo; +use frame_support::{ + derive_impl, ord_parameter_types, parameter_types, traits::Nothing, BoundedVec, PalletId, }; -use frame_support::{derive_impl, ord_parameter_types, parameter_types, traits::Nothing, PalletId}; use frame_system::EnsureSignedBy; use sp_core::ConstU32; -use sp_runtime::{traits::AccountIdConversion, AccountId32, BuildStorage}; - -use crate as bifrost_channel_commission; +use sp_runtime::{traits::AccountIdConversion, AccountId32, BuildStorage, DispatchError}; pub type BlockNumber = u64; pub type Amount = i128; @@ -142,6 +145,66 @@ impl bifrost_channel_commission::Config for Runtime { type ClearingDuration = ClearingDuration; type NameLengthLimit = NameLengthLimit; type BlockNumberProvider = System; + type VtokenMintingInterface = SimpleVtokenMintingInterface; +} + +pub struct SimpleVtokenMintingInterface; + +impl VtokenMintingInterface for SimpleVtokenMintingInterface { + fn mint( + _exchanger: AccountId, + _token_id: CurrencyId, + _token_amount: Balance, + _remark: BoundedVec>, + _channel_id: Option, + ) -> Result { + unimplemented!("method do not need to be implemented yet"); + } + + fn redeem( + _exchanger: AccountId, + _vtoken_id: CurrencyId, + _vtoken_amount: Balance, + ) -> DispatchResultWithPostInfo { + unimplemented!("method do not need to be implemented yet"); + } + + fn slpx_redeem( + _exchanger: AccountId, + _vtoken_id: CurrencyId, + _vtoken_amount: Balance, + _redeem: RedeemType, + ) -> DispatchResultWithPostInfo { + unimplemented!("method do not need to be implemented yet"); + } + + fn get_v_currency_amount_by_currency_amount( + _token_id: CurrencyId, + _vtoken_id: CurrencyId, + token_amount: Balance, + ) -> Result { + Ok(token_amount.checked_div(2u64).unwrap()) + } + + fn get_currency_amount_by_v_currency_amount( + _token_id: CurrencyId, + _vtoken_id: CurrencyId, + _vtoken_amount: Balance, + ) -> Result { + unimplemented!("method do not need to be implemented yet"); + } + + fn get_token_pool(_currency_id: CurrencyId) -> Balance { + unimplemented!("method do not need to be implemented yet"); + } + + fn get_minimums_redeem(_vtoken_id: CurrencyId) -> Balance { + unimplemented!("method do not need to be implemented yet"); + } + + fn get_moonbeam_parachain_id() -> u32 { + unimplemented!("method do not need to be implemented yet"); + } } pub struct ExtBuilder { diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs index bba061f53..82b176821 100644 --- a/runtime/bifrost-kusama/src/lib.rs +++ b/runtime/bifrost-kusama/src/lib.rs @@ -1764,6 +1764,7 @@ impl bifrost_channel_commission::Config for Runtime { type ClearingDuration = ClearingDuration; type NameLengthLimit = NameLengthLimit; type BlockNumberProvider = System; + type VtokenMintingInterface = VtokenMinting; } impl bifrost_vbnc_convert::Config for Runtime { diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs index 0ee845c4f..4f624df24 100644 --- a/runtime/bifrost-polkadot/src/lib.rs +++ b/runtime/bifrost-polkadot/src/lib.rs @@ -1594,6 +1594,7 @@ impl bifrost_channel_commission::Config for Runtime { type ClearingDuration = ClearingDuration; type NameLengthLimit = NameLengthLimit; type BlockNumberProvider = System; + type VtokenMintingInterface = VtokenMinting; } impl bifrost_clouds_convert::Config for Runtime {