Transferências Nativas de Tokens Entre Cadeias¶
Introdução¶
Como apresentado no artigo sobre Comunicação Nativa Entre Cadeias na seção Learn, redes powered by Tanssi contam com a capacidade nativa de se comunicar e interoperar com qualquer outra rede do ecossistema. Essa comunicação entre cadeias permite transferências de tokens seguras e rápidas usando o formato Cross-Consensus Message (XCM), que facilita a comunicação entre diferentes sistemas de consenso.
O protocolo de comunicação que possibilita as transferências é construído sobre o Substrate e opera em um nível mais baixo que o EVM, o que dificulta o acesso direto para desenvolvedores EVM.
Ainda assim, redes EVM contam com um precompile XCM que preenche a lacuna entre as camadas de execução, expondo uma interface de smart contract que abstrai as complexidades subjacentes e torna a execução de transferências cross-chain tão simples quanto qualquer chamada de contrato.
Este guia mostra como interagir com o precompile XCM Interface para executar transferências de tokens entre cadeias via Ethereum API.
O precompile XCM está localizado no seguinte endereço:
0x0000000000000000000000000000000000000804
Note
O uso de precompiladas pode trazer consequências inesperadas. As precompiladas do Tanssi são derivadas das do Moonbeam; portanto, familiarize-se com as considerações de segurança das precompiladas do Moonbeam.
A Interface Solidity XCM¶
A interface XCMInterface.sol nas redes EVM da Tanssi é uma interface Solidity que permite aos desenvolvedores interagir com as funções do precompile.
XCMInterface.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.8.3;
/// @dev The XCM contract's address.
address constant XCM_CONTRACT_ADDRESS = 0x0000000000000000000000000000000000000804;
/// @dev The XCM contract's instance.
XCM constant XCM_CONTRACT = XCM(XCM_CONTRACT_ADDRESS);
/// @author The Moonbeam Team
/// @title XCM precompile Interface
/// @dev The interface that Solidity contracts use to interact with the substrate pallet-xcm.
interface XCM {
// A location is defined by its number of parents and the encoded junctions (interior)
struct Location {
uint8 parents;
bytes[] interior;
}
// Support for Weights V2
struct Weight {
uint64 refTime;
uint64 proofSize;
}
// A way to represent fungible assets in XCM using Location format
struct AssetLocationInfo {
Location location;
uint256 amount;
}
// A way to represent fungible assets in XCM using address format
struct AssetAddressInfo {
address asset;
uint256 amount;
}
/// @dev Function to send assets via XCM using transfer_assets() pallet-xcm extrinsic.
/// @custom:selector 59df8416
/// @param dest The destination chain.
/// @param beneficiary The actual account that will receive the tokens on dest.
/// @param assets The combination (array) of assets to send.
/// @param feeAssetItem The index of the asset that will be used to pay for fees.
/// @param weight The weight to be used for the whole XCM operation.
/// (uint64::MAX in refTime means Unlimited weight)
function transferAssetsLocation(
Location memory dest,
Location memory beneficiary,
AssetLocationInfo[] memory assets,
uint32 feeAssetItem,
Weight memory weight
) external;
/// @dev Function to send assets via XCM to a 20 byte-like parachain
/// using transfer_assets() pallet-xcm extrinsic.
/// @custom:selector b489262e
/// @param paraId The para-id of the destination chain.
/// @param beneficiary The actual account that will receive the tokens on paraId destination.
/// @param assets The combination (array) of assets to send.
/// @param feeAssetItem The index of the asset that will be used to pay for fees.
/// @param weight The weight to be used for the whole XCM operation.
/// (uint64::MAX in refTime means Unlimited weight)
function transferAssetsToPara20(
uint32 paraId,
address beneficiary,
AssetAddressInfo[] memory assets,
uint32 feeAssetItem,
Weight memory weight
) external;
/// @dev Function to send assets via XCM to a 32 byte-like parachain
/// using transfer_assets() pallet-xcm extrinsic.
/// @custom:selector 4461e6f5
/// @param paraId The para-id of the destination chain.
/// @param beneficiary The actual account that will receive the tokens on paraId destination.
/// @param assets The combination (array) of assets to send.
/// @param feeAssetItem The index of the asset that will be used to pay for fees.
/// @param weight The weight to be used for the whole XCM operation.
/// (uint64::MAX in refTime means Unlimited weight)
function transferAssetsToPara32(
uint32 paraId,
bytes32 beneficiary,
AssetAddressInfo[] memory assets,
uint32 feeAssetItem,
Weight memory weight
) external;
/// @dev Function to send assets via XCM to the relay chain
/// using transfer_assets() pallet-xcm extrinsic.
/// @custom:selector d7c89659
/// @param beneficiary The actual account that will receive the tokens on the relay chain.
/// @param assets The combination (array) of assets to send.
/// @param feeAssetItem The index of the asset that will be used to pay for fees.
/// @param weight The weight to be used for the whole XCM operation.
/// (uint64::MAX in refTime means Unlimited weight)
function transferAssetsToRelay(
bytes32 beneficiary,
AssetAddressInfo[] memory assets,
uint32 feeAssetItem,
Weight memory weight
) external;
}
A interface inclui as estruturas de dados necessárias e as funções a seguir:
transferAssetsToPara20(paraId, beneficiary, assets, feeAssetItem, weight) — envia assets para outra rede compatível com EVM usando a transação transfer_assets() do pallet XCM
paraIduint32 - ID da rede de destinobeneficiaryaddress - conta do tipo ECDSA na cadeia de destino que receberá os tokensassetsAssetAddressInfo[] memory - array de assets a enviarfeeAssetItemuint32 - índice do asset que pagará as taxasweightWeight memory - gás máximo de toda a operação. Definiruint64::MAXemrefTimeequivale na prática a weight ilimitado
paraId- 888beneficiary- 0x3f0Aef9Bd799F1291b80376aD57530D353ab0217assets- [["0x0000000000000000000000000000000000000800", 1000000000000000000]]feeAssetItem- 0weight- [9223372036854775807, 9223372036854775807]
transferAssetsToPara32(paraId, beneficiary, assets,feeAssetItem, weight) — envia assets para uma rede Substrate usando a transação transfer_assets() do pallet XCM
paraIduint32 - ID da rede de destinobeneficiarybytes32 - conta do tipo SR25519 na cadeia de destino que receberá os tokensassetsAssetAddressInfo[] memory - array de assets a enviarfeeAssetItemuint32 - índice do asset que pagará as taxasweightWeight memory - gás máximo de toda a operação. Definiruint64::MAXemrefTimeequivale na prática a weight ilimitado
paraId- 888beneficiary- 0xf831d83025f527daeed39a644d64d335a4e627b5f4becc78fb67f05976889a06assets- [["0x0000000000000000000000000000000000000800", 1000000000000000000]]feeAssetItem- 0weight- [9223372036854775807, 9223372036854775807]
transferAssetsToRelay(beneficiary, assets, feeAssetItem, weight) — envia assets para a relay chain usando a transação transfer_assets() do pallet XCM
beneficiarybytes32 - conta do tipo sr25519 na relay chain que receberá os tokensassetsAssetAddressInfo[] memory - array de assets a enviarfeeAssetItemuint32 - índice do asset que pagará as taxasweightWeight memory - gás máximo de toda a operação. Definiruint64::MAXemrefTimeequivale na prática a weight ilimitado
beneficiary- 0xf831d83025f527daeed39a644d64d335a4e627b5f4becc78fb67f05976889a06assets- [["0x0000000000000000000000000000000000000800", 1000000000000000000]]feeAssetItem- 0weight- [9223372036854775807, 9223372036854775807]
transferAssetsLocation(dest, beneficiary, assets, feeAssetItem, weight) — envia assets usando a transação transfer_assets() do pallet XCM
destLocation memory - cadeia de destinobeneficiaryLocation memory - conta na cadeia de destino que receberá os tokensassetsAssetLocationInfo[] memory - array de assets a enviarfeeAssetItemuint32 - índice do asset que pagará as taxasweightWeight memory - gás máximo de toda a operação. Definiruint64::MAXemrefTimeequivale na prática a weight ilimitado
dest- ["1",[]]beneficiary- [0, ["0x01f831d83025f527daeed39a644d64d335a4e627b5f4becc78fb67f05976889a0600"]]assets- [[[1, ["0x010000000000000000000000000000000000000800"]], 1000000000000000000]]feeAssetItem- 0weight- [9223372036854775807, 9223372036854775807]
Interaja com a Interface Solidity¶
Verificando Pré-requisitos¶
Para acompanhar este tutorial, configure sua carteira para sua rede EVM e tenha uma conta com tokens nativos. Você pode adicionar sua rede EVM à MetaMask com um clique no Tanssi dApp. Ou configurar a MetaMask para a Tanssi com a rede EVM de demonstração.
Note
É necessário ter canais de comunicação estabelecidos com a cadeia de destino antes de usar a funcionalidade deste precompile. Para isso, consulte o guia Gerenciar Canais de Comunicação Entre Cadeias. Além disso, se o token transferido for nativo da sua rede, a cadeia de destino deve ter registrado o asset estrangeiro.
Configuração do Remix¶
Você pode interagir com o precompile XCM Interface usando o Remix. Para adicioná-lo ao Remix, siga:
- Obtenha uma cópia de
XCMInterface.sol - Cole o conteúdo em um arquivo do Remix chamado
XcmInterface.sol
Compile o Contrato¶
Em seguida, compile a interface no Remix:
- Clique na aba Compile (segunda de cima)
- Clique em Compile XCMInterface.sol para compilar
Quando a compilação concluir, um check verde aparecerá ao lado da aba Compile.
Acesse o Contrato¶
Em vez de implantar o precompile, acesse a interface informando o endereço do contrato pré-compilado:
- Clique na aba Deploy and Run logo abaixo de Compile no Remix. Os contratos pré-compilados já estão acessíveis em seus endereços, portanto não há etapa de deployment
- Certifique-se de que Injected Provider - Metamask está selecionado em ENVIRONMENT. Ao selecionar, a MetaMask pode solicitar conexão com o Remix
- Garanta que a conta correta apareça em ACCOUNT
- Selecione XCM - XCMInterface.sol em CONTRACT. Como é um contrato pré-compilado, não há deployment; apenas informe o endereço do precompile no campo At Address
- Informe o endereço do precompile:
0x0000000000000000000000000000000000000804e clique em At Address
O precompile XCM Interface aparecerá em Deployed Contracts.
Envie tokens para outra rede compatível com EVM¶
Para enviar tokens a uma conta em outra rede compatível com EVM, siga:
- Expanda a função transferAssetsToPara20
- Informe o ID da rede (
paraId) - Informe a conta de destino (20 bytes, estilo Ethereum)
-
Especifique os tokens a transferir. Este parâmetro é um array com pelo menos um asset; cada asset é definido por seu endereço e montante
Note
Os tokens são especificados pelo endereço ERC-20. Se o token que você deseja transferir for o nativo da rede, a precompilada ERC-20 do token nativo ajuda a referenciá-lo por meio de uma interface ERC-20.
-
Informe o índice do asset que pagará as taxas (baseado em zero)
- Informe o gás máximo da transação, derivado de
refTimeeproofSize. Na prática, definirrefTimecomouint64::MAXequivale a weight ilimitado - Clique em transact
- A MetaMask aparecerá para revisão; clique em Confirm para enviar
Após a confirmação, aguarde alguns blocos para o saldo aparecer na cadeia de destino.
Envie Tokens para uma Rede Substrate¶
Para enviar tokens a uma conta em uma rede Substrate, siga:
- Expanda a função transferAssetsToPara32
- Informe o ID da rede (
paraId) - Informe a conta de destino do tipo sr25519
-
Especifique os tokens a transferir. Este parâmetro é um array com pelo menos um asset; cada asset é definido por seu endereço e montante
Note
Os tokens são especificados pelo endereço ERC-20. Se o token que você deseja transferir for o nativo da rede, a precompilada ERC-20 do token nativo ajuda a referenciá-lo por meio de uma interface ERC-20.
-
Informe o índice do asset que pagará as taxas (baseado em zero)
- Informe o gás máximo da transação, derivado de
refTimeeproofSize. Na prática, definirrefTimecomouint64::MAXequivale a weight ilimitado - Clique em transact
- A MetaMask aparecerá para revisão; clique em Confirm para enviar
Após a confirmação, aguarde alguns blocos para o saldo aparecer na cadeia de destino.
Envie Tokens para a Relay Chain¶
Para enviar tokens a uma conta na relay chain, siga:
- Expanda a função transferAssetsToRelay
- Informe a conta de destino do tipo sr25519
-
Especifique os tokens a transferir. Este parâmetro é um array com pelo menos um asset; cada asset é definido por seu endereço e montante
Note
Os tokens são especificados pelo endereço ERC-20. Se o token que você deseja transferir for o nativo da rede, a precompilada ERC-20 do token nativo ajuda a referenciá-lo por meio de uma interface ERC-20.
-
Informe o índice do asset que pagará as taxas (baseado em zero)
- Informe o gás máximo da transação, derivado de
refTimeeproofSize. Na prática, definirrefTimecomouint64::MAXequivale a weight ilimitado - Clique em transact
- A MetaMask aparecerá para revisão; clique em Confirm para enviar
Após a confirmação, aguarde alguns blocos para o saldo aparecer na cadeia de destino.
Envie Tokens para Locais Específicos¶
Esta função é mais genérica e permite especificar cadeia de destino, conta e assets usando XCM Multilocations. Para enviar tokens para locais específicos:
- Expanda a função transferAssetsLocation
- Informe a multilocation que especifica a cadeia de destino. Qualquer cadeia pode ser informada, independentemente de tipo ou configuração
- Informe a multilocation que especifica a conta de destino. Qualquer conta pode ser informada, independentemente do tipo (ECDSA, sr25519 ou outro)
-
Especifique os tokens a transferir. Este parâmetro é um array com pelo menos um asset; cada asset é definido por sua multilocation e montante
Note
Os tokens são especificados pelo endereço ERC-20. Se o token que você deseja transferir for o nativo da rede, a precompilada ERC-20 do token nativo ajuda a referenciá-lo por meio de uma interface ERC-20.
-
Informe o índice do asset que pagará as taxas (baseado em zero)
- Informe o gás máximo da transação, derivado de
refTimeeproofSize. Na prática, definirrefTimecomouint64::MAXequivale a weight ilimitado - Clique em transact
- A MetaMask aparecerá para revisão; clique em Confirm para enviar
Após a confirmação, aguarde alguns blocos para o saldo aparecer na cadeia de destino.
| Criada: 27 de novembro de 2025





