use super::{
currency, governance, xcm_config, AccountId, AssetId, AssetManager, Assets, Balance, Balances,
OpenTechCommitteeInstance, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX,
};
use super::moonbeam_weights;
use frame_support::{
dispatch::GetDispatchInfo,
parameter_types,
traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, EitherOfDiverse},
weights::Weight,
};
use moonkit_xcm_primitives::AccountIdAssetIdConversion;
use frame_system::{EnsureNever, EnsureRoot};
use sp_core::H160;
use parity_scale_codec::{Compact, Decode, Encode};
use scale_info::TypeInfo;
use sp_std::{
convert::{From, Into},
prelude::*,
};
const REMOVE_ITEMS_LIMIT: u32 = 656;
pub type ForeignAssetInstance = ();
parameter_types! {
pub const AssetDeposit: Balance = 100 * currency::GLMR * currency::SUPPLY_FACTOR;
pub const ApprovalDeposit: Balance = 0;
pub const AssetsStringLimit: u32 = 50;
pub const MetadataDepositBase: Balance = currency::deposit(1,68);
pub const MetadataDepositPerByte: Balance = currency::deposit(0, 1);
}
pub type AssetsForceOrigin =
EitherOfDiverse<EnsureRoot<AccountId>, governance::custom_origins::GeneralAdmin>;
pallet_assets::runtime_benchmarks_enabled! {
pub struct BenchmarkHelper;
impl<AssetIdParameter> pallet_assets::BenchmarkHelper<AssetIdParameter> for BenchmarkHelper
where
AssetIdParameter: From<u128>,
{
fn create_asset_id_parameter(id: u32) -> AssetIdParameter {
(id as u128).into()
}
}
}
impl pallet_assets::Config<ForeignAssetInstance> for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type AssetId = AssetId;
type Currency = Balances;
type ForceOrigin = AssetsForceOrigin;
type AssetDeposit = AssetDeposit;
type MetadataDepositBase = MetadataDepositBase;
type MetadataDepositPerByte = MetadataDepositPerByte;
type ApprovalDeposit = ApprovalDeposit;
type StringLimit = AssetsStringLimit;
type Freezer = ();
type Extra = ();
type AssetAccountDeposit = ConstU128<{ currency::deposit(1, 18) }>;
type WeightInfo = moonbeam_weights::pallet_assets::WeightInfo<Runtime>;
type RemoveItemsLimit = ConstU32<{ REMOVE_ITEMS_LIMIT }>;
type AssetIdParameter = Compact<AssetId>;
type CreateOrigin = AsEnsureOriginWithArg<EnsureNever<AccountId>>;
type CallbackHandle = ();
pallet_assets::runtime_benchmarks_enabled! {
type BenchmarkHelper = BenchmarkHelper;
}
}
pub struct AssetRegistrar;
use frame_support::{pallet_prelude::DispatchResult, transactional};
impl pallet_asset_manager::AssetRegistrar<Runtime> for AssetRegistrar {
#[transactional]
fn create_foreign_asset(
asset: AssetId,
min_balance: Balance,
metadata: AssetRegistrarMetadata,
is_sufficient: bool,
) -> DispatchResult {
Assets::force_create(
RuntimeOrigin::root(),
asset.into(),
AssetManager::account_id(),
is_sufficient,
min_balance,
)?;
Assets::force_set_metadata(
RuntimeOrigin::root(),
asset.into(),
metadata.name,
metadata.symbol,
metadata.decimals,
metadata.is_frozen,
)
}
#[transactional]
fn destroy_foreign_asset(asset: AssetId) -> DispatchResult {
Assets::start_destroy(RuntimeOrigin::root(), asset.into())
}
fn destroy_asset_dispatch_info_weight(asset: AssetId) -> Weight {
RuntimeCall::Assets(
pallet_assets::Call::<Runtime, ForeignAssetInstance>::start_destroy {
id: asset.into(),
},
)
.get_dispatch_info()
.weight
}
}
#[derive(Clone, Default, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
pub struct AssetRegistrarMetadata {
pub name: Vec<u8>,
pub symbol: Vec<u8>,
pub decimals: u8,
pub is_frozen: bool,
}
pub type ForeignAssetModifierOrigin = EitherOfDiverse<
EnsureRoot<AccountId>,
EitherOfDiverse<
pallet_collective::EnsureProportionMoreThan<AccountId, OpenTechCommitteeInstance, 5, 9>,
governance::custom_origins::GeneralAdmin,
>,
>;
impl pallet_asset_manager::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type AssetId = AssetId;
type AssetRegistrarMetadata = AssetRegistrarMetadata;
type ForeignAssetType = xcm_config::AssetType;
type AssetRegistrar = AssetRegistrar;
type ForeignAssetModifierOrigin = ForeignAssetModifierOrigin;
type WeightInfo = moonbeam_weights::pallet_asset_manager::WeightInfo<Runtime>;
}
impl AccountIdAssetIdConversion<AccountId, AssetId> for Runtime {
fn account_to_asset_id(account: AccountId) -> Option<(Vec<u8>, AssetId)> {
let h160_account: H160 = account.into();
let mut data = [0u8; 16];
let (prefix_part, id_part) = h160_account.as_fixed_bytes().split_at(4);
if prefix_part == FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX {
data.copy_from_slice(id_part);
let asset_id: AssetId = u128::from_be_bytes(data).into();
Some((prefix_part.to_vec(), asset_id))
} else {
None
}
}
fn asset_id_to_account(prefix: &[u8], asset_id: AssetId) -> AccountId {
let mut data = [0u8; 20];
data[0..4].copy_from_slice(prefix);
data[4..20].copy_from_slice(&asset_id.to_be_bytes());
AccountId::from(data)
}
}