mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-01 13:37:57 +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:
@@ -154,6 +154,13 @@ impl<Config: config::Config> XcmExecutor<Config> {
|
||||
// We only trust the origin to send us assets that they identify as their
|
||||
// sovereign assets.
|
||||
ensure!(Config::IsTeleporter::filter_asset_location(asset, &origin), XcmError::UntrustedTeleportLocation);
|
||||
// We should check that the asset can actually be teleported in (for this to be in error, there
|
||||
// would need to be an accounting violation by one of the trusted chains, so it's unlikely, but we
|
||||
// don't want to punish a possibly innocent chain/user).
|
||||
Config::AssetTransactor::can_check_in(&origin, asset)?;
|
||||
}
|
||||
for asset in assets.iter() {
|
||||
Config::AssetTransactor::check_in(&origin, asset);
|
||||
}
|
||||
Some((Assets::from(assets), effects))
|
||||
}
|
||||
@@ -238,6 +245,9 @@ impl<Config: config::Config> XcmExecutor<Config> {
|
||||
Config::XcmSender::send_xcm(reserve, Xcm::WithdrawAsset { assets, effects })?;
|
||||
}
|
||||
Order::InitiateTeleport { assets, dest, effects} => {
|
||||
for asset in assets.iter() {
|
||||
Config::AssetTransactor::check_out(&origin, asset);
|
||||
}
|
||||
let assets = Self::reanchored(holding.saturating_take(assets), &dest);
|
||||
Config::XcmSender::send_xcm(dest, Xcm::TeleportAsset { assets, effects })?;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,40 @@ use crate::Assets;
|
||||
/// account locations such as a `MultiLocation::X1(Junction::Parachain)`. Different chains may handle them in
|
||||
/// different ways.
|
||||
pub trait TransactAsset {
|
||||
/// Ensure that `check_in` will result in `Ok`.
|
||||
///
|
||||
/// When composed as a tuple, all type-items are called and at least one must result in `Ok`.
|
||||
fn can_check_in(_origin: &MultiLocation, _what: &MultiAsset) -> XcmResult {
|
||||
Err(XcmError::Unimplemented)
|
||||
}
|
||||
|
||||
/// An asset has been teleported in from the given origin. This should do whatever housekeeping is needed.
|
||||
///
|
||||
/// NOTE: This will make only a best-effort at bookkeeping. The caller should ensure that `can_check_in` has
|
||||
/// returned with `Ok` in order to guarantee that this operation proceeds properly.
|
||||
///
|
||||
/// Implementation note: In general this will do one of two things: On chains where the asset is native,
|
||||
/// it will reduce the assets from a special "teleported" account so that a) total-issuance is preserved;
|
||||
/// and b) to ensure that no more assets can be teleported in than were teleported out overall (this should
|
||||
/// not be needed if the teleporting chains are to be trusted, but better to be safe than sorry). On chains
|
||||
/// where the asset is not native then it will generally just be a no-op.
|
||||
///
|
||||
/// When composed as a tuple, all type-items are called. It is up to the implementor that there exists no
|
||||
/// value for `_what` which can cause side-effects for more than one of the type-items.
|
||||
fn check_in(_origin: &MultiLocation, _what: &MultiAsset) {}
|
||||
|
||||
/// An asset has been teleported out to the given destination. This should do whatever housekeeping is needed.
|
||||
///
|
||||
/// Implementation note: In general this will do one of two things: On chains where the asset is native,
|
||||
/// it will increase the assets in a special "teleported" account so that a) total-issuance is preserved; and
|
||||
/// b) to ensure that no more assets can be teleported in than were teleported out overall (this should not
|
||||
/// be needed if the teleporting chains are to be trusted, but better to be safe than sorry). On chains where
|
||||
/// the asset is not native then it will generally just be a no-op.
|
||||
///
|
||||
/// When composed as a tuple, all type-items are called. It is up to the implementor that there exists no
|
||||
/// value for `_what` which can cause side-effects for more than one of the type-items.
|
||||
fn check_out(_origin: &MultiLocation, _what: &MultiAsset) {}
|
||||
|
||||
/// Deposit the `what` asset into the account of `who`.
|
||||
///
|
||||
/// Implementations should return `XcmError::FailedToTransactAsset` if deposit failed.
|
||||
@@ -64,6 +98,25 @@ pub trait TransactAsset {
|
||||
|
||||
#[impl_trait_for_tuples::impl_for_tuples(30)]
|
||||
impl TransactAsset for Tuple {
|
||||
fn can_check_in(origin: &MultiLocation, what: &MultiAsset) -> XcmResult {
|
||||
for_tuples!( #(
|
||||
match Tuple::can_check_in(origin, what) {
|
||||
Err(XcmError::AssetNotFound) => (),
|
||||
r => return r,
|
||||
}
|
||||
)* );
|
||||
Err(XcmError::AssetNotFound)
|
||||
}
|
||||
fn check_in(origin: &MultiLocation, what: &MultiAsset) {
|
||||
for_tuples!( #(
|
||||
Tuple::check_in(origin, what);
|
||||
)* );
|
||||
}
|
||||
fn check_out(dest: &MultiLocation, what: &MultiAsset) {
|
||||
for_tuples!( #(
|
||||
Tuple::check_out(dest, what);
|
||||
)* );
|
||||
}
|
||||
fn deposit_asset(what: &MultiAsset, who: &MultiLocation) -> XcmResult {
|
||||
for_tuples!( #(
|
||||
match Tuple::deposit_asset(what, who) { o @ Ok(_) => return o, _ => () }
|
||||
@@ -83,4 +136,3 @@ impl TransactAsset for Tuple {
|
||||
Err(XcmError::Unimplemented)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user