Pular para o conteúdo principal

Entenda o contrato inteligente de token ERC-20

smart contracts
tokens
Solidity
erc-20
Iniciante
jdourlens
5 de abril de 2020
5 minutos de leitura

Um dos padrões de contratos inteligentes mais significativos no Ethereum é conhecido como ERC-20, que surgiu como o padrão técnico usado para todos os contratos inteligentes na blockchain do Ethereum para implementações de tokens fungíveis.

O ERC-20 define uma lista comum de regras às quais todos os tokens Ethereum fungíveis devem aderir. Consequentemente, este padrão de token capacita os desenvolvedores de todos os tipos a prever com precisão como os novos tokens funcionarão dentro do sistema Ethereum maior. Isso simplifica e facilita as tarefas dos desenvolvedores, pois eles podem prosseguir com seu trabalho, sabendo que cada novo projeto não precisará ser refeito toda vez que um novo token for lançado, desde que o token siga as regras.

Veja aqui, apresentadas como uma interface, as funções que um ERC-20 deve implementar. Se você não tem certeza do que é uma interface: confira nosso artigo sobre programação OOP em Solidity (opens in a new tab).

1pragma solidity ^0.6.0;
2
3interface IERC20 {
4
5 function totalSupply() external view returns (uint256);
6 function balanceOf(address account) external view returns (uint256);
7 function allowance(address owner, address spender) external view returns (uint256);
8
9 function transfer(address recipient, uint256 amount) external returns (bool);
10 function approve(address spender, uint256 amount) external returns (bool);
11 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
12
13
14 event Transfer(address indexed from, address indexed to, uint256 value);
15 event Approval(address indexed owner, address indexed spender, uint256 value);
16}
Exibir tudo

Aqui está uma explicação linha por linha da finalidade de cada função. Depois disso, apresentaremos uma implementação simples de um token ERC-20.

Getters

1function totalSupply() external view returns (uint256);

Retorna a quantidade de tokens em existência. Esta função é um getter e não modifica o estado do contrato. Lembre-se de que não existem floats em Solidity. Portanto, a maioria dos tokens adota 18 casas decimais e retornará o fornecimento total e outros resultados da seguinte forma: 1000000000000000000 para 1 token. Nem todo token tem 18 casas decimais e isso é algo a que você realmente precisa estar atento ao lidar com tokens.

1function balanceOf(address account) external view returns (uint256);

Retorna a quantidade de tokens pertencentes a um endereço (account). Esta função é um getter e não modifica o estado do contrato.

1function allowance(address owner, address spender) external view returns (uint256);

O padrão ERC-20 permite que um endereço dê uma permissão a outro endereço para poder retirar tokens dele. Este getter retorna o número restante de tokens que o spender terá permissão para gastar em nome do owner. Esta função é um getter, não modifica o estado do contrato e deve retornar 0 por padrão.

Funções

1function transfer(address recipient, uint256 amount) external returns (bool);

Move a quantidade (amount) de tokens do endereço do chamador da função (msg.sender) para o endereço do destinatário. Esta função emite o evento Transfer definido mais adiante. Retorna verdadeiro se a transferência foi possível.

1function approve(address spender, uint256 amount) external returns (bool);

Define o valor da allowance que o spender tem permissão para transferir do saldo do chamador da função (msg.sender). Esta função emite o evento Approval. A função retorna se a permissão foi definida com sucesso.

1function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

Move a quantidade (amount) de tokens de sender para recipient usando o mecanismo de permissão (allowance). A amount (quantia) é então deduzida da permissão (allowance) do chamador. Esta função emite o evento Transfer.

Eventos

1event Transfer(address indexed from, address indexed to, uint256 value);

Este evento é emitido quando a quantidade de tokens (value) é enviada do endereço from para o endereço to.

No caso de cunhagem de novos tokens, a transferência é geralmente from o endereço 0x00..0000, enquanto no caso de queima de tokens a transferência é to 0x00..0000.

1event Approval(address indexed owner, address indexed spender, uint256 value);

Este evento é emitido quando a quantidade de tokens (value) é aprovada pelo owner para ser usada pelo spender.

Uma implementação básica de tokens ERC-20

Aqui está o código mais simples para servir de base para o seu token ERC-20:

1pragma solidity ^0.8.0;
2
3interface IERC20 {
4
5 function totalSupply() external view returns (uint256);
6 function balanceOf(address account) external view returns (uint256);
7 function allowance(address owner, address spender) external view returns (uint256);
8
9 function transfer(address recipient, uint256 amount) external returns (bool);
10 function approve(address spender, uint256 amount) external returns (bool);
11 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
12
13
14 event Transfer(address indexed from, address indexed to, uint256 value);
15 event Approval(address indexed owner, address indexed spender, uint256 value);
16}
17
18
19contract ERC20Basic is IERC20 {
20
21 string public constant name = "ERC20Basic";
22 string public constant symbol = "ERC";
23 uint8 public constant decimals = 18;
24
25
26 mapping(address => uint256) balances;
27
28 mapping(address => mapping (address => uint256)) allowed;
29
30 uint256 totalSupply_ = 10 ether;
31
32
33 constructor() {
34 balances[msg.sender] = totalSupply_;
35 }
36
37 function totalSupply() public override view returns (uint256) {
38 return totalSupply_;
39 }
40
41 function balanceOf(address tokenOwner) public override view returns (uint256) {
42 return balances[tokenOwner];
43 }
44
45 function transfer(address receiver, uint256 numTokens) public override returns (bool) {
46 require(numTokens <= balances[msg.sender]);
47 balances[msg.sender] = balances[msg.sender]-numTokens;
48 balances[receiver] = balances[receiver]+numTokens;
49 emit Transfer(msg.sender, receiver, numTokens);
50 return true;
51 }
52
53 function approve(address delegate, uint256 numTokens) public override returns (bool) {
54 allowed[msg.sender][delegate] = numTokens;
55 emit Approval(msg.sender, delegate, numTokens);
56 return true;
57 }
58
59 function allowance(address owner, address delegate) public override view returns (uint) {
60 return allowed[owner][delegate];
61 }
62
63 function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {
64 require(numTokens <= balances[owner]);
65 require(numTokens <= allowed[owner][msg.sender]);
66
67 balances[owner] = balances[owner]-numTokens;
68 allowed[owner][msg.sender] = allowed[owner][msg.sender]-numTokens;
69 balances[buyer] = balances[buyer]+numTokens;
70 emit Transfer(owner, buyer, numTokens);
71 return true;
72 }
73}
Exibir tudo

Outra excelente implementação do padrão de token ERC-20 é a implementação ERC-20 da OpenZeppelin (opens in a new tab).

Última atualização da página: 21 de agosto de 2025

Este tutorial foi útil?