mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 07:01:03 +00:00
Check out/in assets when teleporting to maintain total issuance (#3007)
* Check out/in assets when teleporting to maintain total issuance * Fixes * Fixes * Fixes * Fixes * Update xcm/xcm-executor/src/traits/transact_asset.rs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com> * Docs Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
@@ -16,8 +16,8 @@
|
||||
|
||||
use sp_std::{result, convert::TryInto, marker::PhantomData};
|
||||
use xcm::v0::{Error as XcmError, Result, MultiAsset, MultiLocation};
|
||||
use sp_runtime::traits::SaturatedConversion;
|
||||
use frame_support::traits::{ExistenceRequirement::AllowDeath, WithdrawReasons};
|
||||
use sp_runtime::traits::{SaturatedConversion, CheckedSub};
|
||||
use frame_support::traits::{ExistenceRequirement::AllowDeath, WithdrawReasons, Get};
|
||||
use xcm_executor::traits::{MatchesFungible, Convert, TransactAsset};
|
||||
use xcm_executor::Assets;
|
||||
|
||||
@@ -43,8 +43,8 @@ impl From<Error> for XcmError {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CurrencyAdapter<Currency, Matcher, AccountIdConverter, AccountId>(
|
||||
PhantomData<(Currency, Matcher, AccountIdConverter, AccountId)>
|
||||
pub struct CurrencyAdapter<Currency, Matcher, AccountIdConverter, AccountId, CheckedAccount>(
|
||||
PhantomData<(Currency, Matcher, AccountIdConverter, AccountId, CheckedAccount)>
|
||||
);
|
||||
|
||||
impl<
|
||||
@@ -52,7 +52,38 @@ impl<
|
||||
AccountIdConverter: Convert<MultiLocation, AccountId>,
|
||||
Currency: frame_support::traits::Currency<AccountId>,
|
||||
AccountId: Clone, // can't get away without it since Currency is generic over it.
|
||||
> TransactAsset for CurrencyAdapter<Currency, Matcher, AccountIdConverter, AccountId> {
|
||||
CheckedAccount: Get<Option<AccountId>>,
|
||||
> TransactAsset for CurrencyAdapter<Currency, Matcher, AccountIdConverter, AccountId, CheckedAccount> {
|
||||
fn can_check_in(_origin: &MultiLocation, what: &MultiAsset) -> Result {
|
||||
// Check we handle this asset.
|
||||
let amount: Currency::Balance = Matcher::matches_fungible(what)
|
||||
.ok_or(Error::AssetNotFound)?;
|
||||
if let Some(checked_account) = CheckedAccount::get() {
|
||||
let new_balance = Currency::free_balance(&checked_account)
|
||||
.checked_sub(&amount)
|
||||
.ok_or(XcmError::NotWithdrawable)?;
|
||||
Currency::ensure_can_withdraw(&checked_account, amount, WithdrawReasons::TRANSFER, new_balance)
|
||||
.map_err(|_| XcmError::NotWithdrawable)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_in(_origin: &MultiLocation, what: &MultiAsset) {
|
||||
if let Some(amount) = Matcher::matches_fungible(what) {
|
||||
if let Some(checked_account) = CheckedAccount::get() {
|
||||
let ok = Currency::withdraw(&checked_account, amount, WithdrawReasons::TRANSFER, AllowDeath).is_ok();
|
||||
debug_assert!(ok, "`can_check_in` must have returned `true` immediately prior; qed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_out(_dest: &MultiLocation, what: &MultiAsset) {
|
||||
if let Some(amount) = Matcher::matches_fungible(what) {
|
||||
if let Some(checked_account) = CheckedAccount::get() {
|
||||
Currency::deposit_creating(&checked_account, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn deposit_asset(what: &MultiAsset, who: &MultiLocation) -> Result {
|
||||
// Check we handle this asset.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use sp_std::{prelude::*, result, marker::PhantomData, borrow::Borrow};
|
||||
use xcm::v0::{Error as XcmError, Result, MultiAsset, MultiLocation, Junction};
|
||||
use frame_support::traits::{Get, tokens::fungibles};
|
||||
use frame_support::traits::{Get, tokens::fungibles, Contains};
|
||||
use xcm_executor::traits::{TransactAsset, Convert};
|
||||
|
||||
/// Asset transaction errors.
|
||||
@@ -160,15 +160,49 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FungiblesMutateAdapter<Assets, Matcher, AccountIdConverter, AccountId>(
|
||||
PhantomData<(Assets, Matcher, AccountIdConverter, AccountId)>
|
||||
pub struct FungiblesMutateAdapter<Assets, Matcher, AccountIdConverter, AccountId, CheckAsset, CheckingAccount>(
|
||||
PhantomData<(Assets, Matcher, AccountIdConverter, AccountId, CheckAsset, CheckingAccount)>
|
||||
);
|
||||
impl<
|
||||
Assets: fungibles::Mutate<AccountId>,
|
||||
Matcher: MatchesFungibles<Assets::AssetId, Assets::Balance>,
|
||||
AccountIdConverter: Convert<MultiLocation, AccountId>,
|
||||
AccountId: Clone, // can't get away without it since Currency is generic over it.
|
||||
> TransactAsset for FungiblesMutateAdapter<Assets, Matcher, AccountIdConverter, AccountId> {
|
||||
CheckAsset: Contains<Assets::AssetId>,
|
||||
CheckingAccount: Get<AccountId>,
|
||||
> TransactAsset for FungiblesMutateAdapter<Assets, Matcher, AccountIdConverter, AccountId, CheckAsset, CheckingAccount> {
|
||||
fn can_check_in(_origin: &MultiLocation, what: &MultiAsset) -> Result {
|
||||
// Check we handle this asset.
|
||||
let (asset_id, amount) = Matcher::matches_fungibles(what)?;
|
||||
if CheckAsset::contains(&asset_id) {
|
||||
// This is an asset whose teleports we track.
|
||||
let checking_account = CheckingAccount::get();
|
||||
Assets::can_withdraw(asset_id, &checking_account, amount)
|
||||
.into_result()
|
||||
.map_err(|_| XcmError::NotWithdrawable)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_in(_origin: &MultiLocation, what: &MultiAsset) {
|
||||
if let Ok((asset_id, amount)) = Matcher::matches_fungibles(what) {
|
||||
if CheckAsset::contains(&asset_id) {
|
||||
let checking_account = CheckingAccount::get();
|
||||
let ok = Assets::burn_from(asset_id, &checking_account, amount).is_ok();
|
||||
debug_assert!(ok, "`can_check_in` must have returned `true` immediately prior; qed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_out(_dest: &MultiLocation, what: &MultiAsset) {
|
||||
if let Ok((asset_id, amount)) = Matcher::matches_fungibles(what) {
|
||||
if CheckAsset::contains(&asset_id) {
|
||||
let checking_account = CheckingAccount::get();
|
||||
let ok = Assets::mint_into(asset_id, &checking_account, amount).is_ok();
|
||||
debug_assert!(ok, "`mint_into` cannot generally fail; qed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn deposit_asset(what: &MultiAsset, who: &MultiLocation) -> Result {
|
||||
// Check we handle this asset.
|
||||
@@ -193,25 +227,43 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FungiblesAdapter<Assets, Matcher, AccountIdConverter, AccountId>(
|
||||
PhantomData<(Assets, Matcher, AccountIdConverter, AccountId)>
|
||||
pub struct FungiblesAdapter<Assets, Matcher, AccountIdConverter, AccountId, CheckAsset, CheckingAccount>(
|
||||
PhantomData<(Assets, Matcher, AccountIdConverter, AccountId, CheckAsset, CheckingAccount)>
|
||||
);
|
||||
impl<
|
||||
Assets: fungibles::Mutate<AccountId> + fungibles::Transfer<AccountId>,
|
||||
Matcher: MatchesFungibles<Assets::AssetId, Assets::Balance>,
|
||||
AccountIdConverter: Convert<MultiLocation, AccountId>,
|
||||
AccountId: Clone, // can't get away without it since Currency is generic over it.
|
||||
> TransactAsset for FungiblesAdapter<Assets, Matcher, AccountIdConverter, AccountId> {
|
||||
CheckAsset: Contains<Assets::AssetId>,
|
||||
CheckingAccount: Get<AccountId>,
|
||||
> TransactAsset for FungiblesAdapter<Assets, Matcher, AccountIdConverter, AccountId, CheckAsset, CheckingAccount> {
|
||||
fn can_check_in(origin: &MultiLocation, what: &MultiAsset) -> Result {
|
||||
FungiblesMutateAdapter::<Assets, Matcher, AccountIdConverter, AccountId, CheckAsset, CheckingAccount>
|
||||
::can_check_in(origin, what)
|
||||
}
|
||||
|
||||
fn check_in(origin: &MultiLocation, what: &MultiAsset) {
|
||||
FungiblesMutateAdapter::<Assets, Matcher, AccountIdConverter, AccountId, CheckAsset, CheckingAccount>
|
||||
::check_in(origin, what)
|
||||
}
|
||||
|
||||
fn check_out(dest: &MultiLocation, what: &MultiAsset) {
|
||||
FungiblesMutateAdapter::<Assets, Matcher, AccountIdConverter, AccountId, CheckAsset, CheckingAccount>
|
||||
::check_out(dest, what)
|
||||
}
|
||||
|
||||
fn deposit_asset(what: &MultiAsset, who: &MultiLocation) -> Result {
|
||||
FungiblesMutateAdapter::<Assets, Matcher, AccountIdConverter, AccountId>::deposit_asset(what, who)
|
||||
FungiblesMutateAdapter::<Assets, Matcher, AccountIdConverter, AccountId, CheckAsset, CheckingAccount>
|
||||
::deposit_asset(what, who)
|
||||
}
|
||||
|
||||
fn withdraw_asset(
|
||||
what: &MultiAsset,
|
||||
who: &MultiLocation
|
||||
) -> result::Result<xcm_executor::Assets, XcmError> {
|
||||
FungiblesMutateAdapter::<Assets, Matcher, AccountIdConverter, AccountId>::withdraw_asset(what, who)
|
||||
FungiblesMutateAdapter::<Assets, Matcher, AccountIdConverter, AccountId, CheckAsset, CheckingAccount>
|
||||
::withdraw_asset(what, who)
|
||||
}
|
||||
|
||||
fn transfer_asset(
|
||||
|
||||
Reference in New Issue
Block a user