Skip to content

Commit

Permalink
Slpx add evm create (#1454)
Browse files Browse the repository at this point in the history
* Fix try-runtime

* Slpx add evm create order
  • Loading branch information
hqwangningbo authored Oct 10, 2024
1 parent 8ba3c31 commit 81f5c6d
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 17 deletions.
37 changes: 37 additions & 0 deletions pallets/slp/src/tests/phala_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use crate::{
use bifrost_primitives::currency::{PHA, VPHA};
use frame_support::{assert_noop, assert_ok, PalletId};
use polkadot_parachain_primitives::primitives::Sibling;
use sp_core::crypto::Ss58Codec;
use sp_runtime::traits::AccountIdConversion;

// parents 0 means vault, parents 1 means stake_pool
Expand Down Expand Up @@ -1460,3 +1461,39 @@ fn phala_convert_asset_works() {
);
});
}

#[test]
fn generate_derivative_account() {
ExtBuilder::default().build().execute_with(|| {
// PublicKey: 0x70617261d1070000000000000000000000000000000000000000000000000000
// AccountId(42): 5Ec4AhPV91i9yNuiWuNunPf6AQCYDhFTTA4G5QCbtqYApH9E
let sovereign_account = <ParaId as AccountIdConversion<AccountId>>::into_account_truncating(
&ParaId::from(2001),
);
println!("sovereign_account: {:?}", sovereign_account);
// PublicKey: 0x5a53736d8e96f1c007cf0d630acf5209b20611617af23ce924c8e25328eb5d28
// AccountId(42): 5E78xTBiaN3nAGYtcNnqTJQJqYAkSDGggKqaDfpNsKyPpbcb
let sovereign_account_derivative_0 =
Utility::derivative_account_id(sovereign_account.clone(), 0);
assert_eq!(
sovereign_account_derivative_0,
AccountId::from_ss58check("5E78xTBiaN3nAGYtcNnqTJQJqYAkSDGggKqaDfpNsKyPpbcb").unwrap()
);
// PublicKey: 0xf1c5ca0368e7a567945a59aaea92b9be1e0794fe5e077d017462b7ce8fc1ed7c
// AccountId(42): 5HXi9pzWnTQzk7VKzY6VQn92KfWCcA5NbSm53uKHrYU1VsjP
let sovereign_account_derivative_1 =
Utility::derivative_account_id(sovereign_account.clone(), 1);
assert_eq!(
sovereign_account_derivative_1,
AccountId::from_ss58check("5HXi9pzWnTQzk7VKzY6VQn92KfWCcA5NbSm53uKHrYU1VsjP").unwrap()
);
// PublicKey: 0x1e365411cfd0b0f78466be433a2ec5f7d545c5e28cb2e9a31ce97d4a28447dfc
// AccountId(42): 5CkKS3YMx64TguUYrMERc5Bn6Mn2aKMUkcozUFREQDgHS3Tv
let sovereign_account_derivative_2 =
Utility::derivative_account_id(sovereign_account.clone(), 2);
assert_eq!(
sovereign_account_derivative_2,
AccountId::from_ss58check("5CkKS3YMx64TguUYrMERc5Bn6Mn2aKMUkcozUFREQDgHS3Tv").unwrap()
);
})
}
118 changes: 104 additions & 14 deletions pallets/slpx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ use crate::types::{
use bifrost_asset_registry::AssetMetadata;
use bifrost_primitives::{
currency::{BNC, MOVR, VFIL},
AstarChainId, Balance, BifrostKusamaChainId, CurrencyId, CurrencyIdMapping, HydrationChainId,
InterlayChainId, MantaChainId, RedeemType, SlpxOperator, TokenInfo, VtokenMintingInterface,
GLMR,
AstarChainId, AstarEvmChainId, Balance, BifrostKusamaChainId, CurrencyId, CurrencyIdMapping,
HydrationChainId, InterlayChainId, MantaChainId, MoonbeamEvmChainId, MoonriverEvmChainId,
RedeemType, SlpxOperator, TokenInfo, VtokenMintingInterface, GLMR,
};
use cumulus_primitives_core::ParaId;
use ethereum::TransactionAction;
Expand Down Expand Up @@ -82,7 +82,7 @@ pub mod pallet {
};
use frame_system::ensure_root;

const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);

#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
Expand Down Expand Up @@ -351,6 +351,8 @@ pub mod pallet {

Self::do_create_order(
source_chain_caller,
Default::default(),
None,
bifrost_chain_caller,
currency_id,
Default::default(),
Expand Down Expand Up @@ -390,6 +392,8 @@ pub mod pallet {

Self::do_create_order(
source_chain_caller,
Default::default(),
None,
bifrost_chain_caller,
vtoken_id,
Default::default(),
Expand Down Expand Up @@ -627,6 +631,8 @@ pub mod pallet {
ensure_root(origin)?;
Self::do_create_order(
source_chain_caller,
Default::default(),
None,
bifrost_chain_caller,
currency_id,
Default::default(),
Expand Down Expand Up @@ -658,6 +664,8 @@ pub mod pallet {

Self::do_create_order(
source_chain_caller,
Default::default(),
None,
bifrost_chain_caller,
currency_id,
Default::default(),
Expand All @@ -667,6 +675,54 @@ pub mod pallet {
)
}

/// EVM create order
/// Parameters:
/// - `source_chain_caller`: The caller of the source chain
/// - `source_chain_id`: The source chain id
/// - `source_chain_block_number`: The source chain block number
/// - `currency_id`: The currency id of the token
/// - `currency_amount`: The currency amount of the token
/// - `send_to`: The target chain to transfer the token to
/// - `remark`: The remark of the order
/// - `channel_id`: The channel id of the order
#[pallet::call_index(14)]
#[pallet::weight(<T as Config>::WeightInfo::mint())]
pub fn evm_create_order(
origin: OriginFor<T>,
source_chain_caller: H160,
source_chain_id: u64,
source_chain_block_number: u128,
currency_id: CurrencyId,
currency_amount: BalanceOf<T>,
send_to: TargetChain<T::AccountId>,
remark: BoundedVec<u8, ConstU32<32>>,
channel_id: u32,
) -> DispatchResultWithPostInfo {
let bifrost_chain_caller = ensure_signed(origin)?;

let support_chain =
Self::match_source_chain_id(source_chain_id).ok_or(Error::<T>::Unsupported)?;

ensure!(
WhitelistAccountId::<T>::get(support_chain).contains(&bifrost_chain_caller),
Error::<T>::AccountNotFound
);

let source_chain_caller = OrderCaller::Evm(source_chain_caller);

Self::do_create_order(
source_chain_caller,
source_chain_id,
Some(source_chain_block_number),
bifrost_chain_caller,
currency_id,
currency_amount,
remark,
channel_id,
send_to,
)
}

// TODO: Substrate user create order
// #[pallet::call_index(14)]
// #[pallet::weight(<T as Config>::WeightInfo::mint())]
Expand Down Expand Up @@ -696,6 +752,18 @@ pub mod pallet {
}

impl<T: Config> Pallet<T> {
fn match_source_chain_id(source_chain_id: u64) -> Option<SupportChain> {
if source_chain_id == AstarEvmChainId::get() {
Some(SupportChain::Astar)
} else if source_chain_id == MoonriverEvmChainId::get() ||
source_chain_id == MoonbeamEvmChainId::get()
{
Some(SupportChain::Moonbeam)
} else {
None
}
}

/// According to currency_id, return the order type
fn order_type(currency_id: CurrencyId) -> Result<OrderType, Error<T>> {
match currency_id {
Expand Down Expand Up @@ -753,6 +821,8 @@ impl<T: Config> Pallet<T> {

fn do_create_order(
source_chain_caller: OrderCaller<T::AccountId>,
source_chain_id: u64,
source_chain_block_number: Option<u128>,
bifrost_chain_caller: T::AccountId,
currency_id: CurrencyId,
currency_amount: BalanceOf<T>,
Expand All @@ -769,6 +839,8 @@ impl<T: Config> Pallet<T> {
currency_amount,
remark,
source_chain_caller,
source_chain_id,
source_chain_block_number,
bifrost_chain_caller,
derivative_account,
target_chain,
Expand Down Expand Up @@ -897,9 +969,9 @@ impl<T: Config> Pallet<T> {
/// Charge an execution fee
fn charge_execution_fee(
currency_id: CurrencyIdOf<T>,
currency_amount: BalanceOf<T>,
evm_caller_account_id: &AccountIdOf<T>,
) -> Result<BalanceOf<T>, DispatchError> {
let free_balance = T::MultiCurrency::free_balance(currency_id, evm_caller_account_id);
let execution_fee = ExecutionFee::<T>::get(currency_id)
.unwrap_or_else(|| Self::get_default_fee(currency_id));

Expand All @@ -910,8 +982,9 @@ impl<T: Config> Pallet<T> {
execution_fee,
)?;

let balance_exclude_fee =
free_balance.checked_sub(&execution_fee).ok_or(Error::<T>::FreeBalanceTooLow)?;
let balance_exclude_fee = currency_amount
.checked_sub(&execution_fee)
.ok_or(Error::<T>::FreeBalanceTooLow)?;
Ok(balance_exclude_fee)
}

Expand Down Expand Up @@ -1016,11 +1089,24 @@ impl<T: Config> Pallet<T> {
pub fn handle_order(
order: &Order<AccountIdOf<T>, CurrencyIdOf<T>, BalanceOf<T>, BlockNumberFor<T>>,
) -> DispatchResult {
let currency_amount =
Self::charge_execution_fee(order.currency_id, &order.derivative_account)
.map_err(|_| Error::<T>::ErrorChargeFee)?;
let currency_amount = Self::charge_execution_fee(
order.currency_id,
order.currency_amount,
&order.derivative_account,
)
.map_err(|_| Error::<T>::ErrorChargeFee)?;
match order.order_type {
OrderType::Mint => {
let vtoken_id =
order.currency_id.to_vtoken().map_err(|_| Error::<T>::ErrorConvertVtoken)?;

let vtoken_amount = T::VtokenMintingInterface::token_to_vtoken(
order.currency_id,
vtoken_id,
currency_amount,
)
.map_err(|_| Error::<T>::ErrorVtokenMiting)?;

T::VtokenMintingInterface::mint(
order.derivative_account.clone(),
order.currency_id,
Expand All @@ -1029,10 +1115,6 @@ impl<T: Config> Pallet<T> {
Some(order.channel_id),
)
.map_err(|_| Error::<T>::ErrorVtokenMiting)?;
let vtoken_id =
order.currency_id.to_vtoken().map_err(|_| Error::<T>::ErrorConvertVtoken)?;
let vtoken_amount =
T::MultiCurrency::free_balance(vtoken_id, &order.derivative_account);

Self::transfer_to(
order.derivative_account.clone(),
Expand Down Expand Up @@ -1079,11 +1161,19 @@ impl<T: Config> Pallet<T> {

if current_block_number - order_queue[0].create_block_number >= DelayBlock::<T>::get() {
let mut order = order_queue.remove(0);
// For compatibility with older versions
if order.currency_amount == Default::default() {
order.currency_amount = T::MultiCurrency::free_balance(
order.currency_id,
&order.derivative_account,
);
} else {
// Ensure that the currency amount is not greater than the free balance
let free_balance = T::MultiCurrency::free_balance(
order.currency_id,
&order.derivative_account,
);
order.currency_amount = order.currency_amount.min(free_balance);
}
match Self::handle_order(&order) {
Ok(_) => {
Expand Down
Loading

0 comments on commit 81f5c6d

Please sign in to comment.