Como criar um token ERC20 em Solidity - Parte 2

Web3 e Blockchain

Como criar um token ERC20 em Solidity - Parte 2

Luiz Duarte
Escrito por Luiz Duarte em 23/07/2024
Junte-se a mais de 34 mil devs

Entre para minha lista e receba conteúdos exclusivos e com prioridade

Na primeira parte deste tutorial nós entendemos a diferença entre token e criptomoeda, a importância do padrão ERC-20 e um resumo do mesmo, o que deve ter te deixado plenamente preparado para, nesta segunda etapa, começar a colocar a mão na massa em código Solidity.

Para isso usaremos a IDE web gratuita Remix, que é o jeito mais prático de escrever e testar nossos códigos Solidity sem setups mirabolantes e outros desafios de ambientes mais profissionais. Em outras oportunidades podemos transportar nosso contrato de token ERC-20 para um projeto HardHat ou Truffle, sem grandes dificuldades.

Dito isso, abra o seu Remix, deixe a primeira parte deste tutorial em outra aba para se lembrar das características essenciais que precisamos ter no token e mãos à obra!

#1 – Criando o contrato e seus estados

Crie um novo arquivo no Remix e dê a ele o nome do seu token. O meu eu vou chamar de LuizCoin e o arquivo deve terminar com a extensão “.sol”.

Uma vez dentro do arquivo, vamos iniciar definindo a licença dos fontes (eu vou usar MIT) e a versão do compilador de Solidity que vamos usar.

Também já deixei pronto a estrutura básica do contrato apenas com seu escopo. É dentro das chaves do contrato que colocaremos toda a programação restante deste tutorial para criação de nosso token. Vamos começar a programar nosso token definindo as propriedades ou estados mais básicos dele.

Coloquei todos como privados (e usando a convenção de começar com underscore) pois teremos funções somente de leitura para fornecer acesso aos mesmos, como manda o padrão ERC-20. De cima para baixo, temos:

  • O fornecimento total deste token na sua menor fração;
  • O nome do token;
  • A sigla do token;
  • O número de casas decimais da menor fração;

Aqui vale uma explicação mais detalhada sobre o _totalSupply e sua relação com o campo _decimals. Primeiramente, _decimals é fácil de entender: é o números de casas decimais aceitas para esta moeda e portanto a menor fração que podemos representar dela, como os centavos no caso do Real, os satoshis no caso do BTC e os weis no caso no ETH.

Já o _totalSupply é o fornecimento total, ou seja, o limite de tokens desta menor fração disponível no mercado. Assim, se eu quero que existam 10.000 tokens “inteiros”, mas que cada um possa ser dividido com 18 casas decimais, preciso elevar 10k à potência de 18, o que estou fazendo ali na primeira linha usando o operador ** (potência) do Solidity.

Resumindo: o _totalSupply no cenário do BTC representa o total de Satoshis, no cenário do Real representa o total de centavos e assim por diante.

Além destas informações, que são do próprio padrão, temos de ter alguma maneira de guardar a informação dos saldos das carteiras que possuem LuizCoin na blockchain. Isso porque como esta não é uma criptomoeda nativa ela não conta com o algoritmo de livro-razão da blockchain e logo não tem uma forma de calcular o saldo “automaticamente”, nós teremos que manter este registro por conta própria.

Para isso, proponho usarmos a estrutura mapping do Solidity, que permite criar uma lista de registros onde usaremos o endereço de carteira como chave apontando para o saldo daquela carteira, como abaixo.

Repare que usei o tipo de dado address aqui, que é excelente para armazenarmos endereços de carteiras ou contratos. Assim, sempre que quisermos alterar o saldo de uma carteira, basta procurarmos a mesma no mapping de _balances e fazer a alteração. Bem como sempre que quisermos consultar o saldo de uma carteira, basta procurarmos no mesmo mapping usando o endereço como chave. Prático e eficiente!

E para finalizarmos este primeiro bloco vamos criar o constructor do nosso contrato. O construtor executa apenas uma vez durante o deploy do mesmo e para que possamos colocar a nossa moeda em circulação eu vou fornecer toda a sua cunhagem ao dono do contrato, ou seja, quem fez o deploy dele.

Repare aqui que usei o estado global msg, que traz informações sobre a transação que disparou a função. Como a constructor é disparada no deploy, o msg então estará trazendo informações sobre a transação de deploy. Ele possui alguns estados e o que nos interessa aqui é o sender, que retorna o endereço da carteira que está fazendo a transação. Usamos este endereço para acessar no mapping o saldo daquela carteira e alteramos o valor dela para que seja igual ao _totalSupply, ou seja, ter em sua posse todo o fornecimento máximo de LuizCoins.

É importante ressaltar que no Solidity todos os objetos são inicializados com seus valores default, sempre. Ou seja, mesmo que não exista nada no mapping de _balances, se eu acessar alguma posição qualquer, ela virá com zero pois é um inteiro. Isso evita erros desnecessários mas pode levar a confusões, então é bom lembrar disso.

Curso Web3 para Iniciantes

 

#2 – Funções de leitura de informações

Agora vamos começar a implementar as primeiras funções do nosso contrato de token, sendo que vamos fazer logo de cara quatro delas que são muito simples, a name, a symbol,  a decimals e a totalSupply, como abaixo.

Aqui não tem muito o que explicar já que são funções muito simples que apenas retornam o campo privado que guarda o respectivo estado do contrato. Agora vamos para outra função, ainda simples mas que já possui um comportamento real e que também é exigida no padrão ERC-20: a balanceOf, para retornar o saldo.

A função balanceOf espera um endereço por parâmetro e usa deste endereço para procurar no mapping de balances pelo saldo daquela carteira, retornando o mesmo. Como o Solidity gera valores default para todas variáveis, caso o endereço não exista ele retornará 0 como saldo, automaticamente. Importante reforçar que balanceOf é exatamente o nome de função, com a mesma assinatura (parâmetros + retornos) definidos no padrão ERC-20, nada foi escolhido por acaso e a única variação que você pode fazer é no conteúdo da função, na lógica para trazer o saldo.

Agora a próxima função que temos de fazer é a de transferência de fundos de uma carteira para outra, sendo que aqui sempre quem está chamando a função é quem está cedendo os seus tokens, o ‘from’.

Aqui temos muitas coisas novas a explorar, então vamos com calma.

Primeiro, vale relembrar que nome de função, parâmetros, etc é tudo padrão do ERC-20, apenas o conteúdo é autoral meu.

Segundo, que não devemos permitir a transferência de fundos inexistentes, certo? Então usaremos logo na primeira linha da função um require que é uma função que testa alguma condição nossa, impedindo a execução da função se ela não for atendida. A condição neste caso é que o saldo do emissor da transferência seja igual ou superior ao valor que irá ser transferido (value). Caso não seja, uma mensagem de erro é definida ao lado e a operação se encerra por aí mesmo.

Caso tenha fundos suficientes os saldos de ambas carteiras (from e to) são atualizados de acordo com o valor da transferência, incrementando a carteira to (destinatária) e decrementando a carteira from (originária, estamos usando msg.sender aqui, que já expliquei antes). Essa ordem que deixei no código é um mindset importante de segurança.

Por fim, a especificação define que devemos emitir um evento de transferência toda vez que alguma ocorrer. O evento Transfer que estou emitindo aqui deve ser definido também no smart contract, como exemplificado abaixo.

Os eventos são um poderoso recurso do Solidity para que outras aplicações e contratos que tenham interesse no seu, sejam avisados quando coisas importantes acontecerem. Neste caso, ao emitir o evento transfer ao final da função de transferência eu estou avisando quem quer que esteja esperando por esse acontecimento de que o evento aconteceu.

Atenção especial aqui à palavra reservada indexed nos parâmetros from e to do evento. Isso permite que mais tarde esses valores sejam usados como índices em pesquisas na blockchain.

#3 – Primeiro Teste

É importante realizarmos alguns testes parciais ao longo do desenvolvimento para descobrirmos o quanto antes quaisquer problemas que tenhamos e para isso o Remix nos ajuda bastante. Salve o seu contrato e vá na aba de deploy do Remix para fazermos nosso primeiro deploy na rede de testes Remix VM London, como abaixo.

Após configurar o deploy selecionando o ambiente e o contrato certos, clique em deploy e se tudo estiver compilando você vai poder testar o seu contrato em uma área que vai se abrir logo abaixo com um botão para cada estado ou função.

Experimente copiar o endereço da conta que fez deploy, disponível logo abaixo do environment, e usar ele na função de balanceOf para ver se o total supply do token foi corretamente transferido para ele. Depois, teste a transferência de fundos enviando tokens para outra carteira qualquer (pode ser uma MetaMask sua), lembrando que todas transações por padrão estão sendo feitas usando a conta do owner do contrato.

Após realizar estes primeiros testes você terá a certeza se programou corretamente o seu token ou não. Como esta parte está ficando grande demais vamos fazer mais uma pausa aqui e na próxima etapa vamos fazer a implementação da transferência delegada e o deploy final na blockchain.

Você confere a terceira parte neste link!

TAGS:

Olá, tudo bem?

O que você achou deste conteúdo? Conte nos comentários.

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

2 Replies to “Como criar um token ERC20 em Solidity – Parte 2”

Getulio Silva

Gostei muito preciso de conhecer melhor quero criar minha moeda.

Voce pode me ajuda?
meu conto 94991173704

Luiz Duarte

Se você já sabe programar, só seguir o tutorial. Se não sabe, comece por essa playlist: https://www.youtube.com/watch?v=c9mDHLYAIu8&list=PLsGmTzb4NxK3r0_sMLyHKaYX97tPN2QPm