Использование паллета X-Tokens для отправки XC-20

Andrey P.
Moonbeam in Russian
9 min readApr 18, 2022

Введение

Создание XCM-сообщения для передачи взаимозаменяемых активов — задача не из легких. Поэтому существуют функции-обёртки/палеты, которые разработчики могут использовать для использования возможностей XCM в Polkadot/Kusama.

Одним из примеров таких оберток является палетка X-Tokens, которая предоставляет различные методы передачи движимых активов через XCM.

Это руководство покажет вам, как использовать палету X-Tokens для отправки XC-20 из сети на базе Moonbeam в другие сети экосистемы (релейные цепи/парачейны). Более того, вы также узнаете, как использовать прекомпиляцию X-Tokens для выполнения тех же действий через Ethereum API.

Разработчики должны понимать, что отправка некорректных сообщений XCM может привести к потере средств. Следовательно, важно протестировать функции XCM на TestNet, прежде чем переходить к производственной среде.

Общие определения XCM

  • XCM — расшифровывается как кросс-консенсусное сообщение, это общий способ общения консенсусных систем друг с другом
  • VMP — означает вертикальную передачу сообщений, она позволяет парачейнам обмениваться сообщениями с релейной цепочкой. UMP (передача сообщений вверх) позволяет парачайнам посылать сообщения своей релейной цепочке, а DMP (передача сообщений вниз) позволяет релейной цепочке передавать сообщения вниз одному из своих парачайнов.
  • XCMP — обозначает передачу сообщений с перекрестным консенсусом, позволяет парачейнам обмениваться сообщениями с другими парачейнами в той же релейной цепи
  • HRMP — обозначает горизонтальную передачу сообщений с релейной маршрутизацией, промежуточный протокол, пока не будет запущена полная реализация XCMP. Тот же интерфейс, что и у XCMP, но сообщения хранятся на релейной цепочке.
  • Multilocation — способ указать точку во всей экосистеме релейной цепочки/парачейна от заданного начала, относительную или абсолютную. Например, он может использоваться для указания конкретного парачейна, актива, счета или даже паллеты внутри парачейна. В общих чертах, мультилокация определяется родителями и внутренним пространством. Родительский относится к тому, сколько “прыжков” в родительский блокчейн вам нужно сделать из данного источника. Внутренняя часть означает, сколько полей вам нужно для определения целевой точки. Например, чтобы нацелиться на парачейн с ID 1000 из другого парачейна, мультилокация будет иметь вид {“ parents”: 1, “interior”: { “X1”: [{ “Parachain”: 1000 }]}}}

Интерфейс палетa X-Tokens

Палет X-Tokens предоставляет следующие экстринсики (функции):

  • transfer(currencyId, amount, dest, destWeight) — передача валюты, определенной либо как собственный токен (саморезервируемый), либо с идентификатором актива.
  • transferMultiasset(asset, dest, destWeight) — передача взаимозаменяемого актива, определяемого его мультилокацией
  • transferMultiassetWithFee(asset, fee, dest, destWeight) — передача сменного актива, но позволяет отправителю оплатить комиссию другим активом. Оба варианта определяются по их мультилокации
  • transferMultiassets(assets, feeItem, dest, destWeight) — передача нескольких сменных активов с указанием того, какой из них используется в качестве платы. Каждый актив определяется его мультилокацией
  • transferMulticurrencies(currencies, feeItem, dest, destWeight) — перевести различные валюты, указав, какая из них используется в качестве платы. Каждая валюта определяется либо как нативный токен (саморезервируемый), либо с помощью идентификатора актива
  • transferWithFee(currencyId, amount, fee, dest, destWeight) — перевод валюты, но позволяет отправителю оплатить комиссию другим активом. Обе функции определяются мультилокацией

Где входы, которые необходимо предоставить, могут быть определены как:

  • currencyId/currencies — идентификатор/идентификаторы валюты/валют, отправляемых через XCM. Различные среды выполнения имеют разные способы определения идентификаторов. В случае сетей на базе Moonbeam, SelfReserve относится к собственному токену, а OtherReserve — к активу
  • amount — количество токенов, которые будут отправлены через XCM
  • dest — мультилокация для определения адреса назначения для токенов, отправляемых через XCM. Поддерживаются различные форматы адресов, например, 20 или 32 байта (Ethereum или Substrate)
  • destWeight — максимальное количество времени выполнения, которое вы хотите предоставить в цепочке назначения для выполнения отправляемого XCM-сообщения. Если не обеспечить достаточный вес, выполнение XCM будет неудачным, и средства могут быть заблокированы либо на главном счете, либо на специальном паллете. Важно правильно установить вес назначения, чтобы избежать неудачного выполнения XCM
  • asset/assets — мультилокация для определения актива/активов, отправляемых через XCM. Каждый парачейн имеет свой способ ссылки на активы. Например, сети на основе Moonbeam ссылаются на свои родные токены с помощью индекса остатков на паллетах
  • fee — мультиместо для определения актива, используемого для оплаты выполнения XCM в целевой сети
  • feeItem — индекс для определения позиции актива в массиве отправляемых активов, используемых для оплаты исполнения XCM в целевой цепочке. Например, если отправляется только один актив, feeItem будет равен 0.

Единственный метод чтения, который предоставляет паллет, это palletVersion, который позволяет узнать версию используемого паллета X-Tokens.

Создание XCM с помощью палета X-Tokens

В данном руководстве рассматривается процесс создания сообщения XCM с помощью палетки X-Tokens, а точнее, с помощью функций transfer и transferMultiasset. Тем не менее, эти два случая могут быть экстраполированы на другие функции, особенно если вы знакомы с мультилокациями.

Примечание

Каждый парачейн может разрешать/запрещать определенные методы из палетки. Следовательно, разработчики должны обеспечить использование методов, которые разрешены. В противном случае транзакция завершится с ошибкой, подобной system.CallFiltered.

Проверка предварительных условий

Чтобы иметь возможность отправлять extrinsics в Polkadot.js Apps, вам необходимо иметь аккаунт с денежными средствами.

Кроме того, для этого урока вам понадобятся токены xcUNIT, которые являются XC-20 представлением токена UNIT релейной цепи Alphanet. Вы можете приобрести их, обменяв на токены DEV (родной токен Moonbase Alpha) на Moonbeam-Swap, демонстрационном клоне Uniswap-V2 на Moonbase Alpha.

Чтобы проверить баланс xcUNIT, вы можете добавить XC-20 в MetaMask со следующим адресом:

0xFfFFfFff1FcaCBd218EDc0EbA20Fc2308C778080

Вы можете посмотреть страницу XC-20, чтобы узнать, как вычислить этот адрес.

Передаточная функция X-Tokens

В этом примере вы создадите сообщение XCM для передачи xcUNIT с Moonbase Alpha обратно на ее релейную цепочку с помощью функции `transfer функции паллета X-Tokens.

Если вы проверили все необходимые условия, перейдите на страницу внешних условий Polkadot JS Apps и установите следующие параметры:

1.Выберите учетную запись , с которого вы хотите отправить XCM.

2.Выберите паллет xTokens

3.Выберите extrinsic перевода

4.Установите идентификатор валюты на OtherReserve. Это необходимо потому, что вы не переводите токены DEV (SelfReserve).

5.Введите идентификатор актива. В данном примере xcUNIT имеет идентификатор актива 42259045809535163221576417993425387648. Вы можете проверить все доступные идентификаторы активов в разделе адреса XC-20.

6.Установите количество токенов для отправки. В данном примере вы отправляете 1 xcUNIT, но вы должны учесть 12 десятичных знаков xcUNIT. Чтобы узнать, сколько десятичных знаков имеет токен XC-20, вы можете проверить его метаданные.

7.Чтобы определить мультилокацию назначения XCM, вы должны выбрать в качестве источника учетную запись в релейной цепочке с Moonbase Alpha. Поэтому задайте следующие параметры:

8.Установите конечный вес на 1000000000. Обратите внимание, что на Moonbase Alpha каждая инструкция XCM стоит около 100000000 единиц веса. Перевод состоит из 4 инструкций XCM, поэтому веса места назначения в 400000000 должно быть достаточно.

9.Нажмите кнопку Отправить транзакцию и подпишите транзакцию.

Примечание

Кодированные данные вызова для настроенного выше extrinsict — 0x1e00018080778c30c20fa2ebc0ed18d2cbca1f0010a5d4e800000000000000000001010100c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300ca9a3b00000000. В нем также указан конкретный получатель, которого вам нужно изменить.

Как только транзакция будет обработана, TargetAccount должен получить переведенную сумму за вычетом небольшой комиссии, которая удерживается для выполнения XCM на цепочке назначения. На Polkadot.js Apps можно проверить соответствующие экстринсики и события на Moonbase Alpha и релейной цепочке.

Функция X-Tokens Transfer MultiAsset Function

В этом примере вы создадите XCM-сообщение для передачи xcUNIT с Moonbase Alpha обратно на ее релейную цепочку, используя функцию transferMultiasset паллета X-Tokens.

Если вы проверили все необходимые условия, перейдите на страницу внешних условий Polkadot JS Apps и установите следующие параметры:

  1. Выберите учетную запись, с которой вы хотите отправить XCM.
  2. Выберите паллет xTokens
  3. Выберите extrinsic transferMultiasset
  4. Чтобы определить мультилокацию актива XCM, вы должны указать UNIT в релейной цепочке с Moonbase Alpha в качестве источника. Каждая цепочка видит свой актив по-разному. Поэтому для каждого пункта назначения необходимо задать разное мультирасположение актива. Для этого примера токен релейной цепи можно определить как:

5.Установите тип актива как Fungible

6.Установите количество токенов для отправки. В данном примере вы отправляете 1 xcUNIT, но вы должны учесть 12 десятичных знаков.

7.Чтобы определить мультилокацию назначения XCM, вы должны выбрать в качестве источника аккаунт в релейной цепочке с Moonbase Alpha. Поэтому установите следующие параметры:

8.Установите вес назначения на 1000000000. Обратите внимание, что на Moonbase Alpha каждая инструкция XCM стоит около 100000000 единиц веса. TransferMultiasset состоит из 4 инструкций XCM, поэтому веса назначения в 400000000 должно быть достаточно.

9.Нажмите кнопку Отправить транзакцию и подпишите транзакцию.

Примечание

Кодированные данные вызова для настроенного выше extrinsict — 0x1e010100010000070010a5d4e80101010100c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300ca9a3b00000000. В нем также указан конкретный получатель, которого вам нужно изменить.

Как только транзакция будет обработана, TargetAccount должен получить переведенную сумму за вычетом небольшой комиссии, которая вычитается за выполнение XCM на цепочке назначения. На Polkadot.js Apps вы можете проверить соответствующие экстерны и события в Moonbase Alpha и релейной цепи.

Предварительная компиляция X-Tokens

Контракт X-Tokens precompile позволяет разработчикам получить доступ к функциям передачи токенов XCM через Ethereum API сетей на базе Moonbeam. Как и другие контракты прекомпиляции, прекомпиляция X-Tokens находится по следующим адресам:

Интерфейс X-Tokens Solidity

Xtokens.sol — это интерфейс, с помощью которого разработчики могут взаимодействовать с палетой X-Tokens, используя API Ethereum.

Интерфейс включает следующие функции:

  • transfer(address currency_address, uint256 amount, Multilocation memory destination, uint64 weight) — функция, представляющая метод передачи, описанный в предыдущем примере. Однако вместо идентификатора валюты необходимо указать адрес XC-20. Мультилокация строится особым образом, который описан в следующем разделе
  • transfer_multiasset(Multilocation memory asset, uint256 amount, Multilocation memory destination, uint64 weight) — функция, представляющая метод transferMultiasset, описанный в предыдущем примере. Оба мультилокации строятся особым образом, который описан в следующем разделе

Построение прекомпилированного мультилокатора

В интерфейсе прекомпиляции X-Tokens структура Multilocation определена следующим образом:

struct Multilocation {

uint8 parents;

bytes [] interior;

}

Обратите внимание, что каждая мультилокация имеет элемент родитель, определяемый в данном случае uint8, и массив байтов. Родители указывают, сколько “прыжков” в направлении вверх вам нужно сделать, если вы проходите через релейную цепочку. Поскольку это uint8, обычными значениями являются:

Массив bytes (bytes[]) определяет внутреннее пространство и его содержимое в мультилокации. Размер массива определяет внутреннее значение следующим образом:

Предположим, что массив bytes содержит данные. Первый байт каждого элемента (2 шестнадцатеричных числа) соответствует селектору данного поля XN. Например:

Далее, в зависимости от селектора и его типа данных, следующие байты соответствуют фактически предоставляемым данным. Обратите внимание, что для AccountId32, AccountIndex64 и AccountKey20 в конце добавляется поле сети, показанное в примере Polkadot.js Apps. Например:

Примечание

Внутренние данные обычно необходимо заключать в кавычки. В противном случае вы можете получить ошибку недопустимого значения элемента связки.xc20

В следующем фрагменте кода рассматриваются некоторые примеры структур мультилокации, поскольку они должны быть введены в функции предварительной компиляции X-Tokens:

// Multilocation targeting the relay chain asset from a parachain

{

1, // parents = 1

[] // interior = here

}

// Multilocation targeting Moonbase Alpha DEV token from another parachain

{

1, // parents = 1

// Size of array is 2, meaning is an X2 interior

[

“0x00000003E8”, // Selector Parachain, ID = 1000 (Moonbase Alpha)

“0x0403” // Pallet Instance = 3

]

}

// Multilocation targeting Alice’s account on the Relay Chain from Moonbase Alpha

{

1, // parents = 0

// Size of array is 1, meaning is an X1 interior

[

“0x01c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300”

// AccountKey32 Selector + Address in hex + Network = Any

]

}

--

--