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

Gateway should no longer build token registration XCM #1381

Open
wants to merge 2 commits into
base: v2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 14 additions & 22 deletions contracts/src/v2/Calls.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,17 @@ import {Token} from "../Token.sol";
import {Upgrade} from "../Upgrade.sol";
import {Functions} from "../Functions.sol";
import {Constants} from "../Constants.sol";
import {ScaleCodec} from "../utils/ScaleCodec.sol";

import {
Payload, OperatingMode, Asset, makeNativeAsset, makeForeignAsset, Network
Payload,
OperatingMode,
Asset,
makeNativeAsset,
makeForeignAsset,
Network,
Xcm,
makeRawXCM,
makeCreateAssetXCM
} from "./Types.sol";

import {UD60x18, ud60x18, convert} from "prb/math/src/UD60x18.sol";
Expand All @@ -46,7 +53,7 @@ library CallsV2 {
uint128 executionFee,
uint128 relayerFee
) external {
_sendMessage(msg.sender, xcm, assets, claimer, executionFee, relayerFee);
_sendMessage(msg.sender, makeRawXCM(xcm), assets, claimer, executionFee, relayerFee);
}

// Refer to `IGateway.registerToken` for documentation
Expand All @@ -56,28 +63,13 @@ library CallsV2 {
uint128 executionFee,
uint128 relayerFee
) internal {
// Build XCM for token registration on AHP and possibly AHK
bytes memory xcm;

require(msg.value <= type(uint128).max, IGatewayV2.ExceededMaximumValue());
require(msg.value >= executionFee + relayerFee, IGatewayV2.InsufficientValue());
uint128 etherValue = uint128(msg.value) - executionFee - relayerFee;

if (network == Network.Polkadot) {
// Build XCM that executes on AHP only
xcm = bytes.concat(
hex"05100f0004020109079edaa80200", ScaleCodec.encodeCompactU128(etherValue), hex"040100000700b2118417000d00040100000700b211841700010100ce796ae65569a670d0c1cc1ac12515a3ce21b5fbf729d63d7b289baad070139d06030045013500020209079edaa8020300", abi.encodePacked(token), hex"00ce796ae65569a670d0c1cc1ac12515a3ce21b5fbf729d63d7b289baad070139d010000000000000000000000000000002000"
);
} else if (network == Network.Kusama) {
// Build XCM that is executed on AHP and forwards another message to AHK
xcm = bytes.concat(
hex"deadbeef", abi.encodePacked(token), hex"deadbeef", abi.encodePacked(etherValue)
);
} else {
revert IGatewayV2.ShouldNotReachHere();
}

Xcm memory xcm = makeCreateAssetXCM(token, network);

Functions.registerNativeToken(token);

_sendMessage(address(this), xcm, new bytes[](0), "", executionFee, relayerFee);
}

Expand All @@ -87,7 +79,7 @@ library CallsV2 {

function _sendMessage(
address origin,
bytes memory xcm,
Xcm memory xcm,
bytes[] memory assets,
bytes memory claimer,
uint128 executionFee,
Expand Down
30 changes: 29 additions & 1 deletion contracts/src/v2/Types.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct Payload {
// sender of the message
address origin;
Asset[] assets;
bytes xcm;
Xcm xcm;
bytes claimer;
// ether value
uint128 value;
Expand All @@ -44,6 +44,34 @@ struct Payload {
uint128 relayerFee;
}

struct Xcm {
uint8 kind;
bytes data;
}

library XcmKind {
/// SCALE-encoded raw bytes for `VersionedXcm`
uint8 constant Raw = 0;
/// Create a new asset in the ForeignAssets pallet of AssetHub
uint8 constant CreateAsset = 1;
}
Comment on lines +52 to +57
Copy link
Collaborator Author

@vgeddes vgeddes Feb 14, 2025

Choose a reason for hiding this comment

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

@alistair-singh @claravanstaden @yrong to give more context, this change opens up the possibility of users not strictly needing to pass raw XCM through the bridge to Polkadot.

Instead they can pass in a simpler ABI-encoded data, like:

struct Transfer {
  destination: Location,
  destination_fee: DestinationFee,
  beneficiary: Location,
  transact: Option<Bytes>,
}

// How to obtain destination fee on AH
enum DestinationFee {
    // Swap native ether in `message.value`
    SwapEther {
        in: amount
        out: (Location, amount)
    },
    // Swap asset in `message.assets`
    SwapAsset {
        in: (u8, amount)
        out: (Location, amount)
    },
    // Directly use some amount of an asset in `message.assets`.
    Asset: (u8, amount),
}

Then the inbound-queue can build an XCM that does the following:

  • Obtain the destination fee according to the DestinationFee instruction on AH
  • Adds an InitiateTransfer instruction that forwards message.assets to destination
    • Sets the asset claimer on the destination to beneficiary
    • Deposits into beneficiary account
    • Optionally executes an XCM::Transact

This would simplify the UX and also make it easier for to on-chain contracts to send messages to Polkadot without having to build XCM. It is hard to build XCM onchain.

Would this be useful?


struct AsCreateAsset {
address token;
uint8 network;
}

function makeRawXCM(bytes memory xcm) pure returns (Xcm memory) {
return Xcm({kind: XcmKind.Raw, data: xcm});
}

function makeCreateAssetXCM(address token, Network network) pure returns (Xcm memory) {
return Xcm({
kind: XcmKind.CreateAsset,
data: abi.encode(AsCreateAsset({token: token, network: uint8(network)}))
});
}

struct Asset {
uint8 kind;
bytes data;
Expand Down
6 changes: 4 additions & 2 deletions contracts/test/GatewayV2.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ import {
Payload,
Asset,
makeNativeAsset,
makeForeignAsset
makeForeignAsset,
Xcm,
makeRawXCM
} from "../src/v2/Types.sol";

import {
Expand Down Expand Up @@ -301,7 +303,7 @@ contract GatewayV2Test is Test {
Payload({
origin: user1,
assets: outputAssets,
xcm: "",
xcm: makeRawXCM(""),
claimer: "",
value: 0.5 ether,
executionFee: 0.1 ether,
Expand Down
Loading