Skip to content

Commit

Permalink
add test for start_foreign_asset_migration call
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmadkaouk committed Nov 14, 2024
1 parent 3f152f7 commit eaf41f6
Show file tree
Hide file tree
Showing 5 changed files with 405 additions and 87 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pallets/moonbeam-lazy-migrations/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ frame-benchmarking = { workspace = true, optional = true }
frame-benchmarking = { workspace = true, features = ["std"] }
pallet-balances = { workspace = true, features = ["std", "insecure_zero_ed"] }
pallet-timestamp = { workspace = true, features = ["std"] }
precompile-utils = { workspace = true, features = ["std"] }
rlp = { workspace = true, features = ["std"] }
sp-io = { workspace = true, features = ["std"] }

Expand All @@ -58,6 +59,7 @@ std = [
"pallet-assets/std",
"pallet-moonbeam-foreign-assets/std",
"pallet-asset-manager/std",
"precompile-utils/std",
"cumulus-primitives-storage-weight-reclaim/std",
"rlp/std",
"xcm-primitives/std",
Expand Down
79 changes: 39 additions & 40 deletions pallets/moonbeam-lazy-migrations/src/foreign_asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ impl Default for ForeignAssetMigrationStatus {

#[derive(Encode, Decode, scale_info::TypeInfo, PartialEq, MaxEncodedLen)]
pub(super) struct ForeignAssetMigreationInfo {
asset_id: u128,
remaining_balances: u32,
remaining_approvals: u32,
pub(super) asset_id: u128,
pub(super) remaining_balances: u32,
pub(super) remaining_approvals: u32,
}

impl<T: Config> Pallet<T>
Expand All @@ -61,44 +61,43 @@ where
Error::<T>::MigrationNotFinished
);

let asset =
pallet_assets::Asset::<T>::get(asset_id).ok_or(Error::<T>::AssetNotFound)?;

// Freeze the asset
pallet_assets::Pallet::<T>::freeze_asset(origin.clone(), asset_id.into())?;

let decimals = pallet_assets::Pallet::<T>::decimals(asset_id);

let symbol = pallet_assets::Pallet::<T>::symbol(asset_id)
.try_into()
.map_err(|_| Error::<T>::SymbolTooLong)?;

let name = <pallet_assets::Pallet<T> as Inspect<_>>::name(asset_id)
.try_into()
.map_err(|_| Error::<T>::NameTooLong)?;

let xcm_location: Location =
pallet_asset_manager::Pallet::<T>::get_asset_type(asset_id)
.ok_or(Error::<T>::AssetTypeNotFound)?
.into()
.ok_or(Error::<T>::LocationNotFound)?;

// Create the SC for the asset with moonbeam foreign assets pallet
pallet_moonbeam_foreign_assets::Pallet::<T>::create_foreign_asset(
origin,
asset_id,
xcm_location,
decimals,
symbol,
name,
)?;

*status = ForeignAssetMigrationStatus::Migrating(ForeignAssetMigreationInfo {
asset_id,
remaining_balances: asset.accounts,
remaining_approvals: asset.approvals,
});
Ok(())
pallet_assets::Asset::<T>::try_mutate_exists(asset_id, |maybe_details| {
let details = maybe_details.as_mut().ok_or(Error::<T>::AssetNotFound)?;

details.status = pallet_assets::AssetStatus::Frozen;

let decimals = pallet_assets::Pallet::<T>::decimals(asset_id);
let symbol = pallet_assets::Pallet::<T>::symbol(asset_id)
.try_into()
.map_err(|_| Error::<T>::SymbolTooLong)?;
let name = <pallet_assets::Pallet<T> as Inspect<_>>::name(asset_id)
.try_into()
.map_err(|_| Error::<T>::NameTooLong)?;
let xcm_location: Location =
pallet_asset_manager::Pallet::<T>::get_asset_type(asset_id)
.ok_or(Error::<T>::AssetTypeNotFound)?
.into()
.ok_or(Error::<T>::LocationNotFound)?;

// Create the SC for the asset with moonbeam foreign assets pallet
pallet_moonbeam_foreign_assets::Pallet::<T>::create_foreign_asset(
origin,
asset_id,
xcm_location,
decimals,
symbol,
name,
)?;

*status = ForeignAssetMigrationStatus::Migrating(ForeignAssetMigreationInfo {
asset_id,
remaining_balances: details.accounts,
remaining_approvals: details.approvals,
});

Ok(())
})
})
}

Expand Down
186 changes: 153 additions & 33 deletions pallets/moonbeam-lazy-migrations/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,25 @@
use super::*;
use crate as pallet_moonbeam_lazy_migrations;
use frame_support::traits::AsEnsureOriginWithArg;
use frame_support::{
construct_runtime, ord_parameter_types, parameter_types,
traits::{EqualPrivilegeOnly, Everything, SortedMembers},
weights::{RuntimeDbWeight, Weight},
};
use frame_system::EnsureRoot;
use pallet_evm::{AddressMapping, EnsureAddressTruncated};
use frame_system::{EnsureRoot, EnsureSigned};
use pallet_asset_manager::AssetRegistrar;
use pallet_evm::{EnsureAddressNever, EnsureAddressRoot};
use precompile_utils::testing::MockAccount;
use sp_core::{ConstU32, H160, H256, U256};
use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup},
AccountId32, BuildStorage, Perbill,
traits::{BlakeTwo256, Hash, IdentityLookup},
BuildStorage, Perbill,
};

pub type AssetId = u128;
pub type Balance = u128;
pub type AccountId = MockAccount;
type Block = frame_system::mocking::MockBlock<Test>;

// Configure a mock runtime to test the pallet.
Expand All @@ -44,6 +49,9 @@ construct_runtime!(
EVM: pallet_evm,
LazyMigrations: pallet_moonbeam_lazy_migrations::{Pallet, Call},
Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event<T>},
Assets: pallet_assets::{Pallet, Call, Storage, Event<T>},
AssetManager: pallet_asset_manager::{Pallet, Call, Storage, Event<T>},
MoonbeamForeignAssets: pallet_moonbeam_foreign_assets::{Pallet, Call, Storage, Event<T>},
}
);

Expand Down Expand Up @@ -72,7 +80,7 @@ impl frame_system::Config for Test {
type RuntimeCall = RuntimeCall;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = AccountId32;
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = BlockHashCount;
Expand Down Expand Up @@ -154,40 +162,21 @@ impl pallet_timestamp::Config for Test {
type WeightInfo = ();
}

const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
/// Block Storage Limit in bytes. Set to 40KB.
const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024;

parameter_types! {
pub BlockGasLimit: U256 = U256::from(u64::MAX);
pub WeightPerGas: Weight = Weight::from_parts(1, 0);
pub GasLimitPovSizeRatio: u64 = {
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
block_gas_limit.saturating_div(MAX_POV_SIZE)
};
pub GasLimitStorageGrowthRatio: u64 = {
let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
block_gas_limit.saturating_div(BLOCK_STORAGE_LIMIT)
};
pub const WeightPerGas: Weight = Weight::from_parts(1, 0);
pub GasLimitPovSizeRatio: u64 = 16;
pub GasLimitStorageGrowthRatio: u64 = 366;
pub SuicideQuickClearLimit: u32 = 0;
}
pub struct HashedAddressMapping;

impl AddressMapping<AccountId32> for HashedAddressMapping {
fn into_account_id(address: H160) -> AccountId32 {
let mut data = [0u8; 32];
data[0..20].copy_from_slice(&address[..]);
AccountId32::from(Into::<[u8; 32]>::into(data))
}
}

impl pallet_evm::Config for Test {
type FeeCalculator = ();
type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
type WeightPerGas = WeightPerGas;
type CallOrigin = EnsureAddressTruncated;
type WithdrawOrigin = EnsureAddressTruncated;
type AddressMapping = HashedAddressMapping;
type CallOrigin = EnsureAddressRoot<AccountId>;
type WithdrawOrigin = EnsureAddressNever<AccountId>;
type AddressMapping = AccountId;
type Currency = Balances;
type RuntimeEvent = RuntimeEvent;
type Runner = pallet_evm::runner::stack::Runner<Self>;
Expand All @@ -202,23 +191,154 @@ impl pallet_evm::Config for Test {
type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio;
type Timestamp = Timestamp;
type WeightInfo = pallet_evm::weights::SubstrateWeight<Test>;
type WeightInfo = ();
type SuicideQuickClearLimit = SuicideQuickClearLimit;
}

parameter_types! {
pub const AssetDeposit: u128 = 1;
pub const MetadataDepositBase: u128 = 1;
pub const MetadataDepositPerByte: u128 = 1;
pub const ApprovalDeposit: u128 = 1;
pub const AssetsStringLimit: u32 = 50;
pub const AssetAccountDeposit: u128 = 1;
}

impl pallet_assets::Config<()> for Test {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type AssetId = AssetId;
type Currency = Balances;
type ForceOrigin = EnsureRoot<AccountId>;
type AssetDeposit = AssetDeposit;
type MetadataDepositBase = MetadataDepositBase;
type MetadataDepositPerByte = MetadataDepositPerByte;
type ApprovalDeposit = ApprovalDeposit;
type StringLimit = AssetsStringLimit;
type Freezer = ();
type Extra = ();
type AssetAccountDeposit = AssetAccountDeposit;
type WeightInfo = ();
type RemoveItemsLimit = ConstU32<656>;
type AssetIdParameter = AssetId;
type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
type CallbackHandle = ();
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, TypeInfo)]
pub enum MockAssetType {
Xcm(Location),
MockAsset(AssetId),
}

impl Default for MockAssetType {
fn default() -> Self {
Self::MockAsset(0)
}
}

impl From<MockAssetType> for AssetId {
fn from(asset: MockAssetType) -> AssetId {
match asset {
MockAssetType::MockAsset(id) => id,
MockAssetType::Xcm(id) => {
let mut result: [u8; 16] = [0u8; 16];
let hash: H256 = id.using_encoded(<Test as frame_system::Config>::Hashing::hash);
result.copy_from_slice(&hash.as_fixed_bytes()[0..16]);
u128::from_le_bytes(result)
}
}
}
}

impl From<Location> for MockAssetType {
fn from(location: Location) -> Self {
Self::Xcm(location)
}
}

impl Into<Option<Location>> for MockAssetType {
fn into(self) -> Option<Location> {
match self {
Self::Xcm(location) => Some(location),
_ => None,
}
}
}

pub struct MockAssetPalletRegistrar;

impl AssetRegistrar<Test> for MockAssetPalletRegistrar {
fn create_foreign_asset(
_asset: u128,
_min_balance: u128,
_metadata: u32,
_is_sufficient: bool,
) -> Result<(), DispatchError> {
Ok(())
}

fn destroy_foreign_asset(_asset: u128) -> Result<(), DispatchError> {
Ok(())
}

fn destroy_asset_dispatch_info_weight(_asset: u128) -> Weight {
Weight::from_parts(0, 0)
}
}

impl pallet_asset_manager::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type AssetId = AssetId;
type AssetRegistrarMetadata = u32;
type ForeignAssetType = MockAssetType;
type AssetRegistrar = MockAssetPalletRegistrar;
type ForeignAssetModifierOrigin = EnsureRoot<AccountId>;
type WeightInfo = ();
}

pub struct AccountIdToH160;
impl sp_runtime::traits::Convert<AccountId, H160> for AccountIdToH160 {
fn convert(account_id: AccountId) -> H160 {
account_id.into()
}
}

impl pallet_moonbeam_foreign_assets::Config for Test {
type AccountIdToH160 = AccountIdToH160;
type AssetIdFilter = Everything;
type EvmRunner = pallet_evm::runner::stack::Runner<Self>;
type ForeignAssetCreatorOrigin = EnsureRoot<AccountId>;
type ForeignAssetFreezerOrigin = EnsureRoot<AccountId>;
type ForeignAssetModifierOrigin = EnsureRoot<AccountId>;
type ForeignAssetUnfreezerOrigin = EnsureRoot<AccountId>;
type OnForeignAssetCreated = ();
type MaxForeignAssets = ConstU32<3>;
type RuntimeEvent = RuntimeEvent;
type WeightInfo = ();
type XcmLocationToH160 = ();
}

impl Config for Test {
type WeightInfo = ();
type ForeignAssetMigratorOrigin = EnsureRoot<AccountId>;
}

/// Externality builder for pallet migration's mock runtime
pub(crate) struct ExtBuilder {
// endowed accounts with balances
balances: Vec<(AccountId32, Balance)>,
balances: Vec<(AccountId, Balance)>,
}

impl Default for ExtBuilder {
fn default() -> ExtBuilder {
ExtBuilder { balances: vec![] }
ExtBuilder {
balances: vec![
(AccountId::from([1; 20]), 1000),
(AccountId::from([2; 20]), 1000),
],
}
}
}

Expand Down
Loading

0 comments on commit eaf41f6

Please sign in to comment.