use crate::xcm_config;
use alloc::{boxed::Box, vec};
use codec::{Decode, Encode};
use core::marker::PhantomData;
use frame_support::pallet_prelude::DispatchResult;
use frame_system::RawOrigin;
use polkadot_primitives::Balance;
use polkadot_runtime_common::identity_migrator::{OnReapIdentity, WeightInfo};
use westend_runtime_constants::currency::*;
use xcm::{latest::prelude::*, VersionedLocation, VersionedXcm};
use xcm_executor::traits::TransactAsset;
#[derive(Encode, Decode)]
enum PeopleRuntimePallets<AccountId: Encode> {
#[codec(index = 248)]
IdentityMigrator(IdentityMigratorCalls<AccountId>),
}
#[derive(Encode, Decode)]
enum IdentityMigratorCalls<AccountId: Encode> {
#[codec(index = 1)]
PokeDeposit(AccountId),
}
pub struct ToParachainIdentityReaper<Runtime, AccountId>(PhantomData<(Runtime, AccountId)>);
impl<Runtime, AccountId> ToParachainIdentityReaper<Runtime, AccountId> {
fn calculate_remote_deposit(bytes: u32, subs: u32) -> Balance {
let para_basic_deposit = deposit(1, 17) / 100;
let para_byte_deposit = deposit(0, 1) / 100;
let para_sub_account_deposit = deposit(1, 53) / 100;
let para_existential_deposit = EXISTENTIAL_DEPOSIT / 10;
let id_deposit =
para_basic_deposit.saturating_add(para_byte_deposit.saturating_mul(bytes as Balance));
let subs_deposit = para_sub_account_deposit.saturating_mul(subs as Balance);
id_deposit
.saturating_add(subs_deposit)
.saturating_add(para_existential_deposit.saturating_mul(2))
}
}
impl<Runtime, AccountId> OnReapIdentity<AccountId> for ToParachainIdentityReaper<Runtime, AccountId>
where
Runtime: frame_system::Config + pallet_xcm::Config,
AccountId: Into<[u8; 32]> + Clone + Encode,
{
fn on_reap_identity(who: &AccountId, fields: u32, subs: u32) -> DispatchResult {
use crate::{
impls::IdentityMigratorCalls::PokeDeposit,
weights::polkadot_runtime_common_identity_migrator::WeightInfo as MigratorWeights,
};
let total_to_send = Self::calculate_remote_deposit(fields, subs);
let wnd = Asset { id: AssetId(Here.into_location()), fun: Fungible(total_to_send) };
let destination: Location = Location::new(0, Parachain(1004));
let who_origin =
Junction::AccountId32 { network: None, id: who.clone().into() }.into_location();
let _withdrawn = xcm_config::LocalAssetTransactor::withdraw_asset(&wnd, &who_origin, None)
.map_err(|err| {
log::error!(
target: "runtime::on_reap_identity",
"withdraw_asset(what: {:?}, who_origin: {:?}) error: {:?}",
wnd, who_origin, err
);
pallet_xcm::Error::<Runtime>::LowBalance
})?;
xcm_config::LocalAssetTransactor::can_check_out(
&destination,
&wnd,
&XcmContext { origin: None, message_id: [0; 32], topic: None },
)
.map_err(|err| {
log::error!(
target: "runtime::on_reap_identity",
"can_check_out(destination: {:?}, asset: {:?}, _) error: {:?}",
destination, wnd, err
);
pallet_xcm::Error::<Runtime>::CannotCheckOutTeleport
})?;
xcm_config::LocalAssetTransactor::check_out(
&destination,
&wnd,
&XcmContext { origin: None, message_id: [0; 32], topic: None },
);
let wnd_reanchored: Assets =
vec![Asset { id: AssetId(Location::new(1, Here)), fun: Fungible(total_to_send) }]
.into();
let poke = PeopleRuntimePallets::<AccountId>::IdentityMigrator(PokeDeposit(who.clone()));
let remote_weight_limit = MigratorWeights::<Runtime>::poke_deposit().saturating_mul(2);
let program: Xcm<()> = Xcm(vec![
UnpaidExecution { weight_limit: Unlimited, check_origin: None },
ReceiveTeleportedAsset(wnd_reanchored),
DepositAsset {
assets: Wild(AllCounted(1)),
beneficiary: Junction::AccountId32 { network: None, id: who.clone().into() }
.into_location()
.into(),
},
Transact {
origin_kind: OriginKind::Superuser,
call: poke.encode().into(),
fallback_max_weight: Some(remote_weight_limit),
},
]);
let _ = <pallet_xcm::Pallet<Runtime>>::send(
RawOrigin::Root.into(),
Box::new(VersionedLocation::from(destination)),
Box::new(VersionedXcm::from(program)),
)?;
Ok(())
}
#[cfg(feature = "runtime-benchmarks")]
fn ensure_successful_identity_reaping(_: &AccountId, _: u32, _: u32) {
crate::Dmp::make_parachain_reachable(1004);
}
}