Pular para o conteúdo principal
Change page

Padrão de token ERC-20

Última atualização da página: 26 de fevereiro de 2026

Introdução

O que é um token?

Um token podem representar praticamente qualquer coisa em Ethereum:

  • pontos de reputação em uma plataforma online
  • habilidades de um personagem em um jogo
  • ativos financeiros, como a ação em uma empresa
  • uma moeda fiduciária, como USD
  • 28,3 gr de ouro
  • e mais...

Uma característica tão poderosa do Ethereum deve ser tratada por um padrão robusto, certo? É aí que o ERC-20 entra! Este padrão permite que desenvolvedores criem aplicativos de token que são interoperáveis com outros produtos e serviços. O padrão ERC-20 também é usado para fornecer funcionalidade adicional ao .

O que é ERC-20?

O ERC-20 introduz um padrão para os tokens fungíveis, ou seja, eles têm uma propriedade que faz com que cada token tenha exatamente o mesmo de outro token (em termos de tipo e valor). Por exemplo, um token ERC-20 age como o ETH, significando que 1 token é e será sempre igual a todos os outros tokens.

Pré-requisitos

Body

O ERC-20 (Ethereum Request for Comments 20), proposto por Fabian Vogelsteller em novembro de 2015, é um padrão de token que implementa uma API para tokens em contratos inteligentes.

Exemplo de funcionalidades que o ERC-20 fornece:

  • transferir tokens de uma conta a outra
  • obter o saldo atual de tokens de uma conta
  • obter a oferta total do token disponível na rede
  • aprovar se uma quantidade de token de uma conta pode ser gasta por uma conta de terceiros

Se um contrato inteligente implementa os métodos e eventos a seguir, ele pode ser chamado de Contrato de token ERC-20 e, uma vez implantado, é responsável por fazer um acompanhamento dos tokens criados no Ethereum.

De EIP-20 (opens in a new tab):

Métodos

1function name() public view returns (string)
2function symbol() public view returns (string)
3function decimals() public view returns (uint8)
4function totalSupply() public view returns (uint256)
5function balanceOf(address _owner) public view returns (uint256 balance)
6function transfer(address _to, uint256 _value) public returns (bool success)
7function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
8function approve(address _spender, uint256 _value) public returns (bool success)
9function allowance(address _owner, address _spender) public view returns (uint256 remaining)
Exibir tudo

Eventos

1event Transfer(address indexed _from, address indexed _to, uint256 _value)
2event Approval(address indexed _owner, address indexed _spender, uint256 _value)

Exemplos

Vejamos por que um padrão é importante e como ele simplifica o controle de qualquer contrato de token ERC-20 no Ethereum. Só precisamos da Interface Binária de Aplicativos (ABI, pela sigla em inglês) do contrato para criar uma interface com qualquer token ERC-20. Como você pode ver abaixo, usaremos uma ABI simplificada, para torná-la um exemplo de fácil compreensão.

Exemplo de Web3.py

Primeiro, certifique-se de que você instalou a biblioteca Python Web3.py (opens in a new tab):

1pip install web3
1from web3 import Web3
2
3
4w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com"))
5
6dai_token_addr = "0x6B175474E89094C44Da98b954EedeAC495271d0F" # DAI
7weth_token_addr = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" # Ether encapsulado (WETH)
8
9acc_address = "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11" # Uniswap V2: DAI 2
10
11# Esta é uma Interface Binária de Aplicação (ABI) de Contrato simplificada de um Contrato de Token ERC-20.
12# Ela irá expor apenas os métodos: balanceOf(address), decimals(), symbol() e totalSupply()
13simplified_abi = [
14 {
15 'inputs': [{'internalType': 'address', 'name': 'account', 'type': 'address'}],
16 'name': 'balanceOf',
17 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],
18 'stateMutability': 'view', 'type': 'function', 'constant': True
19 },
20 {
21 'inputs': [],
22 'name': 'decimals',
23 'outputs': [{'internalType': 'uint8', 'name': '', 'type': 'uint8'}],
24 'stateMutability': 'view', 'type': 'function', 'constant': True
25 },
26 {
27 'inputs': [],
28 'name': 'symbol',
29 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}],
30 'stateMutability': 'view', 'type': 'function', 'constant': True
31 },
32 {
33 'inputs': [],
34 'name': 'totalSupply',
35 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],
36 'stateMutability': 'view', 'type': 'function', 'constant': True
37 }
38]
39
40dai_contract = w3.eth.contract(address=w3.to_checksum_address(dai_token_addr), abi=simplified_abi)
41symbol = dai_contract.functions.symbol().call()
42decimals = dai_contract.functions.decimals().call()
43totalSupply = dai_contract.functions.totalSupply().call() / 10**decimals
44addr_balance = dai_contract.functions.balanceOf(acc_address).call() / 10**decimals
45
46# DAI
47print("===== %s =====" % symbol)
48print("Fornecimento Total:", totalSupply)
49print("Saldo do Endereço:", addr_balance)
50
51weth_contract = w3.eth.contract(address=w3.to_checksum_address(weth_token_addr), abi=simplified_abi)
52symbol = weth_contract.functions.symbol().call()
53decimals = weth_contract.functions.decimals().call()
54totalSupply = weth_contract.functions.totalSupply().call() / 10**decimals
55addr_balance = weth_contract.functions.balanceOf(acc_address).call() / 10**decimals
56
57# WETH
58print("===== %s =====" % symbol)
59print("Fornecimento Total:", totalSupply)
60print("Saldo do Endereço:", addr_balance)
Exibir tudo

Problemas conhecidos

Problema de recebimento de token ERC-20

Em 20/06/2024, pelo menos US$ 83.656.418 em tokens ERC-20 foram perdidos devido a esse problema. Observe que uma implementação ERC-20 pura está propensa a esse problema, a menos que você implemente um conjunto de restrições adicionais além do padrão, conforme listado abaixo.

Quando tokens ERC-20 são enviados para um contrato inteligente que não foi projetado para lidar com tokens ERC-20, esses tokens podem ser permanentemente perdidos. Isso acontece porque o contrato receptor não possui a funcionalidade para reconhecer ou responder aos tokens recebidos, e não há um mecanismo no padrão ERC-20 para notificar o contrato receptor sobre os tokens recebidos. As principais formas pelas quais esse problema se manifesta são:

  1. Mecanismo de transferência de tokens
  • Os tokens ERC-20 são transferidos usando as funções transfer ou transferFrom
    • Quando um usuário envia tokens para um endereço de contrato usando essas funções, os tokens são transferidos independentemente de o contrato receptor estar ou não projetado para manipulá-los
  1. Falta de notificação
    • O contrato receptor não recebe uma notificação ou retorno de chamada de que os tokens foram enviados a ele
    • Se o contrato de recebimento não tiver um mecanismo para lidar com tokens (por exemplo, uma função de fallback ou uma função dedicada para gerenciar a recepção de tokens), os tokens ficarão efetivamente presos no endereço do contrato
  2. Sem manuseio integrado
    • O padrão ERC-20 não inclui uma função obrigatória para receber contratos a serem implementados, levando a uma situação em que muitos contratos não conseguem gerenciar os tokens recebidos adequadamente

Possíveis Soluções

Embora não seja possível evitar completamente esse problema com o ERC-20, existem métodos que permitiriam reduzir significativamente a possibilidade de perda de tokens para o usuário final:

  • O problema mais comum é quando um usuário envia tokens para o próprio endereço do contrato do token (por exemplo, USDT depositado no endereço do contrato do token USDT). É recomendável restringir a função transfer(..) para reverter tais tentativas de transferência. Considere adicionar a verificação require(_to != address(this)); na implementação da função transfer(..).
  • A função transfer(..) em geral não foi projetada para depositar tokens em contratos. O padrão approve(..) & transferFrom(..) é usado, em vez disso, para depositar tokens ERC-20 em contratos. É possível restringir a função de transferência para não permitir o depósito de tokens em quaisquer contratos com ela, no entanto, isso pode quebrar a compatibilidade com contratos que assumem que os tokens podem ser depositados em contratos com a função trasnfer(..) (por exemplo, pools de liquidez Uniswap).
  • Sempre presuma que tokens ERC-20 podem acabar no seu contrato, mesmo que seu contrato nunca deva recebê-los. Não há como evitar ou rejeitar depósitos acidentais por parte dos destinatários. É recomendável implementar uma função que permita extrair tokens ERC-20 depositados acidentalmente.
  • Considere usar padrões de token alternativos.

Alguns padrões alternativos surgiram desse problema, como o ERC-223 ou o ERC-1363.

Leitura adicional

Outros padrões de tokens fungíveis

Este artigo foi útil?