Esse é o quarto post da série Meu primeiro smart contract, que tem a intenção de ensinar ao longo de sete semanas alguns conceitos do solidity até construirmos um token baseado no ERC-20 com alguns testes unitários.
Nesse post vamos entender o que são tokens ERC-20 e criar o nosso próprio token ERC-20.
Ferramentas
Vamos continuar usando Remix IDE para criação dos nossos contratos.dd
O que são tokens ERC-20?
É uma estrutura padrão para desenvolvimento de tokens, usada na rede Ethereum para facilitar a criação de novas criptomoedas.
Ele é um dos padrões mais utilizados no mundo dos cripto ativos e hoje existem diversos tokens criados a partir dele.
O ERC-20 possuem 6 funções obrigatórias, algumas opcionais e 2 eventos obrigatórios.
Caso queira saber mais sobre o ERC-20, clique aqui
Nesse post vamos implementar algumas dessas funções e eventos.
Como criar um token ERC-20?
Igual outras linguagens de programação o solidity possui interface
, que é um conjunto de rotinas e padrões estabelecidos pelo software para a utilização das suas funcionalidades por aplicativos que não pretendem usar suas funções, mas apenas usá-la como base para criar suas funções.
Existem algumas formas de implementar uma interface no solidity, mas nesse post vamos criar nossa interface dentro do nosso arquivo.
Caso queira saber mais sobre o interfaces no solidity, clique aqui
Criando um novo arquivo
Vamos criar um novo arquivo dentro da pasta contracts
chamado 03-token.sol
.
Dentro do arquivo 03-token.sol
, vamos declarar as licenças do nosso contrato, a versão do contrato e dar um nome ao contrato como já fizemos, mas agora vamos declarar nossa interface ERC-20, iremos criar nossa interface com o nome IERC20
é uma boa prática iniciar nossas interfaces com I
para sabermos que é uma interface sempre que olharmos.
Dentro do IERC20
, vamos declarar as funções obrigatórias do contrato e os eventos.
interface IERC20 {
function totalSupply() external view returns(uint256);
function balanceOf(address account) external view returns(uint256);
function transfer(address to, uint256 quantity) external returns(bool);
event Transfer(address from, address to, uint256 value);
}
- Funções:
-
totalSupply
: Retorna o total de tokens existentes. Não precisamos passar nenhum parâmetro para essa função. -
balanceOf
: Retorna o saldo de um determinado endereço. Precisamos passar um parâmetroaddress
que é o endereço do usuário que desejamos saber o saldo. -
transfer
: Realiza a transferência de tokens para um determinado endereço. Precisamos passar dois parâmetros: o endereço do usuário que desejamos transferir e o valor da transferência.
-
- Eventos:
-
Transfer
: Emite um evento quando uma transferência é realizada. Precisamos passar três parâmetros: o endereço do usuário que transferiu, o endereço do usuário que recebeu e o valor da transferência.
-
Para utilizar uma interface em um contrato precisamos colocar is
na frente do nome do contrato e o nome da interface que queremos utilizar.
Nosso contrato inicialmente vai ficar assim com a interface IERC20
:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
interface IERC20 {
function totalSupply() external view returns(uint256);
function balanceOf(address account) external view returns(uint256);
function transfer(address to, uint256 quantity) external returns(bool);
event Transfer(address from, address to, uint256 value);
}
contract CryptoToken is IERC20{
}
Caso queira saber o que são funções external no solidity, clique aqui
Organização do código
Não existe uma forma certa de estruturar o código dos nossos contratos, mas para facilitar o entendimento vamos utilizar o seguinte padrão:
- Properties: Onde definimos nossas variáveis;
- Constructor: Onde definimos nosso construtor;
- Public Functions: Onde definimos nossas funções públicas;
Variáveis
Vamos começar dando o nome para nosso token, o símbolo dele e quantas casas decimais o token vai ter.
//Properties
string public constant name = "CryptoToken";
string public constant symbol = "CRY";
uint8 public constant decimals = 18;
Vamos definir nossas variáveis como constant
, porque variáveis constantes tem seus valores atribuídos em tempo de compilação depois que são compiladas não é possível alterá-los.
Fazemos isso para que não seja possível alterar o nome, símbolo e as casas decimais do nosso token.
Vamos criar uma variável para armazenar o total de tokens existentes e um mapping que vai armazenar a quantidade de tokens para cada endereço.
uint256 public totalSupply;
mapping (address => uint256) public addressToBalance;
Construtor
Vamos agora criar o nosso construtor, que vai definir que totalsupply
vai receber a quantidade total de tokens e que o endereço que fez o deploy vai receber todos esses tokens inicialmente.
//Constructor
constructor(uint256 total) {
totalsupply = total;
addressToBalance[msg.sender] = totalsupply;
}
Funções públicas
Total de tokens
Vamos criar uma função pública chamada totalSupply
que retorna o total de tokens existentes.
//Public Functions
function totalSupply() public override view returns(uint256) {
return totalsupply;
}
Precisamos declarar que essa função é override
porque ela substitui uma classe da interface IERC20
que foi declarada no início do código.
Caso queira saber o que são funções override no solidity, clique aqui
Saldo de um endereço
Para saber o saldo de um determinado endereço, vamos criar uma função pública chamada balanceOf
que retorna o saldo de um determinado endereço.
Ela espera um parâmetro que é o endereço do usuário que desejamos saber o saldo.
function balanceOf(address account) public override view returns(uint256) {
return addressToBalance[account];
}
Transferência de tokens
Para transferir tokens, vamos criar uma função pública chamada transfer
que recebe dois parâmetros: o endereço do usuário que desejamos transferir e a quantidade de tokens que desejamos transferir.
function transfer(address to, uint256 quantity) public returns(bool) {
require(addressToBalance[msg.sender] >= quantity, "Insufficient Balance to Transfer");
addressToBalance[msg.sender] = addressToBalance[msg.sender] - quantity;
addressToBalance[to] = addressToBalance[to] + quantity;
emit Transfer(msg.sender, to, quantity);
return true;
}
Como ficou nosso código
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
interface IERC20 {
function totalSupply() external view returns(uint256);
function balanceOf(address account) external view returns(uint256);
function transfer(address to, uint256 quantity) external returns(bool);
event Transfer(address from, address to, uint256 value);
}
contract CryptoToken is IERC20 {
//Properties
string public constant name = "CryptoToken";
string public constant symbol = "CRY";
uint8 public constant decimals = 7; //Padrão do Ether é 18
uint256 private totalsupply;
mapping(address => uint256) private addressToBalance;
//Constructor
constructor(uint256 total) {
totalsupply = total;
addressToBalance[msg.sender] = totalsupply;
}
//Public Functions
function totalSupply() public override view returns(uint256) {
return totalsupply;
}
function balanceOf(address account) public override view returns(uint256) {
return addressToBalance[account];
}
function transfer(address to, uint256 quantity) public override returns(bool) {
require(addressToBalance[msg.sender] >= quantity, "Insufficient Balance to Transfer");
addressToBalance[msg.sender] = addressToBalance[msg.sender] - quantity;
addressToBalance[to] = addressToBalance[to] + quantity;
emit Transfer(msg.sender, to, quantity);
return true;
}
}
Mão na massa
Agora vamos compilar e realizar o deploy do nosso contrato 03-token.sol
.
No menu lateral esquerdo clique em "Deploy & run transactions".
Informe a quantidade inicial de tokens e clique no botão "Deploy".
Podemos verificar as casas decimais do nosso token, o nome do token, o símbolo e a quantidade total de tokens.
Copie o endereço da carteira que foi feito o deploy e clique em "balanceOf" para vermos a quantidade de tokens que esse endereço tem.
Copie o endereço dessa carteira e clique em "balanceOf" para vermos a quantidade de tokens que esse endereço tem.
Volte para o endereço que fez o deploy do contrato, e informe o endereço da carteira que copiamos, a quantidade de tokens que queremos enviar e clique na função "transact".
Verifique a quantidade de tokens novamente do endereço que acabamos de fazer a transferência.
Conclusão
Esse foi o quarto post da série de posts "Meu primeiro smart contract".
Se você realizou todas as etapas acima, agora você tem um contrato de um token ERC-20 que consegue definir o nome do token, o símbolo do token, as casas decimais do token, ver a quantidade total de tokens existentes, consultar o saldo de tokens de um endereço, criar tokens e transferir tokens.
Se você gostou do conteúdo e te ajudou de alguma forma, deixe um like para ajudar o conteúdo a chegar para mais pessoas.
Referencias
ERC20 & EIP-20
O Que São Tokens ERC-20?
ERC-20: O que é e como funciona esse tipo de token?
Token Standards
Link do repositório
https://github.com/viniblack/meu-primeiro-smart-contract
Vamos trocar uma ideia ?
Fique a vontade para me chamar para trocarmos uma ideia, aqui embaixo está meu contato.
Top comments (1)
Parabéns, disseminando conteúdo de qualidade em português!!!