Implementação de um token ERC-20
Desenvolva e implante seu próprio token compatível com ERC-20, incluindo funções de transferência, aprovação e autorização de uso.
Implementação de um token ERC-20 é uma aula grátis de Blockchain Smart Contracts with Solidity no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Blockchain Smart Contracts with Solidity, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Blockchain Smart Contracts with Solidity inclui 4 aulas no total.
Partes desta aula ainda não foram traduzidas e aparecem em inglês.
Build Your Own ERC-20 Token
Welcome! In this lesson, you'll learn to implement your very own ERC-20 compliant token. We'll cover the essential functions and variables that make up this widely used standard.
By the end, you'll have a working understanding of how these tokens operate at a fundamental level on the Ethereum blockchain.
Token Identity: Name, Symbol, Decimals
Every ERC-20 token needs basic identifying information: a name, a symbol, and decimals. These are often public state variables.
- name: The full name of your token (e.g., "MyCoddyToken").
- symbol: A short ticker symbol (e.g., "MCT").
- decimals: How many decimal places the token can be divided into (commonly 18, like Ether).
Let's start our contract with these properties:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18; // Common for ERC-20
}Total Supply & Initial Minting
The totalSupply variable keeps track of all existing tokens. We also need a way to store each user's balance, typically using a mapping.
The constructor is a special function that runs only once when the contract is deployed. We use it to set the initial totalSupply and assign all initial tokens to the deployer's address.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply; // Total tokens in existence
mapping(address => uint256) private _balances; // User balances
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply; // Mints to deployer
}
}Checking Balances: `balanceOf`
The balanceOf function allows anyone to query the token balance of a specific address. It's a view function, meaning it doesn't change the contract's state and costs no gas to call off-chain.
We retrieve the balance from our _balances mapping.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) private _balances;
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
}Direct Transfers: `transfer`
The transfer function enables a token holder to send tokens directly to another address. It's a core function of the ERC-20 standard.
Before transferring, we must ensure the sender has sufficient balance. After the transfer, we emit a Transfer event, which is vital for blockchain explorers and dApps to track token movements.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) private _balances;
// ERC-20 events
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply;
emit Transfer(address(0), msg.sender, initialSupply); // Minting event
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(_balances[msg.sender] >= amount, "Insufficient balance");
_balances[msg.sender] -= amount;
_balances[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
}Delegated Spending: `approve`
The approve function allows a token holder (the owner) to grant another address (the spender) permission to spend a certain amount of their tokens on their behalf.
This is crucial for interacting with decentralized applications (dApps) where you might want a smart contract to manage your tokens (e.g., for staking or trading). We track these approvals in an _allowances mapping.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances; // New: owner => (spender => amount)
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply;
emit Transfer(address(0), msg.sender, initialSupply);
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(_balances[msg.sender] >= amount, "Insufficient balance");
_balances[msg.sender] -= amount;
_balances[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint256 amount) public returns (bool) {
_allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
}Checking Allowance: `allowance`
The allowance function lets you check how many tokens a specific spender is currently permitted to transfer from an owner's balance.
This is a view function, similar to balanceOf, and helps external applications understand the spending limits set by users.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply;
emit Transfer(address(0), msg.sender, initialSupply);
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(_balances[msg.sender] >= amount, "Insufficient balance");
_balances[msg.sender] -= amount;
_balances[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint256 amount) public returns (bool) {
_allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
}Spending on Behalf: `transferFrom`
The transferFrom function is used by a spender (who has been approved) to move tokens from an owner's balance to a recipient.
It requires checks for both the sender's balance and the allowance granted. After a successful transfer, the allowance is reduced by the transferred amount.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply;
emit Transfer(address(0), msg.sender, initialSupply);
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(_balances[msg.sender] >= amount, "Insufficient balance");
_balances[msg.sender] -= amount;
_balances[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint256 amount) public returns (bool) {
_allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public returns (bool) {
require(_balances[sender] >= amount, "Insufficient balance from sender");
require(_allowances[sender][msg.sender] >= amount, "Insufficient allowance");
_allowances[sender][msg.sender] -= amount;
_balances[sender] -= amount;
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
}
}Full Minimal ERC-20 Implementation
Here's a complete, minimal ERC-20 token contract. While more advanced implementations (like OpenZeppelin's) include additional features and safety checks, this code covers all the core functions required by the standard.
You can deploy this contract to a testnet to create your own functional token!
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public name = "MyCoddyToken";
string public symbol = "MCT";
uint8 public decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
constructor(uint256 initialSupply) {
totalSupply = initialSupply;
_balances[msg.sender] = initialSupply;
emit Transfer(address(0), msg.sender, initialSupply);
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
require(_balances[msg.sender] >= amount, "Insufficient balance");
_balances[msg.sender] -= amount;
_balances[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint256 amount) public returns (bool) {
_allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public returns (bool) {
require(_balances[sender] >= amount, "Insufficient balance from sender");
require(_allowances[sender][msg.sender] >= amount, "Insufficient allowance");
_allowances[sender][msg.sender] -= amount;
_balances[sender] -= amount;
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
}
}ERC-20 Core Functions Check
You've learned about the essential functions for an ERC-20 token. Now, let's test your knowledge!
Recap: Your Own Token
Congratulations! You've now implemented the core logic for an ERC-20 token. You learned how to define its properties, manage total supply and individual balances, and enable both direct and delegated token transfers.
Understanding these fundamental building blocks is key to working with any token on the Ethereum blockchain. Next, you might explore how to integrate with existing ERC-20 libraries or add more advanced features!
Perguntas Frequentes
A aula “Implementação de um token ERC-20” é grátis?
Sim — o texto completo de “Implementação de um token ERC-20” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Blockchain Smart Contracts with Solidity, atualize para CoddyKit PRO. O curso de Blockchain Smart Contracts with Solidity inclui 4 aulas no total.
O que vou aprender em “Implementação de um token ERC-20”?
Desenvolva e implante seu próprio token compatível com ERC-20, incluindo funções de transferência, aprovação e autorização de uso. Você pratica Blockchain Smart Contracts with Solidity com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Blockchain Smart Contracts with Solidity?
Nenhuma experiência prévia é necessária. Blockchain Smart Contracts with Solidity no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Implementação de um token ERC-20”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Blockchain Smart Contracts with Solidity?
Sim. Cada aula de Blockchain Smart Contracts with Solidity inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Padrão de tokens fungíveis ERC-20
- Implementação de um token ERC-20
- Tokens não fungíveis ERC-721 (NFTs)
- Padrão de Multi-Tokens ERC-1155