mirror of
https://github.com/pezkuwichain/pezkuwi-fellows.git
synced 2026-04-24 13:28:04 +00:00
523 lines
41 KiB
HTML
523 lines
41 KiB
HTML
|
|
<!DOCTYPE HTML>
|
|
<html lang="en" class="polkadot" dir="ltr">
|
|
<head>
|
|
<!-- Book generated using mdBook -->
|
|
<meta charset="UTF-8">
|
|
<title>RFC-0100: New XCM instruction: InitiateAssetsTransfer - Polkadot Fellowship RFCs</title>
|
|
|
|
|
|
<!-- Custom HTML head -->
|
|
|
|
<meta name="description" content="An online book of RFCs approved or proposed within the Polkadot Fellowship.">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="theme-color" content="#ffffff">
|
|
|
|
<link rel="icon" href="../favicon.svg">
|
|
<link rel="shortcut icon" href="../favicon.png">
|
|
<link rel="stylesheet" href="../css/variables.css">
|
|
<link rel="stylesheet" href="../css/general.css">
|
|
<link rel="stylesheet" href="../css/chrome.css">
|
|
<link rel="stylesheet" href="../css/print.css" media="print">
|
|
|
|
<!-- Fonts -->
|
|
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
|
|
<link rel="stylesheet" href="../fonts/fonts.css">
|
|
|
|
<!-- Highlight.js Stylesheets -->
|
|
<link rel="stylesheet" href="../highlight.css">
|
|
<link rel="stylesheet" href="../tomorrow-night.css">
|
|
<link rel="stylesheet" href="../ayu-highlight.css">
|
|
|
|
<!-- Custom theme stylesheets -->
|
|
<link rel="stylesheet" href="../theme/polkadot.css">
|
|
|
|
</head>
|
|
<body class="sidebar-visible no-js">
|
|
<div id="body-container">
|
|
<!-- Provide site root to javascript -->
|
|
<script>
|
|
var path_to_root = "../";
|
|
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "polkadot" : "polkadot";
|
|
</script>
|
|
|
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
|
<script>
|
|
try {
|
|
var theme = localStorage.getItem('mdbook-theme');
|
|
var sidebar = localStorage.getItem('mdbook-sidebar');
|
|
|
|
if (theme.startsWith('"') && theme.endsWith('"')) {
|
|
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
|
}
|
|
|
|
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
|
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
|
}
|
|
} catch (e) { }
|
|
</script>
|
|
|
|
<!-- Set the theme before any content is loaded, prevents flash -->
|
|
<script>
|
|
var theme;
|
|
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
|
if (theme === null || theme === undefined) { theme = default_theme; }
|
|
var html = document.querySelector('html');
|
|
html.classList.remove('polkadot')
|
|
html.classList.add(theme);
|
|
var body = document.querySelector('body');
|
|
body.classList.remove('no-js')
|
|
body.classList.add('js');
|
|
</script>
|
|
|
|
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
|
|
|
|
<!-- Hide / unhide sidebar before it is displayed -->
|
|
<script>
|
|
var body = document.querySelector('body');
|
|
var sidebar = null;
|
|
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
|
|
if (document.body.clientWidth >= 1080) {
|
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
|
sidebar = sidebar || 'visible';
|
|
} else {
|
|
sidebar = 'hidden';
|
|
}
|
|
sidebar_toggle.checked = sidebar === 'visible';
|
|
body.classList.remove('sidebar-visible');
|
|
body.classList.add("sidebar-" + sidebar);
|
|
</script>
|
|
|
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
|
<div class="sidebar-scrollbox">
|
|
<ol class="chapter"><li class="chapter-item expanded affix "><a href="../introduction.html">Introduction</a></li><li class="spacer"></li><li class="chapter-item expanded affix "><li class="part-title">Newly Proposed</li><li class="spacer"></li><li class="chapter-item expanded affix "><li class="part-title">Proposed</li><li class="chapter-item expanded "><a href="../proposed/0150-voting-while-delegating.html">RFC-150: Allow Voting While Delegating</a></li><li class="chapter-item expanded "><a href="../proposed/0154-multi-slot-aura.html">RFC-0154: AURA Multi-Slot Collation </a></li><li class="chapter-item expanded "><a href="../proposed/0155-pUSD.html">RFC-0155: pUSD (Polkadot USD over-collateralised debt token)</a></li><li class="chapter-item expanded "><a href="../proposed/0156-bls-signatures.html">RFC-0156: Add BLS12-381 Host Functions</a></li><li class="spacer"></li><li class="chapter-item expanded affix "><li class="part-title">Approved</li><li class="chapter-item expanded "><a href="../approved/0001-agile-coretime.html">RFC-1: Agile Coretime</a></li><li class="chapter-item expanded "><a href="../approved/0005-coretime-interface.html">RFC-5: Coretime Interface</a></li><li class="chapter-item expanded "><a href="../approved/0007-system-collator-selection.html">RFC-0007: System Collator Selection</a></li><li class="chapter-item expanded "><a href="../approved/0008-parachain-bootnodes-dht.html">RFC-0008: Store parachain bootnodes in relay chain DHT</a></li><li class="chapter-item expanded "><a href="../approved/0009-improved-net-light-client-requests.html">RFC-0009: Improved light client requests networking protocol</a></li><li class="chapter-item expanded "><a href="../approved/0010-burn-coretime-revenue.html">RFC-0010: Burn Coretime Revenue</a></li><li class="chapter-item expanded "><a href="../approved/0012-process-for-adding-new-collectives.html">RFC-0012: Process for Adding New System Collectives</a></li><li class="chapter-item expanded "><a href="../approved/0013-prepare-blockbuilder-and-core-runtime-apis-for-mbms.html">RFC-0013: Prepare Core runtime API for MBMs</a></li><li class="chapter-item expanded "><a href="../approved/0014-improve-locking-mechanism-for-parachains.html">RFC-0014: Improve locking mechanism for parachains</a></li><li class="chapter-item expanded "><a href="../approved/0017-coretime-market-redesign.html">RFC-0017: Coretime Market Redesign</a></li><li class="chapter-item expanded "><a href="../approved/0022-adopt-encointer-runtime.html">RFC-0022: Adopt Encointer Runtime</a></li><li class="chapter-item expanded "><a href="../approved/0026-sassafras-consensus.html">RFC-0026: Sassafras Consensus Protocol</a></li><li class="chapter-item expanded "><a href="../approved/0032-minimal-relay.html">RFC-0032: Minimal Relay</a></li><li class="chapter-item expanded "><a href="../approved/0042-extrinsics-state-version.html">RFC-0042: Add System version that replaces StateVersion on RuntimeVersion</a></li><li class="chapter-item expanded "><a href="../approved/0043-storage-proof-size-hostfunction.html">RFC-0043: Introduce storage_proof_size Host Function for Improved Parachain Block Utilization</a></li><li class="chapter-item expanded "><a href="../approved/0045-nft-deposits-asset-hub.html">RFC-0045: Lowering NFT Deposits on Asset Hub</a></li><li class="chapter-item expanded "><a href="../approved/0047-assignment-of-availability-chunks.html">RFC-0047: Assignment of availability chunks to validators</a></li><li class="chapter-item expanded "><a href="../approved/0048-session-keys-runtime-api.html">RFC-0048: Generate ownership proof for SessionKeys</a></li><li class="chapter-item expanded "><a href="../approved/0050-fellowship-salaries.html">RFC-0050: Fellowship Salaries</a></li><li class="chapter-item expanded "><a href="../approved/0056-one-transaction-per-notification.html">RFC-0056: Enforce only one transaction per notification</a></li><li class="chapter-item expanded "><a href="../approved/0059-nodes-capabilities-discovery.html">RFC-0059: Add a discovery mechanism for nodes based on their capabilities</a></li><li class="chapter-item expanded "><a href="../approved/0078-merkleized-metadata.html">RFC-0078: Merkleized Metadata</a></li><li class="chapter-item expanded "><a href="../approved/0084-general-transaction-extrinsic-format.html">RFC-0084: General transactions in extrinsic format</a></li><li class="chapter-item expanded "><a href="../approved/0091-dht-record-creation-time.html">RFC-0091: DHT Authority discovery record creation time</a></li><li class="chapter-item expanded "><a href="../approved/0097-unbonding_queue.html">RFC-0097: Unbonding Queue</a></li><li class="chapter-item expanded "><a href="../approved/0099-transaction-extension-version.html">RFC-0099: Introduce a transaction extension version</a></li><li class="chapter-item expanded "><a href="../approved/0100-xcm-multi-type-asset-transfer.html" class="active">RFC-0100: New XCM instruction: InitiateAssetsTransfer</a></li><li class="chapter-item expanded "><a href="../approved/0101-xcm-transact-remove-max-weight-param.html">RFC-0101: XCM Transact remove require_weight_at_most parameter</a></li><li class="chapter-item expanded "><a href="../approved/0103-introduce-core-index-commitment.html">RFC-0103: Introduce a CoreIndex commitment and a SessionIndex field in candidate receipts</a></li><li class="chapter-item expanded "><a href="../approved/0105-xcm-improved-fee-mechanism.html">RFC-0105: XCM improved fee mechanism</a></li><li class="chapter-item expanded "><a href="../approved/0107-xcm-execution-hints.html">RFC-0107: XCM Execution hints</a></li><li class="chapter-item expanded "><a href="../approved/0108-xcm-remove-testnet-ids.html">RFC-0108: Remove XCM testnet NetworkIds</a></li><li class="chapter-item expanded "><a href="../approved/0122-alias-origin-on-asset-transfers.html">RFC-0122: Asset transfers can alias XCM origin on destination to original origin</a></li><li class="chapter-item expanded "><a href="../approved/0123-pending-code-as-storage-location-for-runtime-upgrades.html">RFC-0123: Introduce :pending_code as intermediate storage key for the runtime code</a></li><li class="chapter-item expanded "><a href="../approved/0125-xcm-asset-metadata.html">RFC-0125: XCM Asset Metadata</a></li><li class="chapter-item expanded "><a href="../approved/0126-introduce-pvq.html">RFC-0126: Introduce PVQ (PolkaVM Query)</a></li><li class="chapter-item expanded "><a href="../approved/0135-compressed-blob-prefixes.html">RFC-0135: Compressed Blob Prefixes</a></li><li class="chapter-item expanded "><a href="../approved/0139-faster-erasure-coding.html">RFC-0139: Faster Erasure Coding</a></li><li class="chapter-item expanded "><a href="../approved/0146-deflationary-fee-proposal.html">RFC-0146: Deflationary Transaction Fee Model for the Relay Chain and its System Parachains</a></li><li class="chapter-item expanded "><a href="../approved/0149-rfc-1-renewal-adjustment.html">RFC-0149: Renewal Adjustment</a></li><li class="spacer"></li><li class="chapter-item expanded affix "><li class="part-title">Stale</li><li class="chapter-item expanded "><a href="../stale/0000-pre-elves_soft.html">RFC-0000: Pre-ELVES soft concensus</a></li><li class="chapter-item expanded "><a href="../stale/0000-rewards.html">RFC-0000: Validator Rewards</a></li><li class="chapter-item expanded "><a href="../stale/0004-remove-unnecessary-allocator-usage.html">RFC-0004: Remove the host-side runtime memory allocator</a></li><li class="chapter-item expanded "><a href="../stale/0006-dynamic-pricing-for-bulk-coretime-sales.html">RFC-0006: Dynamic Pricing for Bulk Coretime Sales</a></li><li class="chapter-item expanded "><a href="../stale/0034-xcm-absolute-location-account-derivation.html">RFC-34: XCM Absolute Location Account Derivation</a></li><li class="chapter-item expanded "><a href="../stale/0035-conviction-voting-delegation-modifications.html"> RFC-0035: Conviction Voting Delegation Modifications</a></li><li class="chapter-item expanded "><a href="../stale/0044-rent-based-registration.html">RFC-0044: Rent based registration model</a></li><li class="chapter-item expanded "><a href="../stale/0054-remove-heap-pages.html">RFC-0054: Remove the concept of "heap pages" from the client</a></li><li class="chapter-item expanded "><a href="../stale/0070-x-track-kusamanetwork.html">RFC-0070: X Track for @kusamanetwork</a></li><li class="chapter-item expanded "><a href="../stale/0073-referedum-deposit-track.html">RFC-0073: Decision Deposit Referendum Track</a></li><li class="chapter-item expanded "><a href="../stale/0074-stateful-multisig-pallet.html">RFC-0074: Stateful Multisig Pallet</a></li><li class="chapter-item expanded "><a href="../stale/0077-increase-max-length-of-identity-pgp-fingerprint-value.html">RFC-0077: Increase maximum length of identity PGP fingerprint values from 20 bytes</a></li><li class="chapter-item expanded "><a href="../stale/0088-broker-pallet-slashable-deposit-purchaser-reputation-reserved-cores.html">RFC-0088: Add slashable locked deposit, purchaser reputation, and reserved cores for on-chain identities to broker pallet</a></li><li class="chapter-item expanded "><a href="../stale/00xx-secondary-marketplace-for-regions.html">RFC-0001: Secondary Market for Regions</a></li><li class="chapter-item expanded "><a href="../stale/00xx-smart-contracts-coretime-chain.html">RFC-0002: Smart Contracts on the Coretime Chain</a></li><li class="chapter-item expanded "><a href="../stale/0102-offchain-parachain-runtime-upgrades.html">RFC-0000: Feature Name Here</a></li><li class="chapter-item expanded "><a href="../stale/0106-xcm-remove-fees-mode.html">RFC-0106: Remove XCM fees mode</a></li><li class="chapter-item expanded "><a href="../stale/0111-pure-proxy-replication.html">RFC-0111: Pure Proxy Replication</a></li><li class="chapter-item expanded "><a href="../stale/0112-compress-state-response-message-in-state-sync.html">RFC-0112: Compress the State Response Message in State Sync</a></li><li class="chapter-item expanded "><a href="../stale/0114-secp256r1-hostfunction.html">RFC-0114: Introduce secp256r1_ecdsa_verify_prehashed Host Function to verify NIST-P256 elliptic curve signatures</a></li><li class="chapter-item expanded "><a href="../stale/0117-unbrick-collective.html">RFC-0117: The Unbrick Collective</a></li><li class="chapter-item expanded "><a href="../stale/0120-referenda-confirmation-by-candle-mechanism.html">RFC-0120: Referenda Confirmation by Candle Mechanism</a></li><li class="chapter-item expanded "><a href="../stale/0124-extrinsic-version-5.html">RFC-0124: Extrinsic version 5</a></li><li class="chapter-item expanded "><a href="../stale/0138-invulnerable-collator-election.html">RFC-0138: Election mechanism for invulnerable collators on system chains</a></li><li class="chapter-item expanded "><a href="../stale/0152-decentralized-convex-preference-coretime-market-for-polkadot.html">RFC-0152: Decentralized Convex-Preference Coretime Market for Polkadot</a></li><li class="chapter-item expanded "><a href="../stale/RFC-114 Adjust Tipper Track Confirmation Periods.html">RFC-114: Adjust Tipper Track Confirmation Periods</a></li><li class="chapter-item expanded "><a href="../stale/TODO-stale-nomination-reward-curve.html">RFC-TODO: Stale Nomination Reward Curve</a></li><li class="chapter-item expanded "><a href="../stale/xxxx-improve-the-security-of-proof-of-possession.html">RFC-XXXX: Adding customized mandatory context to proof of possession statement</a></li></ol>
|
|
</div>
|
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
|
</nav>
|
|
|
|
<!-- Track and set sidebar scroll position -->
|
|
<script>
|
|
var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
|
|
sidebarScrollbox.addEventListener('click', function(e) {
|
|
if (e.target.tagName === 'A') {
|
|
sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
|
|
}
|
|
}, { passive: true });
|
|
var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
|
|
sessionStorage.removeItem('sidebar-scroll');
|
|
if (sidebarScrollTop) {
|
|
// preserve sidebar scroll position when navigating via links within sidebar
|
|
sidebarScrollbox.scrollTop = sidebarScrollTop;
|
|
} else {
|
|
// scroll sidebar to current active section when navigating via "next/previous chapter" buttons
|
|
var activeSection = document.querySelector('#sidebar .active');
|
|
if (activeSection) {
|
|
activeSection.scrollIntoView({ block: 'center' });
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div id="page-wrapper" class="page-wrapper">
|
|
|
|
<div class="page">
|
|
<div id="menu-bar-hover-placeholder"></div>
|
|
<div id="menu-bar" class="menu-bar sticky">
|
|
<div class="left-buttons">
|
|
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
|
<i class="fa fa-bars"></i>
|
|
</label>
|
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
|
<i class="fa fa-paint-brush"></i>
|
|
</button>
|
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
|
<li role="none"><button role="menuitem" class="theme" id="polkadot">Polkadot</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
|
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
|
</ul>
|
|
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
|
<i class="fa fa-search"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<h1 class="menu-title">Polkadot Fellowship RFCs</h1>
|
|
|
|
<div class="right-buttons">
|
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
|
<i id="print-button" class="fa fa-print"></i>
|
|
</a>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div id="search-wrapper" class="hidden">
|
|
<form id="searchbar-outer" class="searchbar-outer">
|
|
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
|
</form>
|
|
<div id="searchresults-outer" class="searchresults-outer hidden">
|
|
<div id="searchresults-header" class="searchresults-header"></div>
|
|
<ul id="searchresults">
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
|
<script>
|
|
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
|
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
|
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
|
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
|
});
|
|
</script>
|
|
|
|
<div id="content" class="content">
|
|
<main>
|
|
<p><a href="https://github.com/polkadot-fellows/RFCs/blob/main/text/0100-xcm-multi-type-asset-transfer.md">(source)</a></p>
|
|
<p><strong>Table of Contents</strong></p>
|
|
<ul>
|
|
<li><a href="#rfc-0100-new-xcm-instruction-initiateassetstransfer">RFC-0100: New XCM instruction: <code>InitiateAssetsTransfer</code></a>
|
|
<ul>
|
|
<li><a href="#summary">Summary</a></li>
|
|
<li><a href="#motivation">Motivation</a></li>
|
|
<li><a href="#stakeholders">Stakeholders</a></li>
|
|
<li><a href="#explanation">Explanation</a>
|
|
<ul>
|
|
<li><a href="#example-usage-transferring-2-different-asset-types-across-3-chains">Example usage: transferring 2 different asset types across 3 chains</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#drawbacks">Drawbacks</a></li>
|
|
<li><a href="#testing-security-and-privacy">Testing, Security, and Privacy</a></li>
|
|
<li><a href="#performance-ergonomics-and-compatibility">Performance, Ergonomics, and Compatibility</a>
|
|
<ul>
|
|
<li><a href="#performance">Performance</a></li>
|
|
<li><a href="#ergonomics">Ergonomics</a></li>
|
|
<li><a href="#compatibility">Compatibility</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#prior-art-and-references">Prior Art and References</a></li>
|
|
<li><a href="#unresolved-questions">Unresolved Questions</a></li>
|
|
<li><a href="#future-directions-and-related-material">Future Directions and Related Material</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<h1 id="rfc-0100-new-xcm-instruction-initiateassetstransfer"><a class="header" href="#rfc-0100-new-xcm-instruction-initiateassetstransfer">RFC-0100: New XCM instruction: <code>InitiateAssetsTransfer</code></a></h1>
|
|
<div class="table-wrapper"><table><thead><tr><th></th><th></th></tr></thead><tbody>
|
|
<tr><td><strong>Start Date</strong></td><td>11 July 2024</td></tr>
|
|
<tr><td><strong>Description</strong></td><td>Add new XCM instruction: <code>InitiateAssetsTransfer</code> for mixing asset transfer types in same XCM</td></tr>
|
|
<tr><td><strong>Authors</strong></td><td>Adrian Catangiu</td></tr>
|
|
</tbody></table>
|
|
</div>
|
|
<h2 id="summary"><a class="header" href="#summary">Summary</a></h2>
|
|
<p>This RFC proposes a new instruction that provides a way to initiate on remote chains, asset transfers which
|
|
transfer multiple types (teleports, local-reserve, destination-reserve) of assets, using XCM alone.</p>
|
|
<p>The currently existing instructions are too opinionated and force each XCM asset transfer to a single
|
|
transfer type (teleport, local-reserve, destination-reserve). This results in inability to combine different
|
|
types of transfers in single transfer which results in overall poor UX when trying to move assets across
|
|
chains.</p>
|
|
<h2 id="motivation"><a class="header" href="#motivation">Motivation</a></h2>
|
|
<p>XCM is the de-facto cross-chain messaging protocol within the Polkadot ecosystem, and cross-chain
|
|
assets transfers is one of its main use-cases. Unfortunately, in its current spec, it does not support
|
|
initiating on a remote chain, one or more transfers that combine assets with different transfer types.<br />
|
|
For example, <code>ParachainA</code> cannot instruct <code>AssetHub</code> to teleport <code>ForeignAssetX</code> to <code>ParachainX</code> alongside
|
|
<code>USDT</code> (which has to be reserve transferred) using current XCM specification.</p>
|
|
<p>There currently exist <code>DepositReserveAsset</code>, <code>InitiateReserveWithdraw</code> and <code>InitiateTeleport</code> instructions
|
|
that initiate asset transfers on execution, but they are opinionated in the type of transfer to use.
|
|
Combining them is also not possible, because as a result of their individual execution, a message containing
|
|
a <code>ClearOrigin</code> instruction is sent to the destination chain, making subsequent transfers impossible after
|
|
the first instruction is executed.</p>
|
|
<p>The new instruction proposed by this RFC allows an XCM program to describe multiple asset transfer types,
|
|
then execute them in one shot with a single <code>remote_xcm</code> program sent to the target chain to effect
|
|
the transfer and subsequently clear origin.</p>
|
|
<p>Multi-hop asset transfers will benefit from this change by allowing single XCM program to handle multiple
|
|
types of transfers and reduce complexity.</p>
|
|
<p>Bridge asset transfers greatly benefit from this change by allowing building XCM programs to transfer multiple
|
|
assets across multiple hops in a single pseudo-atomic action.<br />
|
|
For example, allows single XCM program execution to transfer multiple assets from <code>ParaK</code> on Kusama, through
|
|
Kusama Asset Hub, over the bridge through Polkadot Asset Hub with final destination <code>ParaP</code> on Polkadot.</p>
|
|
<p>With current XCM, we are limited to doing multiple independent transfers for each individual hop in order to
|
|
move both "interesting" assets, but also "supporting" assets (used to pay fees).</p>
|
|
<h2 id="stakeholders"><a class="header" href="#stakeholders">Stakeholders</a></h2>
|
|
<ul>
|
|
<li>Runtime users</li>
|
|
<li>Runtime devs</li>
|
|
<li>Wallet devs</li>
|
|
<li>dApps devs</li>
|
|
</ul>
|
|
<h2 id="explanation"><a class="header" href="#explanation">Explanation</a></h2>
|
|
<p>A new instruction <code>InitiateAssetsTransfer</code> 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.</p>
|
|
<p><strong>Note:</strong> Transferring assets that require different paths (chains along the way) is <em>not supported
|
|
within same XCM</em> 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.</p>
|
|
<p>The usage and composition model of <code>InitiateAssetsTransfer</code> is the same as with existing
|
|
<code>DepositReserveAsset</code>, <code>InitiateReserveWithdraw</code> and <code>InitiateTeleport</code> 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.</p>
|
|
<p>We can specify the desired transfer type for some asset(s) using:</p>
|
|
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
|
|
</span><span class="boring">fn main() {
|
|
</span>/// 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),
|
|
}
|
|
<span class="boring">}</span></code></pre></pre>
|
|
<p>This RFC proposes 1 new XCM instruction:</p>
|
|
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
|
|
</span><span class="boring">fn main() {
|
|
</span>/// 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*.
|
|
///
|
|
InitiateAssetsTransfer {
|
|
destination: Location,
|
|
assets: Vec<AssetTransferFilter>,
|
|
remote_fees: Option<AssetTransferFilter>,
|
|
remote_xcm: Xcm<()>,
|
|
}
|
|
<span class="boring">}</span></code></pre></pre>
|
|
<p>An <code>InitiateAssetsTransfer { .. }</code> instruction shall transfer to <code>dest</code>, all assets in the <code>holding</code> register
|
|
that match the provided <code>assets</code> and <code>remote_fees</code> 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 <code>dest</code> for handling
|
|
the remote side of the transfer.</p>
|
|
<p>It should do so using same mechanisms as existing <code>DepositReserveAsset</code>, <code>InitiateReserveWithdraw</code>, <code>InitiateTeleport</code>
|
|
instructions but practically combining all required XCM instructions to be remotely executed into a <em>single</em>
|
|
remote XCM program to be sent over to <code>dest</code>.</p>
|
|
<p>Furthermore, through <code>remote_fees: Option<AssetTransferFilter></code>, it shall allow specifying a single asset to be used
|
|
for fees on <code>dest</code> chain. This single asset shall be remotely handled/received by the <strong>first instruction</strong> in the
|
|
onward XCM and shall be followed by a <code>BuyExecution</code> instruction using it.
|
|
If <code>remote_fees</code> is set to <code>None</code>, the <strong>first instruction</strong> in the onward XCM shall be a <code>UnpaidExecution</code> instruction.
|
|
The rest of the assets shall be handled by subsequent instructions, thus also finally allowing
|
|
<a href="https://github.com/paritytech/polkadot-sdk/issues/2423">single asset buy execution</a> barrier security recommendation.</p>
|
|
<p>The <code>BuyExecution</code> appended to the onward XCM specifies <code>WeightLimit::Unlimited</code>, thus being limited only by the
|
|
<code>remote_fees</code> 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.</p>
|
|
<p>The onward XCM, following the assets transfers instructions, <code>ClearOrigin</code> or <code>DescendOrigin</code> instructions shall be
|
|
appended to stop acting on behalf of the source chain, then the caller-provided <code>remote_xcm</code> shall also be appended,
|
|
allowing the caller to control what to do with the transferred assets.</p>
|
|
<h3 id="example-usage-transferring-2-different-asset-types-across-3-chains"><a class="header" href="#example-usage-transferring-2-different-asset-types-across-3-chains">Example usage: transferring 2 different asset types across 3 chains</a></h3>
|
|
<ul>
|
|
<li>Transferring ROCs as the native asset of <code>RococoAssetHub</code> and PENs as the native asset of <code>Penpal</code>,</li>
|
|
<li>Transfer origin is <code>Penpal</code> (on Rococo) and the destination is <code>WestendAssetHub</code> (across the bridge),</li>
|
|
<li>ROCs are native to <code>RococoAssetHub</code> and are registered as trust-backed assets on <code>Penpal</code> and <code>WestendAssetHub</code>,</li>
|
|
<li>PENs are native to <code>Penpal</code> and are registered as teleportable assets on <code>RococoAssetHub</code> and as
|
|
foreign assets on <code>WestendAssetHub</code>,</li>
|
|
<li>Fees on <code>RococoAssetHub</code> and <code>WestendAssetHub</code> are paid using ROCs.</li>
|
|
</ul>
|
|
<p>We can transfer them from <code>Penpal</code> (Rococo), through <code>RococoAssetHub</code>, over the bridge to <code>WestendAssetHub</code>
|
|
by executing a <em>single</em> XCM message, even though we'll be mixing multiple types of transfers along the path:</p>
|
|
<ol>
|
|
<li>1st leg of the transfer: Penpal -> Rococo Asset Hub:
|
|
<ul>
|
|
<li>teleport PENs</li>
|
|
<li>reserve withdraw ROCs</li>
|
|
</ul>
|
|
</li>
|
|
<li>2nd leg of the transfer: Rococo Asset Hub -> Westend Asset Hub:
|
|
<ul>
|
|
<li>reserve deposit both PENs and ROCs</li>
|
|
</ul>
|
|
</li>
|
|
</ol>
|
|
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
|
|
</span><span class="boring">fn main() {
|
|
</span>Penpal::execute_with(|| {
|
|
let destination = Location::new(2, (GlobalConsensus(Westend), Parachain(1000)).into());
|
|
let rocs_id: AssetId = Parent.into();
|
|
let rocs: Asset = (rocs_id.clone(), rocs_amount).into();
|
|
let pens: Asset = (pens_id, pens_amount).into();
|
|
let assets: Assets = vec![rocs.clone(), pens.clone()].into();
|
|
|
|
// XCM to be executed at dest (Westend Asset Hub)
|
|
let xcm_on_dest =
|
|
Xcm(vec![DepositAsset { assets: Wild(All), beneficiary: beneficiary.clone() }]);
|
|
|
|
// XCM to be executed at Rococo Asset Hub
|
|
let context = PenpalUniversalLocation::get();
|
|
let reanchored_assets = assets.clone().reanchored(&local_asset_hub, &context).unwrap();
|
|
let reanchored_dest = destination.clone().reanchored(&local_asset_hub, &context).unwrap();
|
|
let reanchored_rocs_id = rocs_id.clone().reanchored(&local_asset_hub, &context).unwrap();
|
|
|
|
// from AHR, both ROCs and PENs are local-reserve transferred to Westend Asset Hub
|
|
let assets_filter = vec![
|
|
AssetTransferFilter::ReserveDeposit(reanchored_assets.clone().into())
|
|
];
|
|
// we want to pay with ROCs on WAH
|
|
let remote_fees = Some(AssetTransferFilter::ReserveDeposit(
|
|
AssetFilter::Wild(AllOf { id: reanchored_rocs_id.into(), fun: WildFungibility::Fungible }))
|
|
);
|
|
let xcm_on_ahr = Xcm(vec![
|
|
InitiateAssetsTransfer {
|
|
dest: reanchored_dest,
|
|
assets: assets_filter,
|
|
remote_fees: Some(),
|
|
remote_xcm: xcm_on_dest,
|
|
},
|
|
]);
|
|
|
|
// pay remote fees with ROCs
|
|
let remote_fees = Some(
|
|
AssetTransferFilter::ReserveWithdraw(
|
|
AssetFilter::Wild(AllOf { id: rocs_id.into(), fun: WildFungibility::Fungible })
|
|
)
|
|
);
|
|
// XCM to be executed locally
|
|
let xcm = Xcm::<penpal_runtime::RuntimeCall>(vec![
|
|
// Withdraw both ROCs and PENs from origin account
|
|
WithdrawAsset(assets.clone().into()),
|
|
// Execute the transfers while paying remote fees with ROCs
|
|
InitiateAssetsTransfer {
|
|
dest: local_asset_hub,
|
|
assets: vec![
|
|
// ROCs are reserve-withdrawn on AHR
|
|
ReserveWithdraw(rocs.into()),
|
|
// PENs are teleported to AHR
|
|
Teleport(pens.into()),
|
|
],
|
|
remote_fees,
|
|
remote_xcm: xcm_on_ahr,
|
|
},
|
|
]);
|
|
|
|
<Penpal as PenpalPallet>::PolkadotXcm::execute(
|
|
signed_origin,
|
|
bx!(xcm::VersionedXcm::V4(xcm.into())),
|
|
Weight::MAX,
|
|
).unwrap();
|
|
})
|
|
<span class="boring">}</span></code></pre></pre>
|
|
<h2 id="drawbacks"><a class="header" href="#drawbacks">Drawbacks</a></h2>
|
|
<p>No drawbacks identified.</p>
|
|
<h2 id="testing-security-and-privacy"><a class="header" href="#testing-security-and-privacy">Testing, Security, and Privacy</a></h2>
|
|
<p>There should be no security risks related to the new instruction from the XCVM perspective. It follows the same
|
|
pattern as with single-type asset transfers, only now it allows combining multiple types at once.</p>
|
|
<p><em>Improves</em> security by enabling
|
|
<a href="https://github.com/paritytech/polkadot-sdk/issues/2423">enforcement of single asset for buying execution</a>,
|
|
which minimizes the potential free/unpaid work that a receiving chain has to do. It does so, by making the
|
|
required execution fee payment, part of the instruction logic through the <code>remote_fees: Option<AssetTransferFilter></code>
|
|
parameter, which will make sure the remote XCM starts with a single-asset-holding-loading-instruction,
|
|
immediately followed by a <code>BuyExecution</code> using said asset.</p>
|
|
<h2 id="performance-ergonomics-and-compatibility"><a class="header" href="#performance-ergonomics-and-compatibility">Performance, Ergonomics, and Compatibility</a></h2>
|
|
<p>This brings no impact to the rest of the XCM spec. It is a new, independent instruction, no changes to existing instructions.</p>
|
|
<p>Enhances the exposed functionality of Polkadot. Will allow multi-chain transfers that are currently forced to happen in
|
|
multiple programs per asset per "hop", to be possible in a single XCM program.</p>
|
|
<h3 id="performance"><a class="header" href="#performance">Performance</a></h3>
|
|
<p>No performance changes/implications.</p>
|
|
<h3 id="ergonomics"><a class="header" href="#ergonomics">Ergonomics</a></h3>
|
|
<p>The proposal enhances developers' and users' cross-chain asset transfer capabilities. This enhancement is optimized for XCM
|
|
programs transferring multiple assets, needing to run their logic across multiple chains.</p>
|
|
<h3 id="compatibility"><a class="header" href="#compatibility">Compatibility</a></h3>
|
|
<p>Does this proposal break compatibility with existing interfaces, older versions of implementations? Summarize necessary
|
|
migrations or upgrade strategies, if any.</p>
|
|
<p>This enhancement is compatible with all <strong>existing</strong> XCM programs and versions.</p>
|
|
<p>New (XCMv5) programs using this instruction shall be best-effort downgraded to an older XCM version, but cannot guarantee
|
|
success.
|
|
A program where the new instruction is used to initiate multiple types of asset transfers, cannot be downgraded to older
|
|
XCM versions, because there is no equivalent capability there.
|
|
Such conversion attempts will explicitly fail.</p>
|
|
<h2 id="prior-art-and-references"><a class="header" href="#prior-art-and-references">Prior Art and References</a></h2>
|
|
<p>None.</p>
|
|
<h2 id="unresolved-questions"><a class="header" href="#unresolved-questions">Unresolved Questions</a></h2>
|
|
<p>None.</p>
|
|
<h2 id="future-directions-and-related-material"><a class="header" href="#future-directions-and-related-material">Future Directions and Related Material</a></h2>
|
|
<p>None.</p>
|
|
|
|
</main>
|
|
|
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
|
<!-- Mobile navigation buttons -->
|
|
<a rel="prev" href="../approved/0099-transaction-extension-version.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
<a rel="next prefetch" href="../approved/0101-xcm-transact-remove-max-weight-param.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
|
|
<div style="clear: both"></div>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
|
<a rel="prev" href="../approved/0099-transaction-extension-version.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
<i class="fa fa-angle-left"></i>
|
|
</a>
|
|
|
|
<a rel="next prefetch" href="../approved/0101-xcm-transact-remove-max-weight-param.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
<i class="fa fa-angle-right"></i>
|
|
</a>
|
|
</nav>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
window.playground_copyable = true;
|
|
</script>
|
|
|
|
|
|
<script src="../elasticlunr.min.js"></script>
|
|
<script src="../mark.min.js"></script>
|
|
<script src="../searcher.js"></script>
|
|
|
|
<script src="../clipboard.min.js"></script>
|
|
<script src="../highlight.js"></script>
|
|
<script src="../book.js"></script>
|
|
|
|
<!-- Custom JS scripts -->
|
|
|
|
|
|
</div>
|
|
</body>
|
|
</html>
|