Ativos Externos como ERC-20¶
Introdução¶
Como apresentado no artigo Comunicação Cross-Chain Nativa, as redes implantadas através da Tanssi podem se comunicar e interagir com qualquer outra rede no ecossistema. Este ambiente multi-chain leva a um mundo multi-ativo, onde a transferência perfeita de ativos, dados e valor entre diferentes redes amplia as possibilidades de construir casos de uso em diversos setores, como finanças (DeFi), ativos do mundo real (RWAs) e outros.
Ativos externos são tokens nativos de outra blockchain, ou, em outras palavras, ativos cuja cadeia de reserva não é a cadeia com a qual você está interagindo. As redes Tanssi podem registrar ativos externos para permitir sua entrada. Para fazer isso, é necessário estabelecer um canal XCM com a outra cadeia e, em seguida, registrar um de seus ativos nativos como um ativo externo. Os ativos externos registrados se comportam, em certa medida, da mesma forma que os locais.
A pré-compilação de ativos ERC-20 permite que as redes baseadas no Template Tanssi EVM acessem qualquer ativo externo registrado através da interface ERC-20 padrão. Consequentemente, contratos inteligentes implantados na rede podem interagir com esses ativos da mesma forma que fariam com qualquer outro ERC-20 regular.
O endereço que representa o contrato ERC-20 é formado com as primeiras trinta e seis posições (dezoito bytes) definidas para o valor máximo e as últimas quatro posições (dois bytes) substituídas pela representação hexadecimal do identificador de ativo registrado:
Por exemplo, para o ativo cujo ID é 1, as últimas quatro posições devem ser substituídas por 0001, e para um ativo com um ID de 10, essas quatro posições devem ser substituídas por 000A.
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.
Pré-requisitos¶
Para acompanhar o conteúdo deste guia, você precisará:
- Acesso a uma rede Tanssi EVM executando runtime 500 ou superior
- Um canal XCM bidirecional estabelecido para outra cadeia. Para gerenciar os canais da sua rede, consulte o artigo Gerenciar Canais de Comunicação Cross-Chain
- Um ativo externo registrado. Uma vez que os canais XCM estejam abertos, o registro de ativos pode ser facilmente feito usando o dApp, conforme explicado no guia Registrar Ativos Externos
- Finalmente, você precisará de uma carteira compatível com EVM configurada para funcionar com sua rede. Você também pode conectar sua carteira à rede demo EVM.
Os exemplos neste guia são baseados na rede demo Tanssi EVM, que já possui canais abertos para outras redes e ativos externos registrados, como mostra a imagem a seguir:
- O ativo externo registrado (UNIT) que será usado nas seções a seguir
- Outros ativos externos disponíveis ainda não registrados
A Interface Solidity ERC-20¶
A interface ERC20.sol nas redes Tanssi EVM segue o EIP-20 Token Standard, que é a interface API padrão para tokens dentro de contratos inteligentes. O padrão define as funções e eventos necessários que um contrato de token deve implementar para ser interoperável com diferentes aplicações.
ERC20.sol
/ SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.8.3;
/// @dev The IERC20 contract's address.
address constant IERC20_ADDRESS = 0x0000000000000000000000000000000000000800;
/// @dev The IERC20 contract's instance.
IERC20 constant IERC20_CONTRACT = IERC20(IERC20_ADDRESS);
/// @title ERC20 interface
/// @dev see https://github.com/ethereum/EIPs/issues/20
/// @dev copied from https://github.com/OpenZeppelin/openzeppelin-contracts
/// @custom:address 0x0000000000000000000000000000000000000800
interface IERC20 {
/// @dev Returns the name of the token.
/// @custom:selector 06fdde03
function name() external view returns (string memory);
/// @dev Returns the symbol of the token.
/// @custom:selector 95d89b41
function symbol() external view returns (string memory);
/// @dev Returns the decimals places of the token.
/// @custom:selector 313ce567
function decimals() external view returns (uint8);
/// @dev Total number of tokens in existence
/// @custom:selector 18160ddd
function totalSupply() external view returns (uint256);
/// @dev Gets the balance of the specified address.
/// @custom:selector 70a08231
/// @param owner The address to query the balance of.
/// @return An uint256 representing the amount owned by the passed address.
function balanceOf(address owner) external view returns (uint256);
/// @dev Function to check the amount of tokens that an owner allowed to a spender.
/// @custom:selector dd62ed3e
/// @param owner address The address which owns the funds.
/// @param spender address The address which will spend the funds.
/// @return A uint256 specifying the amount of tokens still available for the spender.
function allowance(address owner, address spender)
external
view
returns (uint256);
/// @dev Transfer token for a specified address
/// @custom:selector a9059cbb
/// @param to The address to transfer to.
/// @param value The amount to be transferred.
/// @return true if the transfer was succesful, revert otherwise.
function transfer(address to, uint256 value) external returns (bool);
/// @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
/// Beware that changing an allowance with this method brings the risk that someone may use both the old
/// and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
/// race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
/// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
/// @custom:selector 095ea7b3
/// @param spender The address which will spend the funds.
/// @param value The amount of tokens to be spent.
/// @return true, this cannot fail
function approve(address spender, uint256 value) external returns (bool);
/// @dev Transfer tokens from one address to another
/// @custom:selector 23b872dd
/// @param from address The address which you want to send tokens from
/// @param to address The address which you want to transfer to
/// @param value uint256 the amount of tokens to be transferred
/// @return true if the transfer was succesful, revert otherwise.
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
/// @dev Event emited when a transfer has been performed.
/// @custom:selector ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
/// @param from address The address sending the tokens
/// @param to address The address receiving the tokens.
/// @param value uint256 The amount of tokens transfered.
event Transfer(address indexed from, address indexed to, uint256 value);
/// @dev Event emited when an approval has been registered.
/// @custom:selector 8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925
/// @param owner address Owner of the tokens.
/// @param spender address Allowed spender.
/// @param value uint256 Amount of tokens approved.
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
/// @title Native currency wrapper interface.
/// @dev Allow compatibility with dApps expecting this precompile to be
/// a WETH-like contract.
interface WrappedNativeCurrency {
/// @dev Provide compatibility for contracts that expect wETH design.
/// Returns funds to sender as this precompile tokens and the native tokens are the same.
/// @custom:selector d0e30db0
function deposit() external payable;
/// @dev Provide compatibility for contracts that expect wETH design.
/// Does nothing.
/// @custom:selector 2e1a7d4d
/// @param value uint256 The amount to withdraw/unwrap.
function withdraw(uint256 value) external;
/// @dev Event emited when deposit() has been called.
/// @custom:selector e1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c
/// @param owner address Owner of the tokens
/// @param value uint256 The amount of tokens "wrapped".
event Deposit(address indexed owner, uint256 value);
/// @dev Event emited when withdraw(uint256) has been called.
/// @custom:selector 7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65
/// @param owner address Owner of the tokens
/// @param value uint256 The amount of tokens "unwrapped".
event Withdrawal(address indexed owner, uint256 value);
}
Note
A pré-compilação de ativos externos ERC-20 não inclui funções deposit e withdraw e eventos subsequentes esperados de um contrato de token embrulhado, como WETH.
Adicionar Token à uma Carteira EVM¶
Se você quiser interagir com os ativos externos registrados da sua rede como faria com um ERC-20, pode adicioná-los à sua carteira usando o prefixo de endereço de pré-compilação e o ID do ativo. Esta seção irá guiá-lo através da adição de um ativo externo ao MetaMask.
Para começar, abra o MetaMask e certifique-se de que você está conectado à sua rede e:
-
Vá para a aba Tokens
-
Clique em Importar tokens
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0001
- Insira o endereço de pré-compilação para o endereço do contrato do token. Ao inserir o endereço, os campos Símbolo do token e Decimais do token devem ser preenchidos automaticamente. Se não preencherem, você pode inserir
UNITpara o símbolo e12para as casas decimais - Clique em Próximo
MetaMask solicitará que você confirme a importação. Você pode verificar os detalhes do token e clicar em Importar tokens para importar tokens UNIT para sua carteira.
E é isso! Você adicionou com sucesso o ativo externo do token UNIT como um token ERC-20 personalizado na rede demo Tanssi EVM.
Interagir com a Interface Solidity via Remix¶
Configuração do Remix¶
Você pode interagir com a pré-compilação de ativos externos ERC-20 usando Remix. Para adicionar a pré-compilação ao Remix, você precisará:
- Obter uma cópia de
ERC20.sol - Cole o conteúdo do arquivo em um arquivo Remix chamado
IERC20.sol
Compilar o Contrato¶
Em seguida, você precisará compilar a interface no Remix:
- Clique na aba Compilar, a segunda de cima
- Compile a interface clicando em Compilar IERC20.sol
Quando a compilação for concluída, você verá uma marca de seleção verde ao lado da aba Compilar.
Acessar o Contrato¶
Em vez de implantar o contrato inteligente, você acessará a interface através do endereço da pré-compilação de ativos externos:
- Clique na aba Deploy and Run diretamente abaixo da aba Compilar no Remix. Observe que os contratos pré-compilados já estão acessíveis em seus respectivos endereços. Portanto, não há nenhuma etapa de implantação
- Certifique-se de que Injected Web3 esteja selecionado no menu suspenso ENVIRONMENT. Depois de selecionar Injected Web3, você pode ser solicitado pelo MetaMask para conectar sua conta ao Remix, caso ela ainda não esteja conectada
- Certifique-se de que a conta correta seja exibida em ACCOUNT
- Certifique-se de que IERC20 - IERC20.sol esteja selecionado no menu suspenso CONTRACT. Dado que é um contrato pré-compilado, não há nenhuma etapa de implantação. Em vez disso, você fornecerá o endereço da pré-compilação no campo At Address
- Forneça o endereço da pré-compilação ERC-20 (que é
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0001neste exemplo) e clique em At Address - A pré-compilação IERC20 aparecerá na lista de Deployed Contracts

Obter Informações Básicas do Token¶
A interface ERC-20 permite obter rapidamente informações sobre o token, incluindo a oferta total do token, nome, símbolo e casas decimais. Você pode recuperar essas informações seguindo estas etapas:
- Expanda o contrato IERC20 em Deployed Contracts
- Clique em decimals para obter as casas decimais do token do protocolo nativo da sua rede
- Clique em name para obter o nome do token
- Clique em symbol para obter o símbolo do token
- Clique em totalSupply para obter a oferta total de tokens nativos em sua rede
Os resultados de cada chamada de função são exibidos sob as respectivas funções.
Obter Saldo da Conta¶
Você pode verificar o saldo de qualquer endereço em sua rede chamando a função balanceOf e passando um endereço:
- Expanda a função balanceOf
- Insira um endereço para o qual você gostaria de verificar o saldo para o owner
- Clique em call
Seu saldo será exibido na função balanceOf.
Enviar Transferência¶
Para enviar tokens da sua conta diretamente para outra conta, você pode chamar a função transfer seguindo estas etapas:
- Expanda a função transfer
- Insira o endereço para enviar tokens UNIT
- Insira a quantidade de tokens UNIT para enviar. Para este exemplo, você pode enviar 1 token UNIT (
1000000000000) - Clique em transact
- O MetaMask aparecerá e você será solicitado a revisar os detalhes da transação. Clique em Confirmar para enviar a transação
Assim que a transação for concluída, você poderá verificar seu saldo usando a função balanceOf ou olhando para o MetaMask. Você notará que seu saldo diminuiu em 1 token UNIT. Você também pode usar a função balanceOf para garantir que o saldo dos destinatários tenha aumentado em 1 token UNIT, conforme o esperado.
E é isso! Você interagiu com sucesso com a pré-compilação de ativos externos ERC-20 usando MetaMask e Remix!
| Criada: 27 de novembro de 2025







