From 15f92bfffbe673d7ce74b08f7941a5fe5dc515d2 Mon Sep 17 00:00:00 2001 From: zktony Date: Thu, 9 Feb 2023 20:23:00 +0530 Subject: [PATCH 1/5] Added PDEX Handler --- pallets/asset-handler/src/lib.rs | 25 +++++++++++++++++++++++++ pallets/thea/src/lib.rs | 4 ++-- runtime/src/lib.rs | 8 ++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/pallets/asset-handler/src/lib.rs b/pallets/asset-handler/src/lib.rs index 25c725d1d..ddcbacf04 100644 --- a/pallets/asset-handler/src/lib.rs +++ b/pallets/asset-handler/src/lib.rs @@ -130,6 +130,13 @@ pub mod pallet { /// Parachain Network Id #[pallet::constant] type ParachainNetworkId: Get; + + /// Polkadex Asset + #[pallet::constant] + type PolkadexAssetId: Get; + + /// PDEX Token Holder Account + type PDEXHolderAccount: Get; } #[pallet::pallet] @@ -660,6 +667,24 @@ pub mod pallet { Ok(()) } + pub fn handle_asset( + asset_id: u128, + who: T::AccountId, + amount: u128, + ) -> Result<(), DispatchError> { + let polkadex_asset_id = T::PolkadexAssetId::get(); + if polkadex_asset_id == asset_id { + Self::lock_pdex_asset(amount, who) + } else { + Self::burn_thea_asset(asset_id, who, amount) + } + } + + pub fn lock_pdex_asset(amount: u128, who: T::AccountId) -> DispatchResult { + let polkadex_holder_account = T::PDEXHolderAccount::get(); + T::Currency::transfer(&who, &polkadex_holder_account, amount.saturated_into(), ExistenceRequirement::KeepAlive) + } + pub fn burn_thea_asset( asset_id: u128, who: T::AccountId, diff --git a/pallets/thea/src/lib.rs b/pallets/thea/src/lib.rs index fb3dca94d..edcb1119f 100644 --- a/pallets/thea/src/lib.rs +++ b/pallets/thea/src/lib.rs @@ -537,8 +537,8 @@ pub mod pallet { // TODO[#610]: Update Thea Staking pallet about fees collected - // Burn assets - asset_handler::pallet::Pallet::::burn_thea_asset(asset_id, user.clone(), amount)?; + // Handle assets + asset_handler::pallet::Pallet::::handle_asset(asset_id, user.clone(), amount)?; let withdrawal = ApprovedWithdraw { asset_id, diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index c3c0bb725..fe0e83fed 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -252,6 +252,7 @@ parameter_types! { pub const MaxPending: u16 = 32; } use scale_info::TypeInfo; +use sp_core::crypto::AccountId32; use sp_npos_elections::ExtendedBalance; /// The type used to represent the kinds of proxying allowed. @@ -1288,6 +1289,11 @@ impl chainbridge::Config for Runtime { type ProposalLifetime = ProposalLifetime; } +parameter_types! { + pub const PolkadexAssetId: u128 = 1000; //TODO: Chnage Polkddex Asset ID + pub const PDEXHolderAccount: AccountId32 = AccountId32::new([1u8;32]); //TODO Chnage Holder Account +} + impl asset_handler::pallet::Config for Runtime { type Event = Event; type Currency = Balances; @@ -1296,6 +1302,8 @@ impl asset_handler::pallet::Config for Runtime { type TreasuryPalletId = TreasuryPalletId; type WeightInfo = asset_handler::WeightInfo; type ParachainNetworkId = ParachainNetworkId; + type PolkadexAssetId = PolkadexAssetId; + type PDEXHolderAccount = PDEXHolderAccount; } impl thea::pallet::Config for Runtime { From 6d57592180acdce819680e9c2e14db6d2b5a32fe Mon Sep 17 00:00:00 2001 From: zktony Date: Fri, 10 Feb 2023 12:13:25 +0530 Subject: [PATCH 2/5] Added test case --- pallets/asset-handler/src/lib.rs | 5 +++- pallets/thea/src/lib.rs | 28 +++++++++++++++------- pallets/thea/src/mock.rs | 10 ++++++++ pallets/thea/src/tests.rs | 40 ++++++++++++++++++++++++++++++++ runtime/src/lib.rs | 2 ++ 5 files changed, 76 insertions(+), 9 deletions(-) diff --git a/pallets/asset-handler/src/lib.rs b/pallets/asset-handler/src/lib.rs index ddcbacf04..963f12ffd 100644 --- a/pallets/asset-handler/src/lib.rs +++ b/pallets/asset-handler/src/lib.rs @@ -682,7 +682,10 @@ pub mod pallet { pub fn lock_pdex_asset(amount: u128, who: T::AccountId) -> DispatchResult { let polkadex_holder_account = T::PDEXHolderAccount::get(); - T::Currency::transfer(&who, &polkadex_holder_account, amount.saturated_into(), ExistenceRequirement::KeepAlive) + let current_balance = T::Currency::free_balance(&who); + println!("Here 2 {:?} > {:?}", current_balance, amount); + + T::Currency::transfer(&who, &polkadex_holder_account, amount.saturated_into(), ExistenceRequirement::AllowDeath) } pub fn burn_thea_asset( diff --git a/pallets/thea/src/lib.rs b/pallets/thea/src/lib.rs index edcb1119f..1747671be 100644 --- a/pallets/thea/src/lib.rs +++ b/pallets/thea/src/lib.rs @@ -52,6 +52,7 @@ pub mod pallet { latest::{AssetId, Junction, Junctions, MultiAsset, MultiLocation, NetworkId}, prelude::{Fungible, X1}, }; + use thea_primitives::parachain_primitives::AssetType; pub type Network = u8; @@ -101,6 +102,8 @@ pub mod pallet { /// Total Withdrawals #[pallet::constant] type WithdrawalSize: Get; + /// Para Id + type ParaId: Get; } #[pallet::pallet] @@ -503,11 +506,13 @@ pub mod pallet { ) -> Result<(), DispatchError> { ensure!(beneficiary.len() <= 100, Error::::BeneficiaryTooLong); // TODO: This will be refactored when work on withdrawal so not fixing clippy suggestion - let (network, ..) = asset_handler::pallet::Pallet::::get_thea_assets(asset_id); + let (mut network, ..) = asset_handler::pallet::Pallet::::get_thea_assets(asset_id); + if asset_id == T::PolkadexAssetId::get() { + network = 1; + }; ensure!(network != 0, Error::::UnableFindNetworkForAssetId); let payload = Self::withdrawal_router(network, asset_id, amount, beneficiary.clone())?; let withdrawal_nonce = >::get(network); - let mut pending_withdrawals = >::get(network); // Ensure pending withdrawals have space for a new withdrawal @@ -536,10 +541,10 @@ pub mod pallet { )?; // TODO[#610]: Update Thea Staking pallet about fees collected - + println!("Here"); // Handle assets asset_handler::pallet::Pallet::::handle_asset(asset_id, user.clone(), amount)?; - + println!("Here 3"); let withdrawal = ApprovedWithdraw { asset_id, amount: amount.saturated_into(), @@ -593,10 +598,17 @@ pub mod pallet { amount: u128, beneficiary: Vec, ) -> Result, DispatchError> { - let (_, _, asset_identifier) = asset_handler::pallet::TheaAssets::::get(asset_id); - let asset_identifier: ParachainAsset = - Decode::decode(&mut &asset_identifier.to_vec()[..]) - .map_err(|_| Error::::FailedToDecode)?; + let asset_identifier = if asset_id != T::PolkadexAssetId::get() { + let (_, _, asset_identifier) = asset_handler::pallet::TheaAssets::::get(asset_id); + let asset_identifier: ParachainAsset = + Decode::decode(&mut &asset_identifier.to_vec()[..]) + .map_err(|_| Error::::FailedToDecode)?; + asset_identifier + } else { + let para_id = T::ParaId::get(); + let asset_location = MultiLocation{ parents: 1, interior: Junctions::X1(Junction::Parachain(para_id)) }; + ParachainAsset { location: asset_location, asset_type: AssetType::Fungible } + }; let asset_id = AssetId::Concrete(asset_identifier.location); let asset_and_amount = MultiAsset { id: asset_id, fun: Fungible(amount) }; let recipient: MultiLocation = Self::get_recipient(beneficiary)?; diff --git a/pallets/thea/src/mock.rs b/pallets/thea/src/mock.rs index 03c8413f7..b7b1ae575 100644 --- a/pallets/thea/src/mock.rs +++ b/pallets/thea/src/mock.rs @@ -28,6 +28,7 @@ use crate::pallet as thea; use asset_handler::pallet::WithdrawalLimit; use frame_support::PalletId; +use sp_core::crypto::AccountId32; use sp_runtime::traits::AccountIdConversion; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -148,6 +149,11 @@ impl chainbridge::Config for Test { //type PalletId = ChainbridgePalletId; } +parameter_types! { + pub const PolkadexAssetId: u128 = 1000; + pub const PDEXHolderAccount: u64 = 10u64; +} + impl asset_handler::pallet::Config for Test { type Event = Event; type Currency = Balances; @@ -156,11 +162,14 @@ impl asset_handler::pallet::Config for Test { type TreasuryPalletId = ChainbridgePalletId; type WeightInfo = asset_handler::weights::WeightInfo; type ParachainNetworkId = ParachainNetworkId; + type PolkadexAssetId = PolkadexAssetId; + type PDEXHolderAccount = PDEXHolderAccount; } parameter_types! { pub const TheaPalletId: PalletId = PalletId(*b"THBRIDGE"); pub const WithdrawalSize: u32 = 10; + pub const ParaId: u32 = 2040; } impl thea::Config for Test { @@ -169,6 +178,7 @@ impl thea::Config for Test { type AssetCreateUpdateOrigin = frame_system::EnsureSigned; type TheaPalletId = TheaPalletId; type WithdrawalSize = WithdrawalSize; + type ParaId = ParaId; } // Build genesis storage according to the mock runtime. diff --git a/pallets/thea/src/tests.rs b/pallets/thea/src/tests.rs index a7534a39b..ecdf5ea70 100644 --- a/pallets/thea/src/tests.rs +++ b/pallets/thea/src/tests.rs @@ -510,6 +510,46 @@ fn test_withdraw_with_no_fee_config() { }) } +#[test] +fn transfer_native_asset() { + new_test_ext().execute_with(|| { + let asset_id = 1000; + let para_id = 2040; + let multi_location = MultiLocation { + parents: 1, + interior: X1(Junction::AccountId32 { network: NetworkId::Any, id: [1; 32] }), + }; + let asset_location = MultiLocation { parents: 1, interior: Junctions::X1(Junction::Parachain(para_id)) }; + let asset = MultiAsset{ id: AssetId::Concrete(asset_location), fun: 10_000_000_000_000u128.into() }; + assert_ok!(Thea::set_withdrawal_fee(Origin::root(), 1, 0)); + let beneficiary: [u8; 32] = [1; 32]; + // Mint Asset to Alice + assert_ok!(pallet_balances::pallet::Pallet::::set_balance( + Origin::root(), + 1, + 1_000_000_000_000_000_000, + 0 + )); + assert_ok!(Thea::withdraw( + Origin::signed(1), + asset_id.clone(), + 10_000_000_000_000u128, + beneficiary.to_vec(), + false + )); + let pending_withdrawal = >::get(1); + let payload = ParachainWithdraw::get_parachain_withdraw(asset, multi_location); + let approved_withdraw = ApprovedWithdraw { + asset_id: asset_id, + amount: 10_000_000_000_000u128, + network: 1, + beneficiary: vec![1; 32], + payload: payload.encode(), + }; + assert_eq!(pending_withdrawal.to_vec().pop().unwrap(), approved_withdraw); + }) +} + pub type PrivateKeys = Vec; pub type PublicKeys = Vec; diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index fe0e83fed..b6bbe77f7 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1292,6 +1292,7 @@ impl chainbridge::Config for Runtime { parameter_types! { pub const PolkadexAssetId: u128 = 1000; //TODO: Chnage Polkddex Asset ID pub const PDEXHolderAccount: AccountId32 = AccountId32::new([1u8;32]); //TODO Chnage Holder Account + pub const ParaId: u32 = 2040; } impl asset_handler::pallet::Config for Runtime { @@ -1312,6 +1313,7 @@ impl thea::pallet::Config for Runtime { type AssetCreateUpdateOrigin = EnsureRootOrHalfCouncil; type TheaPalletId = TheaPalletId; type WithdrawalSize = WithdrawalSize; + type ParaId = ParaId; } //Install Staking Pallet From 5c707c776b9dc9a549ee5e13a559c4ba903b6640 Mon Sep 17 00:00:00 2001 From: zktony Date: Fri, 10 Feb 2023 12:21:45 +0530 Subject: [PATCH 3/5] Formatted --- pallets/asset-handler/src/lib.rs | 10 ++++++---- pallets/thea/src/lib.rs | 13 +++++++------ pallets/thea/src/tests.rs | 10 +++++++--- runtime/src/lib.rs | 2 +- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/pallets/asset-handler/src/lib.rs b/pallets/asset-handler/src/lib.rs index 963f12ffd..c8a668e0d 100644 --- a/pallets/asset-handler/src/lib.rs +++ b/pallets/asset-handler/src/lib.rs @@ -682,10 +682,12 @@ pub mod pallet { pub fn lock_pdex_asset(amount: u128, who: T::AccountId) -> DispatchResult { let polkadex_holder_account = T::PDEXHolderAccount::get(); - let current_balance = T::Currency::free_balance(&who); - println!("Here 2 {:?} > {:?}", current_balance, amount); - - T::Currency::transfer(&who, &polkadex_holder_account, amount.saturated_into(), ExistenceRequirement::AllowDeath) + T::Currency::transfer( + &who, + &polkadex_holder_account, + amount.saturated_into(), + ExistenceRequirement::AllowDeath, + ) } pub fn burn_thea_asset( diff --git a/pallets/thea/src/lib.rs b/pallets/thea/src/lib.rs index 1747671be..9161de87c 100644 --- a/pallets/thea/src/lib.rs +++ b/pallets/thea/src/lib.rs @@ -43,7 +43,7 @@ pub mod pallet { }; use thea_primitives::{ normal_deposit::Deposit, - parachain_primitives::{ParachainAsset, ParachainDeposit, ParachainWithdraw}, + parachain_primitives::{AssetType, ParachainAsset, ParachainDeposit, ParachainWithdraw}, thea_types::OnSessionChange, ApprovedWithdraw, AssetIdConverter, BLSPublicKey, TokenType, }; @@ -52,7 +52,6 @@ pub mod pallet { latest::{AssetId, Junction, Junctions, MultiAsset, MultiLocation, NetworkId}, prelude::{Fungible, X1}, }; - use thea_primitives::parachain_primitives::AssetType; pub type Network = u8; @@ -541,10 +540,8 @@ pub mod pallet { )?; // TODO[#610]: Update Thea Staking pallet about fees collected - println!("Here"); // Handle assets asset_handler::pallet::Pallet::::handle_asset(asset_id, user.clone(), amount)?; - println!("Here 3"); let withdrawal = ApprovedWithdraw { asset_id, amount: amount.saturated_into(), @@ -599,14 +596,18 @@ pub mod pallet { beneficiary: Vec, ) -> Result, DispatchError> { let asset_identifier = if asset_id != T::PolkadexAssetId::get() { - let (_, _, asset_identifier) = asset_handler::pallet::TheaAssets::::get(asset_id); + let (_, _, asset_identifier) = + asset_handler::pallet::TheaAssets::::get(asset_id); let asset_identifier: ParachainAsset = Decode::decode(&mut &asset_identifier.to_vec()[..]) .map_err(|_| Error::::FailedToDecode)?; asset_identifier } else { let para_id = T::ParaId::get(); - let asset_location = MultiLocation{ parents: 1, interior: Junctions::X1(Junction::Parachain(para_id)) }; + let asset_location = MultiLocation { + parents: 1, + interior: Junctions::X1(Junction::Parachain(para_id)), + }; ParachainAsset { location: asset_location, asset_type: AssetType::Fungible } }; let asset_id = AssetId::Concrete(asset_identifier.location); diff --git a/pallets/thea/src/tests.rs b/pallets/thea/src/tests.rs index ecdf5ea70..768d94cfa 100644 --- a/pallets/thea/src/tests.rs +++ b/pallets/thea/src/tests.rs @@ -519,8 +519,12 @@ fn transfer_native_asset() { parents: 1, interior: X1(Junction::AccountId32 { network: NetworkId::Any, id: [1; 32] }), }; - let asset_location = MultiLocation { parents: 1, interior: Junctions::X1(Junction::Parachain(para_id)) }; - let asset = MultiAsset{ id: AssetId::Concrete(asset_location), fun: 10_000_000_000_000u128.into() }; + let asset_location = + MultiLocation { parents: 1, interior: Junctions::X1(Junction::Parachain(para_id)) }; + let asset = MultiAsset { + id: AssetId::Concrete(asset_location), + fun: 10_000_000_000_000u128.into(), + }; assert_ok!(Thea::set_withdrawal_fee(Origin::root(), 1, 0)); let beneficiary: [u8; 32] = [1; 32]; // Mint Asset to Alice @@ -540,7 +544,7 @@ fn transfer_native_asset() { let pending_withdrawal = >::get(1); let payload = ParachainWithdraw::get_parachain_withdraw(asset, multi_location); let approved_withdraw = ApprovedWithdraw { - asset_id: asset_id, + asset_id, amount: 10_000_000_000_000u128, network: 1, beneficiary: vec![1; 32], diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index b6bbe77f7..f82afdadc 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -1290,7 +1290,7 @@ impl chainbridge::Config for Runtime { } parameter_types! { - pub const PolkadexAssetId: u128 = 1000; //TODO: Chnage Polkddex Asset ID + pub const PolkadexAssetId: u128 = 1000; //TODO: Chnage Polkddex Asset ID pub const PDEXHolderAccount: AccountId32 = AccountId32::new([1u8;32]); //TODO Chnage Holder Account pub const ParaId: u32 = 2040; } From 44c4afd725ef0f08b5a715831064239c8b4c5b70 Mon Sep 17 00:00:00 2001 From: zktony Date: Fri, 10 Feb 2023 13:02:44 +0530 Subject: [PATCH 4/5] Fixed test cases --- pallets/asset-handler/src/mock.rs | 7 +++++++ pallets/thea-staking/src/mock.rs | 9 +++++++++ pallets/thea/src/lib.rs | 1 - 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/pallets/asset-handler/src/mock.rs b/pallets/asset-handler/src/mock.rs index 48f0b0577..7e2aecbb2 100644 --- a/pallets/asset-handler/src/mock.rs +++ b/pallets/asset-handler/src/mock.rs @@ -145,6 +145,11 @@ impl chainbridge::Config for Test { //type PalletId = ChainbridgePalletId; } +parameter_types! { + pub const PolkadexAssetId: u128 = 1000; + pub const PDEXHolderAccount: u64 = 10u64; +} + impl asset_handler::Config for Test { type Event = Event; type Currency = Balances; @@ -153,6 +158,8 @@ impl asset_handler::Config for Test { type TreasuryPalletId = ChainbridgePalletId; type WeightInfo = crate::weights::WeightInfo; type ParachainNetworkId = ParachainNetworkId; + type PolkadexAssetId = PolkadexAssetId; + type PDEXHolderAccount = PDEXHolderAccount; } // Build genesis storage according to the mock runtime. diff --git a/pallets/thea-staking/src/mock.rs b/pallets/thea-staking/src/mock.rs index ac37f3d80..ccb4e824d 100644 --- a/pallets/thea-staking/src/mock.rs +++ b/pallets/thea-staking/src/mock.rs @@ -113,6 +113,11 @@ impl chainbridge::Config for Test { type ProposalLifetime = ProposalLifetime; } +parameter_types! { + pub const PolkadexAssetId: u128 = 1000; + pub const PDEXHolderAccount: u64 = 10u64; +} + impl asset_handler::pallet::Config for Test { type Event = Event; type Currency = Balances; @@ -121,11 +126,14 @@ impl asset_handler::pallet::Config for Test { type TreasuryPalletId = ChainbridgePalletId; type WeightInfo = asset_handler::weights::WeightInfo; type ParachainNetworkId = ParachainNetworkId; + type PolkadexAssetId = PolkadexAssetId; + type PDEXHolderAccount = PDEXHolderAccount; } parameter_types! { pub const TheaPalletId: PalletId = PalletId(*b"THBRIDGE"); pub const WithdrawalSize: u32 = 10; + pub const ParaId: u32 = 2040; } impl thea::pallet::Config for Test { @@ -134,6 +142,7 @@ impl thea::pallet::Config for Test { type AssetCreateUpdateOrigin = frame_system::EnsureSigned; type TheaPalletId = TheaPalletId; type WithdrawalSize = WithdrawalSize; + type ParaId = ParaId; } //defined trait for Session Change diff --git a/pallets/thea/src/lib.rs b/pallets/thea/src/lib.rs index 9161de87c..325ba8835 100644 --- a/pallets/thea/src/lib.rs +++ b/pallets/thea/src/lib.rs @@ -513,7 +513,6 @@ pub mod pallet { let payload = Self::withdrawal_router(network, asset_id, amount, beneficiary.clone())?; let withdrawal_nonce = >::get(network); let mut pending_withdrawals = >::get(network); - // Ensure pending withdrawals have space for a new withdrawal ensure!(!pending_withdrawals.is_full(), Error::::WithdrawalNotAllowed); From 6750d371cbcc6909dceb8b6fce0725b46d52f385 Mon Sep 17 00:00:00 2001 From: zktony Date: Wed, 15 Feb 2023 18:07:11 +0530 Subject: [PATCH 5/5] Fixed Serhi's comment --- pallets/asset-handler/src/lib.rs | 11 +++++++++++ pallets/thea/src/lib.rs | 9 +++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/pallets/asset-handler/src/lib.rs b/pallets/asset-handler/src/lib.rs index c8a668e0d..5afdafa06 100644 --- a/pallets/asset-handler/src/lib.rs +++ b/pallets/asset-handler/src/lib.rs @@ -667,6 +667,12 @@ pub mod pallet { Ok(()) } + /// Asset Handler for Withdraw Extrinsic + /// # Parameters + /// + /// * `asset_id`: Asset Id. + /// * `who`: Asset Holder. + /// * `amount`: Amount to be burned/locked. pub fn handle_asset( asset_id: u128, who: T::AccountId, @@ -680,6 +686,11 @@ pub mod pallet { } } + /// Asset Locker + /// # Parameters + /// + /// * `amount`: Amount to be locked. + /// * `who`: Asset Holder. pub fn lock_pdex_asset(amount: u128, who: T::AccountId) -> DispatchResult { let polkadex_holder_account = T::PDEXHolderAccount::get(); T::Currency::transfer( diff --git a/pallets/thea/src/lib.rs b/pallets/thea/src/lib.rs index 325ba8835..28c5c993c 100644 --- a/pallets/thea/src/lib.rs +++ b/pallets/thea/src/lib.rs @@ -504,10 +504,11 @@ pub mod pallet { pay_for_remaining: bool, ) -> Result<(), DispatchError> { ensure!(beneficiary.len() <= 100, Error::::BeneficiaryTooLong); - // TODO: This will be refactored when work on withdrawal so not fixing clippy suggestion - let (mut network, ..) = asset_handler::pallet::Pallet::::get_thea_assets(asset_id); - if asset_id == T::PolkadexAssetId::get() { - network = 1; + let network = if asset_id == T::PolkadexAssetId::get() { + 1 + } else { + let (network, ..) = asset_handler::pallet::Pallet::::get_thea_assets(asset_id); + network }; ensure!(network != 0, Error::::UnableFindNetworkForAssetId); let payload = Self::withdrawal_router(network, asset_id, amount, beneficiary.clone())?;