Skip to content
  1. Dec 12, 2023
    • Branislav Kontur's avatar
      Ensure xcm versions over bridge (on sending chains) (#2481) · 575b8f8d
      Branislav Kontur authored
      ## Summary
      
      This pull request proposes a solution for improved control of the
      versioned XCM flow over the bridge (across different consensus chains)
      and resolves the situation where the sending chain/consensus has already
      migrated to a higher XCM version than the receiving chain/consensus.
      
      ## Problem/Motivation
      
      The current flow over the bridge involves a transfer from AssetHubRococo
      (AHR) to BridgeHubRococo (BHR) to BridgeHubWestend (BHW) and finally to
      AssetHubWestend (AHW), beginning with a reserve-backed transfer on AHR.
      
      In this process:
      1. AHR sends XCM `ExportMessage` through `XcmpQueue`, incorporating XCM
      version checks using the `WrapVersion` feature, influenced by
      `pallet_xcm::SupportedVersion` (managed by
      `pallet_xcm::force_xcm_version` or version discovery).
      
      2. BHR handles the `ExportMessage` instruction, utilizing the latest XCM
      version. The `HaulBlobExporter` converts the inner XCM to
      [`VersionedXcm::from`](https://github.com/paritytech/polkadot-sdk/blob/63ac2471/polkadot/xcm/xcm-builder/src/universal_exports.rs#L465-L467),
      also using the latest XCM version.
      
      However, challenges arise:
      - Incompatibility when BHW uses a different version than BHR. For
      instance, if BHR migrates to **XCMv4** while BHW remains on **XCMv3**,
      BHR's `VersionedXcm::from` uses `VersionedXcm::V4` variant, causing
      encoding issues for BHW.
        ```
      	/// Just a simulation of possible error, which could happen on BHW
      	/// (this code is based on actual master without XCMv4)
      	let encoded = hex_literal::hex!("0400");
      	println!("{:?}", VersionedXcm::<()>::decode(&mut &encoded[..]));
      
      Err(Error { cause: None, desc: "Could not decode `VersionedXcm`, variant
      doesn't exist" })
        ``` 
      - Similar compatibility issues exist between AHR and AHW.
      
      ## Solution
      
      This pull request introduces the following solutions:
      
      1. **New trait `CheckVersion`** - added to the `xcm` module and exposing
      `pallet_xcm::SupportedVersion`. This enhancement allows checking the
      actual XCM version for desired destinations outside of the `pallet_xcm`
      module.
      
      2. **Version Check in `HaulBlobExporter`** uses `CheckVersion` to check
      known/configured destination versions, ensuring compatibility. For
      example, in the scenario mentioned, BHR can store the version `3` for
      BHW. If BHR is on XCMv4, it will attempt to downgrade the message to
      version `3` instead of using the latest version `4`.
      
      3. **Version Check in `pallet-xcm-bridge-hub-router`** - this check
      ensures compatibility with the real destination's XCM version,
      preventing the unnecessary sending of messages to the local bridge hub
      if versions are incompatible.
      
      These additions aim to improve the control and compatibility of XCM
      flows over the bridge and addressing issues related to version
      mismatches.
      
      ## Possible alternative solution
      
      _(More investigation is needed, and at the very least, it should extend
      to XCMv4/5. If this proves to be a viable option, I can open an RFC for
      XCM.)._
      
      Add the `XcmVersion` attribute to the `ExportMessage` so that the
      sending chain can determine, based on what is stored in
      `pallet_xcm::SupportedVersion`, the version the destination is using.
      This way, we may not need to handle the version in `HaulBlobExporter`.
      
      ```
      ExportMessage {
      	network: NetworkId,
      	destination: InteriorMultiLocation,
      	xcm: Xcm<()>
      	destination_xcm_version: Version, // <- new attritbute
      },
      ```
      
      ```
      pub trait ExportXcm {
              fn validate(
      		network: NetworkId,
      		channel: u32,
      		universal_source: &mut Option<InteriorMultiLocation>,
      		destination: &mut Option<InteriorMultiLocation>,
      		message: &mut Option<Xcm<()>>,
                      destination_xcm_version: Version, , // <- new attritbute
      	) -> SendResult<Self::Ticket>;
      ```
      
      ## Future Directions
      
      This PR does not fix version discovery over bridge, further
      investigation will be conducted here:
      https://github.com/paritytech/polkadot-sdk/issues/2417.
      
      ## TODO
      
      - [x] `pallet_xcm` mock for tests uses hard-coded XCM version `2` -
      change to 3 or lastest?
      - [x] fix `pallet-xcm-bridge-hub-router`
      - [x] fix HaulBlobExporter with version determination
      [here](https://github.com/paritytech/polkadot-sdk/blob/2183669d/polkadot/xcm/xcm-builder/src/universal_exports.rs#L465)
      - [x] add unit-tests to the runtimes
      - [x] run benchmarks for `ExportMessage`
      - [x] extend local run scripts about `force_xcm_version(dest, version)`
      - [ ] when merged, prepare governance calls for Rococo/Westend
      - [ ] add PRDoc
      
      Part of: https://github.com/paritytech/parity-bridges-common/issues/2719
      
      ---------
      
      Co-authored-by: command-bot <>
      575b8f8d
  2. Dec 11, 2023
  3. Dec 06, 2023
    • Adrian Catangiu's avatar
      pallet-xcm: add new flexible `transfer_assets()` call/extrinsic (#2388) · e7651cf4
      Adrian Catangiu authored
      # Motivation (+testing)
      
      ### Enable easy `ForeignAssets` transfers using `pallet-xcm` 
      
      We had just previously added capabilities to teleport fees during
      reserve-based transfers, but what about reserve-transferring fees when
      needing to teleport some non-fee asset?
      
      This PR aligns everything under either explicit reserve-transfer,
      explicit teleport, or this new flexible `transfer_assets()` which can
      mix and match as needed with fewer artificial constraints imposed to the
      user.
      
      This will enable, for example, a (non-system) parachain to teleport
      their `ForeignAssets` assets to AssetHub while using DOT to pay fees.
      (the assets are teleported - as foreign assets should from their owner
      chain - while DOT used for fees can only be reserve-based transferred
      between said parachain and AssetHub).
      
      Added `xcm-emulator` tests for this scenario ^.
      
      # Description
      
      Reverts `(limited_)reserve_transfer_assets` to only allow reserve-based
      transfers for all `assets` including fees.
      
      Similarly `(limited_)teleport_assets` only allows teleports for all
      `assets` including fees.
          
      For complex combinations of asset transfers where assets and fees may
      have different reserves or different reserve/teleport trust
      configurations, users can use the newly added `transfer_assets()`
      extrinsic which is more flexible in allowing more complex scenarios.
      
      `assets` (excluding `fees`) must have same reserve location or otherwise
      be teleportable to `dest`.
      No limitations imposed on `fees`.
      
      - for local reserve: transfer assets to sovereign account of destination
      chain and forward a notification XCM to `dest` to mint and deposit
      reserve-based assets to `beneficiary`.
      - for destination reserve: burn local assets and forward a notification
      to `dest` chain to withdraw the reserve assets from this chain's
      sovereign account and deposit them to `beneficiary`.
      - for remote reserve: burn local assets, forward XCM to reserve chain to
      move reserves from this chain's SA to `dest` chain's SA, and forward
      another XCM to `dest` to mint and deposit reserve-based assets to
      `beneficiary`.
      - for teleports: burn local assets and forward XCM to `dest` chain to
      mint/teleport assets and deposit them to `beneficiary`.
      
      ## Review notes
      
      Only around 500 lines are prod code (see `pallet_xcm/src/lib.rs`), the
      rest of the PR is new tests and improving existing tests.
      
      ---------
      
      Co-authored-by: command-bot <>
      e7651cf4
  4. Nov 24, 2023
  5. Nov 15, 2023
  6. Nov 13, 2023
    • Adrian Catangiu's avatar
      pallet-xcm: enhance `reserve_transfer_assets` to support remote reserves (#1672) · 18257373
      Adrian Catangiu authored
      
      
      ## Motivation
      
      `pallet-xcm` is the main user-facing interface for XCM functionality,
      including assets manipulation functions like `teleportAssets()` and
      `reserve_transfer_assets()` calls.
      
      While `teleportAsset()` works both ways, `reserve_transfer_assets()`
      works only for sending reserve-based assets to a remote destination and
      beneficiary when the reserve is the _local chain_.
      
      ## Solution
      
      This PR enhances `pallet_xcm::(limited_)reserve_withdraw_assets` to
      support transfers when reserves are other chains.
      This will allow complete, **bi-directional** reserve-based asset
      transfers user stories using `pallet-xcm`.
      
      Enables following scenarios:
      - transferring assets with local reserve (was previously supported iff
      asset used as fee also had local reserve - now it works in all cases),
      - transferring assets with reserve on destination,
      - transferring assets with reserve on remote/third-party chain (iff
      assets and fees have same remote reserve),
      - transferring assets with reserve different than the reserve of the
      asset to be used as fees - meaning can be used to transfer random asset
      with local/dest reserve while using DOT for fees on all involved chains,
      even if DOT local/dest reserve doesn't match asset reserve,
      - transferring assets with any type of local/dest reserve while using
      fees which can be teleported between involved chains.
      
      All of the above is done by pallet inner logic without the user having
      to specify which scenario/reserves/teleports/etc. The correct scenario
      and corresponding XCM programs are identified, and respectively, built
      automatically based on runtime configuration of trusted teleporters and
      trusted reserves.
      
      #### Current limitations:
      - while `fees` and "non-fee" `assets` CAN have different reserves (or
      fees CAN be teleported), the remaining "non-fee" `assets` CANNOT, among
      themselves, have different reserve locations (this is also implicitly
      enforced by `MAX_ASSETS_FOR_TRANSFER=2`, but this can be safely
      increased in the future).
      - `fees` and "non-fee" `assets` CANNOT have **different remote**
      reserves (this could also be supported in the future, but adds even more
      complexity while possibly not being worth it - we'll see what the future
      holds).
      
      Fixes https://github.com/paritytech/polkadot-sdk/issues/1584
      Fixes https://github.com/paritytech/polkadot-sdk/issues/2055
      
      ---------
      
      Co-authored-by: default avatarFrancisco Aguirre <[email protected]>
      Co-authored-by: default avatarBranislav Kontur <[email protected]>
      18257373