Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[xcm-v5] implement RFC#100: add new InitiateTransfer instruction #5876

Merged
merged 89 commits into from
Oct 23, 2024

Conversation

acatangiu
Copy link
Contributor

@acatangiu acatangiu commented Sep 30, 2024

A new instruction InitiateTransfer is introduced that initiates an assets transfer from the chain it is executed on, to another chain. The executed transfer is point-to-point (chain-to-chain) with all of the transfer properties specified in the instruction parameters. The instruction also allows specifying another XCM program to be executed on the remote chain.
If a transfer requires going through multiple hops, an XCM program can compose this instruction to be used at every chain along the path, on each hop describing that specific leg of the transfer.

Note: Transferring assets that require different paths (chains along the way) is not supported within same XCM because of the async nature of cross chain messages. This new instruction, however, enables initiating transfers for multiple assets that take the same path even if they require different transfer types along that path.

The usage and composition model of InitiateTransfer is the same as with existing DepositReserveAsset, InitiateReserveWithdraw and InitiateTeleport instructions. The main difference comes from the ability to handle assets that have different point-to-point transfer type between A and B. The other benefit is that it also allows specifying remote fee payment and transparently appends the required remote fees logic to the remote XCM.

We can specify the desired transfer type for some asset(s) using:

/// Specify which type of asset transfer is required for a particular `(asset, dest)` combination.
pub enum AssetTransferFilter {
	/// teleport assets matching `AssetFilter` to `dest`
	Teleport(AssetFilter),
	/// reserve-transfer assets matching `AssetFilter` to `dest`, using the local chain as reserve
	ReserveDeposit(AssetFilter),
	/// reserve-transfer assets matching `AssetFilter` to `dest`, using `dest` as reserve
	ReserveWithdraw(AssetFilter),
}

This PR adds 1 new XCM instruction:

/// Cross-chain transfer matching `assets` in the holding register as follows:
///
/// Assets in the holding register are matched using the given list of `AssetTransferFilter`s,
/// they are then transferred based on their specified transfer type:
///
/// - teleport: burn local assets and append a `ReceiveTeleportedAsset` XCM instruction to
///   the XCM program to be sent onward to the `dest` location,
///
/// - reserve deposit: place assets under the ownership of `dest` within this consensus system
///   (i.e. its sovereign account), and append a `ReserveAssetDeposited` XCM instruction
///   to the XCM program to be sent onward to the `dest` location,
///
/// - reserve withdraw: burn local assets and append a `WithdrawAsset` XCM instruction
///   to the XCM program to be sent onward to the `dest` location,
///
/// The onward XCM is then appended a `ClearOrigin` to allow safe execution of any following
/// custom XCM instructions provided in `remote_xcm`.
///
/// The onward XCM also potentially contains a `BuyExecution` instruction based on the presence
/// of the `remote_fees` parameter (see below).
///
/// If a transfer requires going through multiple hops, an XCM program can compose this instruction
/// to be used at every chain along the path, describing that specific leg of the transfer.
///
/// Parameters:
/// - `dest`: The location of the transfer next hop.
/// - `remote_fees`: If set to `Some(asset_xfer_filter)`, the single asset matching
///   `asset_xfer_filter` in the holding register will be transferred first in the remote XCM
///   program, followed by a `BuyExecution(fee)`, then rest of transfers follow.
///   This guarantees `remote_xcm` will successfully pass a `AllowTopLevelPaidExecutionFrom` barrier.
/// - `remote_xcm`: Custom instructions that will be executed on the `dest` chain. Note that
///   these instructions will be executed after a `ClearOrigin` so their origin will be `None`.
///
/// Safety: No concerns.
///
/// Kind: *Command*.
///
InitiateTransfer {
	destination: Location,
	remote_fees: Option<AssetTransferFilter>,
	assets: Vec<AssetTransferFilter>,
	remote_xcm: Xcm<()>,
}

An InitiateTransfer { .. } instruction shall transfer to dest, all assets in the holding register that match the provided assets and remote_fees filters.
These filters identify the assets to be transferred as well as the transfer type to be used for transferring them.
It shall handle the local side of the transfer, then forward an onward XCM to dest for handling the remote side of the transfer.

It should do so using same mechanisms as existing DepositReserveAsset, InitiateReserveWithdraw, InitiateTeleport instructions but practically combining all required XCM instructions to be remotely executed into a single remote XCM program to be sent over to dest.

Furthermore, through remote_fees: Option<AssetTransferFilter>, it shall allow specifying a single asset to be used for fees on dest chain. This single asset shall be remotely handled/received by the first instruction in the onward XCM and shall be followed by a BuyExecution instruction using it.
If remote_fees is set to None, the first instruction in the onward XCM shall be a UnpaidExecution instruction. The rest of the assets shall be handled by subsequent instructions, thus also finally allowing single asset buy execution barrier security recommendation.

The BuyExecution appended to the onward XCM specifies WeightLimit::Unlimited, thus being limited only by the remote_fees asset "amount". This is a deliberate decision for enhancing UX - in practice, people/dApps care about limiting the amount of fee asset used and not the actually used weight.

The onward XCM, following the assets transfers instructions, ClearOrigin or DescendOrigin instructions shall be appended to stop acting on behalf of the source chain, then the caller-provided remote_xcm shall also be appended, allowing the caller to control what to do with the transferred assets.

Closes #5209

franciscoaguirre and others added 30 commits August 20, 2024 16:26
…coco --target_dir=polkadot --pallet=pallet_xcm_benchmarks::generic
…stend --target_dir=polkadot --pallet=pallet_xcm_benchmarks::generic
…retime-westend --runtime_dir=coretime --target_dir=cumulus --pallet=pallet_xcm_benchmarks::generic
…set-hub-rococo --runtime_dir=assets --target_dir=cumulus --pallet=pallet_xcm_benchmarks::generic
…set-hub-westend --runtime_dir=assets --target_dir=cumulus --pallet=pallet_xcm_benchmarks::generic
…retime-rococo --runtime_dir=coretime --target_dir=cumulus --pallet=pallet_xcm_benchmarks::generic
…idge-hub-rococo --runtime_dir=bridge-hubs --target_dir=cumulus --pallet=pallet_xcm_benchmarks::generic
…idge-hub-westend --runtime_dir=bridge-hubs --target_dir=cumulus --pallet=pallet_xcm_benchmarks::generic
…ople-westend --runtime_dir=people --target_dir=cumulus --pallet=pallet_xcm_benchmarks::generic
…coco --target_dir=polkadot --pallet=pallet_xcm_benchmarks::fungible
@command-bot
Copy link

command-bot bot commented Oct 21, 2024

@franciscoaguirre Command "$PIPELINE_SCRIPTS_DIR/commands/bench/bench.sh" --subcommand=xcm --runtime=rococo --target_dir=polkadot --pallet=pallet_xcm_benchmarks::fungible has finished. Result: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614460 has finished. If any artifacts were generated, you can download them from https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614460/artifacts/download.

command-bot added 2 commits October 21, 2024 22:16
…idge-hub-rococo --runtime_dir=bridge-hubs --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible
…retime-westend --runtime_dir=coretime --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible
@command-bot
Copy link

command-bot bot commented Oct 21, 2024

@franciscoaguirre Command "$PIPELINE_SCRIPTS_DIR/commands/bench/bench.sh" --subcommand=xcm --runtime=bridge-hub-rococo --runtime_dir=bridge-hubs --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible has finished. Result: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614464 has finished. If any artifacts were generated, you can download them from https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614464/artifacts/download.

command-bot added 2 commits October 21, 2024 22:16
…set-hub-rococo --runtime_dir=assets --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible
…retime-rococo --runtime_dir=coretime --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible
@command-bot
Copy link

command-bot bot commented Oct 21, 2024

@franciscoaguirre Command "$PIPELINE_SCRIPTS_DIR/commands/bench/bench.sh" --subcommand=xcm --runtime=coretime-westend --runtime_dir=coretime --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible has finished. Result: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614462 has finished. If any artifacts were generated, you can download them from https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614462/artifacts/download.

@command-bot
Copy link

command-bot bot commented Oct 21, 2024

@franciscoaguirre Command "$PIPELINE_SCRIPTS_DIR/commands/bench/bench.sh" --subcommand=xcm --runtime=asset-hub-rococo --runtime_dir=assets --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible has finished. Result: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614461 has finished. If any artifacts were generated, you can download them from https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614461/artifacts/download.

@command-bot
Copy link

command-bot bot commented Oct 21, 2024

@franciscoaguirre Command "$PIPELINE_SCRIPTS_DIR/commands/bench/bench.sh" --subcommand=xcm --runtime=coretime-rococo --runtime_dir=coretime --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible has finished. Result: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614463 has finished. If any artifacts were generated, you can download them from https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614463/artifacts/download.

command-bot added 2 commits October 21, 2024 22:17
…idge-hub-westend --runtime_dir=bridge-hubs --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible
…ople-rococo --runtime_dir=people --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible
@command-bot
Copy link

command-bot bot commented Oct 21, 2024

@franciscoaguirre Command "$PIPELINE_SCRIPTS_DIR/commands/bench/bench.sh" --subcommand=xcm --runtime=bridge-hub-westend --runtime_dir=bridge-hubs --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible has finished. Result: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614465 has finished. If any artifacts were generated, you can download them from https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614465/artifacts/download.

@command-bot
Copy link

command-bot bot commented Oct 21, 2024

@franciscoaguirre Command "$PIPELINE_SCRIPTS_DIR/commands/bench/bench.sh" --subcommand=xcm --runtime=people-rococo --runtime_dir=people --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible has finished. Result: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614467 has finished. If any artifacts were generated, you can download them from https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614467/artifacts/download.

…ople-westend --runtime_dir=people --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible
@command-bot
Copy link

command-bot bot commented Oct 21, 2024

@franciscoaguirre Command "$PIPELINE_SCRIPTS_DIR/commands/bench/bench.sh" --subcommand=xcm --runtime=people-westend --runtime_dir=people --target_dir=cumulus --pallet=pallet_xcm_benchmarks::fungible has finished. Result: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614466 has finished. If any artifacts were generated, you can download them from https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/7614466/artifacts/download.

@acatangiu acatangiu mentioned this pull request Oct 22, 2024
10 tasks
Copy link
Contributor

@serban300 serban300 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@bkontur bkontur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@franciscoaguirre franciscoaguirre merged commit 8fe7700 into paritytech:xcm-v5 Oct 23, 2024
171 of 194 checks passed
@franciscoaguirre franciscoaguirre deleted the impl-rfc-100 branch October 23, 2024 16:35
acatangiu added a commit that referenced this pull request Oct 29, 2024
…rigin on destination (#5971)

Built on top of #5876

# Description

Currently, all XCM asset transfer instructions ultimately clear the
origin in the remote XCM message by use of the `ClearOrigin`
instruction. This is done for security considerations to ensure that
subsequent (user-controlled) instructions cannot command the authority
of the sending chain.

The problem with this approach is that it limits what can be achieved on
remote chains through XCM. Most XCM operations require having an origin,
and following any asset transfer the origin is lost, meaning not much
can be done other than depositing the transferred assets to some local
account or transferring them onward to another chain.

For example, we cannot transfer some funds for buying execution, then do
a `Transact` (all in the same XCM message).

In the case of XCM programs going from source-chain directly to
dest-chain without an intermediary hop, we can enable scenarios such as
above by using the AliasOrigin instruction instead of the ClearOrigin
instruction.

Instead of clearing the source-chain origin, the destination chain shall
attempt to alias source-chain to "original origin" on the source chain.
Most common such origin aliasing would be X1(Parachain(source-chain)) ->
X2(Parachain(source-chain), AccountId32(origin-account)) for the case of
a single hop transfer where the initiator is a (signed/pure/proxy)
account origin-account on source-chain. This is equivalent to using the
DescendOrigin instruction in this case, but also usable in the multi hop
case.

This allows an actor on chain A to Transact on chain B without having to
prefund its SA account on chain B, instead they can simply transfer the
required fees in the same XCM program as the Transact.

As long as the asset transfer has the same XCM route/hops as the rest of
the program, this pattern of usage can be composed across multiple hops,
to ultimately Transact on the final hop using the original origin on the
source chain, effectively abstracting away any intermediary hops.

### XCM `InitiateAssetsTransfer` instruction changes

A new parameter `preserve_origin` to be added to the
`InitiateAssetsTransfer` XCM instruction that specifies if the original
origin should be preserved or cleared.

```diff
InitiateAssetsTransfer {
	destination: Location,
	assets: Vec<AssetTransferFilter>,
	remote_fees: Option<AssetTransferFilter>,
+	preserve_origin: bool,
	remote_xcm: Xcm<()>,
}
```

This parameter is explicitly necessary because the instruction should be
usable between any two chains regardless of their origin-aliasing trust
relationship. Preserving the origin requires some level of trust, while
clearing it works regardless of that relationship.
Specifying `preserve_origin: false` will always work regardless of the
configured alias filters of the
involved chains.

# Testing

- [x] e2e test: User on PenpalA registers foreign token (transacts) on
PenpalB through XCM, while paying all fees using USDT (meaning XCM has
to go through AssetHub) - AH carries over the original origin,
effectively being a transparent proxy,
- [x] e2e test: User/contract on Ethereum registers foreign token
(transacts) on Polkadot-PenpalA through XCM (over bridge), while paying
all fees using DOT (has to go through AssetHub) - AH carries over the
original origin, effectively being a transparent proxy for Ethereum,

---------

Signed-off-by: Adrian Catangiu <[email protected]>
Co-authored-by: Francisco Aguirre <[email protected]>
Co-authored-by: Branislav Kontur <[email protected]>
github-merge-queue bot pushed a commit that referenced this pull request Nov 6, 2024
# Context

This PR aims to introduce XCMv5, for now it's in progress and will be
updated over time.
This branch will serve as a milestone branch for merging in all features
we want to add to XCM, roughly outlined
[here](polkadot-fellows/xcm-format#60).
More features could be added.

## TODO
- [x] Migrate foreign assets from v3 to v4
- [x] Setup v5 skeleton
- [x] Remove XCMv2
- [x] #5390
- [x] #5585
- [x] #5420
- [x] #5876
- [x] #5971
- [x] #6148
- [x] #6228

Fixes #3434 
Fixes #4190
Fixes #5209
Fixes #5241
Fixes #4284

---------

Signed-off-by: Adrian Catangiu <[email protected]>
Co-authored-by: Adrian Catangiu <[email protected]>
Co-authored-by: Andrii <[email protected]>
Co-authored-by: Branislav Kontur <[email protected]>
Co-authored-by: Joseph Zhao <[email protected]>
Co-authored-by: Nazar Mokrynskyi <[email protected]>
Co-authored-by: Bastian Köcher <[email protected]>
Co-authored-by: Shawn Tabrizi <[email protected]>
Co-authored-by: command-bot <>
Co-authored-by: GitHub Action <[email protected]>
Co-authored-by: Serban Iorga <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T6-XCM This PR/Issue is related to XCM.
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

Implement new XCM InitiateAssetsTransfer instruction
5 participants