Pré-compilado ERC-20 do Token Nativo¶
Introdução¶
O contrato precompilado ERC-20 do token nativo em redes EVM com Tanssi permite que os desenvolvedores interajam com o token nativo do protocolo por meio de uma interface ERC-20. Embora o token nativo da sua rede não seja um ERC-20, agora você pode interagir com ele como se fosse um ERC-20 puro.
Um dos principais benefícios dessa precompilada é eliminar a necessidade de ter uma representação embrulhada do token do protocolo como um smart contract ERC-20, como o WETH no Ethereum. Além disso, ela minimiza a necessidade de múltiplas representações embrulhadas do mesmo token do protocolo. Consequentemente, dApps que precisam interagir com o token do protocolo via interface ERC-20 podem fazê-lo sem precisar de um contrato separado.
Por baixo dos panos, a precompilada ERC-20 executa ações específicas do Substrate relacionadas ao módulo de saldos do Substrate, escrito em Rust. O módulo de saldos fornece funcionalidades para lidar com diversos tipos de saldos.
Este guia mostrará como interagir com os tokens UNIT, os tokens nativos do protocolo para redes de teste rápido no Dancelight, por meio da precompilada ERC-20. Você pode seguir e adaptar este guia para interagir com a sua própria rede.
A precompilada está localizada no endereço:
0x0000000000000000000000000000000000000800
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.
Interface Solidity do ERC-20¶
A interface ERC20.sol nas redes EVM do Tanssi segue o Padrão de Token EIP-20, que define as funções e eventos exigidos para um token interoperar 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);
}
Nota
A precompilada ERC-20 não inclui as funções deposit e withdraw nem os eventos associados esperados de um token embrulhado, como o WETH.
Interagir com a interface Solidity¶
Verificando Pré-requisitos¶
Para acompanhar este tutorial, você precisará ter sua carteira configurada para funcionar com sua rede EVM com Tanssi e uma conta financiada com tokens nativos. Você pode adicionar sua rede EVM ao MetaMask com um clique no Tanssi dApp ou configurar o MetaMask para Tanssi com a rede EVM de demonstração.
Adicionar token a uma carteira EVM¶
Se quiser interagir com o token nativo da rede como um ERC-20, adicione um token personalizado à sua carteira compatível com EVM usando o endereço da precompilada. Esta seção mostra como adicionar um ativo externo ao MetaMask.
Para começar, abra o MetaMask, certifique-se de estar conectado à sua rede e:
- Acesse a aba Assets
- Clique em Import tokens
Agora, crie o token personalizado:
- Informe o endereço da precompilada —
0x0000000000000000000000000000000000000800. Ao inserir o endereço, os campos Token Symbol e Token Decimal devem ser preenchidos automaticamente. Caso não aconteça, useUNITcomo símbolo e18para casas decimais (o padrão das redes EVM do Tanssi, igual ao Ethereum) - Clique em Next
O MetaMask solicitará a confirmação da importação. Revise os detalhes e clique em Import Tokens para importar os tokens UNIT para sua carteira.
Pronto! Você adicionou o token UNIT como um ERC-20 personalizado na sua rede EVM do Tanssi.
Configuração do Remix¶
Você pode interagir com a precompilada ERC-20 usando o Remix. Para adicioná-la ao Remix, você precisará:
- Obter uma cópia do
ERC20.sol - Colar o conteúdo em um arquivo chamado
IERC20.solno Remix
Compilar o contrato¶
Em seguida, compile a interface no Remix:
- Clique na aba Compile (segunda de cima para baixo)
- Compile a interface clicando em Compile IERC20.sol
Quando a compilação terminar, aparecerá um check verde ao lado da aba Compile.
Acessar o contrato¶
Em vez de implantar a precompilada, você acessará a interface informando o endereço do contrato já disponibilizado:
- Clique na aba Deploy and Run logo abaixo de Compile no Remix. Lembre-se de que contratos precompilados já estão acessíveis em seus endereços, portanto não há etapa de implantação
- Certifique-se de que Injected Web3 está selecionado em ENVIRONMENT. Ao escolher Injected Web3, o MetaMask pode solicitar conexão com o Remix caso ainda não esteja
- Verifique se a conta correta aparece em ACCOUNT
- Garanta que IERC20 - IERC20.sol esteja selecionado em CONTRACT. Como é um contrato precompilado, não há implantação; você informará o endereço da precompilada em At Address
- Informe o endereço da precompilada ERC-20:
0x0000000000000000000000000000000000000800e clique em At Address
A precompilada IERC20 aparecerá na lista de Deployed Contracts.
Obter informações básicas do token¶
A interface ERC-20 permite obter rapidamente informações como oferta total, nome, símbolo e casas decimais. Para isso:
- Expanda o contrato IERC20 em Deployed Contracts
- Clique em decimals para obter as casas decimais do token nativo
- 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 na rede
Os resultados de cada chamada aparecem sob as respectivas funções.
Consultar saldo de uma conta¶
Para checar o saldo de qualquer endereço na rede usando balanceOf:
- Expanda a função balanceOf
- Informe o endereço a consultar em owner
- Clique em call
O saldo será exibido abaixo da função balanceOf.
Aprovar um gasto¶
Para aprovar uma autorização de gasto, forneça um endereço para o spender e o número de tokens permitidos. O spender pode ser uma EOA ou um contrato inteligente. Exemplo: autorizar 1 UNIT.
- Expanda approve
- Insira o endereço do spender (use a segunda conta criada)
- Informe o valor que o spender pode gastar em value. Exemplo: 1 UNIT em Wei (
1000000000000000000) - Clique em transact
- O MetaMask abrirá para você revisar e confirmar a transação
Após a confirmação, o saldo da sua conta permanece o mesmo porque apenas a permissão foi concedida; nenhum gasto foi feito. Na próxima seção, usaremos allowance para verificar a permissão.
Verificar a permissão do spender¶
Para checar se o spender recebeu a autorização:
- Expanda allowance
- Informe seu endereço em owner
- Informe o endereço do spender usado anteriormente
- Clique em call
O valor exibido deve equivaler a 1 UNIT (1000000000000000000).
Enviar transferência padrão¶
Para enviar tokens diretamente da sua conta a outra:
- Expanda transfer
- Insira o endereço de destino
- Informe a quantidade de UNIT a enviar (ex.: 1 UNIT =
1000000000000000000) - Clique em transact
- Confirme a transação no MetaMask
Após a conclusão, verifique seu saldo via balanceOf ou no MetaMask. O saldo deve ter diminuído em 1 UNIT, e o destinatário deve ter recebido 1 UNIT.
Enviar transferência a partir de uma conta específica¶
Até agora, você aprovou 1 UNIT para o spender e enviou 1 UNIT com transfer. A função transferFrom permite definir de qual endereço sairão os tokens. Para este exemplo, use a conta do spender para transferir o valor autorizado do owner para o spender.
Primeiro, mude para a conta do spender no MetaMask; o endereço selecionado em Remix será o do spender.
Em seguida, envie a transferência:
- Expanda transferFrom
- Informe seu endereço como owner no campo from
- Informe o destinatário (o spender) no campo to
- Informe a quantidade de UNIT (a autorização é de 1 UNIT, então use
1000000000000000000) - Clique em transact
Depois da transação, confira o saldo do owner e do spender com balanceOf. O saldo do spender terá aumentado em 1 UNIT e a permissão terá sido consumida. Para confirmar que não há mais permissão, chame allowance passando os endereços do owner e do spender; o resultado deve ser 0.
E é isso! Você interagiu com a precompilada ERC-20 usando MetaMask e Remix.
| Criada: 9 de dezembro de 2025












