Como criar uma nova criptomoeda usando Solidity e Truffle (JS)

Cripto

Como criar uma nova criptomoeda usando Solidity e Truffle (JS)

Luiz Duarte
Escrito por Luiz Duarte em 16/01/2023
Junte-se a mais de 34 mil devs

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

Recentemente ensinei como criar uma nova criptomoeda, ou melhor, um novo token, no padrão da rede Ethereum (ERC-20), o mais usado mundialmente. Naquele momento, usamos a ferramenta Remix e fizemos todo o processo até o deploy e a configuração do token na nossa carteira MetaMask. Recomendo fortemente que faça esse outro tutorial primeiro antes desse aqui, pois hoje vamos aprender novamente a criar novos tokens ERC-20, mas usando ferramentas mais profissionais como o Truffle e OpenZepellin.

Outro ponto importante é que este não deve ser o seu primeiro tutorial envolvendo a linguagem Solidity ou mesmo o toolkit Truffle. Se esse for o seu caso, recomendo começar por este outro aqui.

#1 – Criando o Projeto

O primeiro passo é você criar um novo projeto Truffle. Para isso, crie uma pasta na sua máquina, que eu vou chamar de token-erc20-truffle. Dentro dela, rode o comando do Truffle para criar um template de projeto.

Com o projeto criado, revise a pasta contracts e deixe somente um contrato nela, cujo nome do arquivo vai ser o nome da sua cripto, no meu caso: LuizCoin. Se você fez meu outro tutorial de token ERC-20, pode inclusive copiar e colar o código-fonte de lá para ganhar tempo, mas a abordagem que vou propor aqui é diferente e mais profissional pois vamos usar contratos da OpenZeppelin.

A OpenZeppelin é uma empresa conhecida mundialmente na área de cripto e blockchain por oferecer produtos e serviços na área de segurança de aplicações decentralizadas. Como alguns códigos Solidity são muito frequentes, como os códigos de padrões ERC, e é muito fácil de você deixar brechas em smart contracts para atacantes, eles resolvem os dois problemas fornecendo bibliotecas de contratos open-source já testados e auditados extensivamente para você usar, além de serviços de auditoria requisitados por grandes players do mercado.

Assim, vamos instalar a biblioteca de contratos deles em nosso projeto e você verá os ganhos que ela vai nos trazer logo mais.

Agora deixa na pasta migrations apenas uma, atualizando o código da mesma para fazer o deploy do seu contrato apenas.

E ajuste seu truffle-config.js para usar a versão mais recente do Solidity e também usar a rede de testes interna do Truffle, como abaixo.

E por fim, na pasta test, deixe somente um arquivo JS de testes, o que eu recomendo que tenha o mesmo nome do contrato com o sufixo “.test.js”, inicialmente com o conteúdo abaixo.

Agora temos o setup do nosso projeto de novo token pronto, é hora de programarmos ele!

Curso Web3 para Iniciantes

#2 – Contrato do Token

Agora vamos nos concentrar no arquivo LuizCoin.sol, que é a implementação do nosso token ERC20. Como vamos usar a biblioteca de contratos da OpenZeppelin, vamos começar importando a mesma, logo no topo do arquivo e dizendo que nosso contrato vai herdar todas as características do contrato ERC20.sol existente na biblioteca do OpenZeppelin. Fazemos isso com a keyword ‘is’ ao lado do nome do contrato novo e antes do nome do contrato-pai, como abaixo.

Com esta implementação agora nossa LuizCoin tem acesso a todas características e funções compartilhadas pelo contrato ERC20.sol, acelerando bastante o nosso desenvolvimento e reduzindo drasticamente a nossa chance de deixar brechas em nosso código pois ele será mais de customização do que de implementação.

Por exemplo, para definir o nome e symbol do nosso token, basta chamarmos o constructor da superclasse/classe-pai junto ao nosso constructor, como abaixo, passando os seus parâmetros.

Aqui estou dizendo que o constructor de LuizCoin, quando chamado, deve invocar o constructor de ERC20 passando no primeiro argumento o nome da moeda e no segundo o symbol dela.

Também já realizei a implementação do código personalizado do constructor de LuizCoin, que vai fazer o minting, ou seja, a cunhagem/criação das moedas e a sua imediata transferência para uma carteira à sua escolha. Essa função _mint é herdade de ERC20 também e espera o endereço da carteira de destino e a quantidade de tokens a serem cunhados.

No exemplo, estou dizendo que a carteira do criador do contrato (lembrando que o constructor é chamado no deploy do contrato, então msg.sender é quem criou o mesmo na blockchain neste momento) vai receber 1000 tokens, o que será 0 nosso supply inicial. Eu multiplico a quantidade por 10 elevado na potência 18 porque quero que meu token tenha 18 casas decimais, como a maioria dos tokens ERC20 aliás, mas você pode alterar como quiser.

Com isso você já tem um token ERC20 funcional e se fizer deploy dele vai funcionar normalmente, como manda a especificação e tenho a certeza que você achou que seria mais complicado, certo?

Dá pra complicar, mas a base é essa aí mesmo.

Antes de pensar em complicar, vamos testar para ver se funciona mesmo.

#3 – Testes do Contrato

É aqui onde você vai escrever a maior quantidade de código e é onde também se mostrará necessário você ter feito o outro tutorial de token ERC20 onde escrevemos todo o contrato do zero, pois ali construímos o conhecimento de como tudo funciona, permitindo que a gente consiga saber como testar um token também. Para alguns dos testes vamos precisar manipular big numbers ou números gigantes, então recomendo que você instale no seu projeto a mesma biblioteca que o Truffle usa internamente, a BN.js.

Agora abra o arquivo LuizCoin.test.js (ou equivalente) na pasta test e vamos escrever a estrutura básica para nossos testes, que consiste na função contract e um beforeEach, já que quero manter cada teste independente eu vou sugerir que o contrato seja inicializado individualmente antes de cada um. Além disso, já vou usar a biblioteca BN para inicializar uma constante DECIMALS corretamente (não esquecendo de carregá-la no topo do arquivo).

Essa constante DECIMALS será usada em alguns testes e embora ela não seja realmente um número gigante, vou inicializá-la dessa forma a fim de que facilite os testes e uso posterior.

Falando em testes, nosso primeiro teste irá verificar se o saldo total do token foi transferido para a carteira de quem fez o deploy do contrato (vulgo admin/owner).

Começamos o teste pegando o saldo do contrato e comparamos ele com o big number do total supply que é 1000 multiplicado por 10 na potência 18. Repare como uso as funções do objeto BN para multiplicar e depois para fazer a potenciação. Isso é necessário pois os operadores tradicionais do JS não suportam big numbers. No final das contas a asserção é simples, mas exige que a gente use a função eq para comparação entre os big numbers.

Eu não vou ficar citando, mas a cada teste codificado, o ideal é rodar a bateria toda com o comando ‘truffle test’ a ver se estão passando, ok?

O teste seguinte é mais simples, para verificar se o nome do token foi definido corretamente.

Nada de especial aqui, então vamos avançar para o próximo que é igualmente simples: verificar se o symbol foi definido corretamente.

E também outro bem simples que verifica se os decimals estão corretos.

E agora sim, finalmente entramos em um teste mais complicado: transfer. Aqui teremos dois cenários: um de sucesso e um de fracasso. No primeiro cenário, sucesso, vamos fazer uma transferência de 1 token para outra das carteiras disponíveis nos testes. No entanto, antes de fazermos esta transferência, sugiro pegar os saldos do from e do to a fim de podermos comparar se a transferência deu certo depois.

A chamada da função transfer é bem direta e simples e ela é nativamente feita a partir (from) da accounts[0] que é quem faz o deploy do mesmo. Como é uma transferência direta e de um valor pequeno (que cabe no saldo), ela será aceita normalmente e como resultado os saldos estarão ajustados após a mesma, o que podemos conferir pedindo novamente o saldo e comparando nos asserts com as funções da BN.js (já que é tudo big number não rola de comparar com os operadores do JS).

Agora vamos fazer o cenário de fracasso. Para isso, vou fazer o mesmo teste, mas tentando transferir mais do que a accounts[0] possui. Isso deve dar um erro, então vamos capturar o erro e fazer o assert em cima dele.

Repare que o big number que defini é acima do total supply em 1 token, já causando o erro de transferência inválida por fundos insuficientes. Isso que nem é considerado nos testes as taxas de gás, caso contrário eu nem precisaria ter usado 1001.

Avançando nos testes, agora vamos fazer o teste da função approve, que serve para dar permissão a outra carteira transferir uma quantidade x de nosso fundos. Para podermos fazer o “antes e depois”, temos de pegar o allowance que nada mais é do que a quantidade permitida em transferências delegadas.

Nada muito diferente aqui se você já entende como funciona a função approve e a função allowance, então vamos avançar para a próxima, que é a função transferFrom, que permite transferências delegadas.

Aqui temos um teste bem semelhante ao transfer, porém com mais passos e mais verificações. No “antes e depois” eu quero ver se o allowance depois da transferência estará igual a antes da mesma, já que ele será “queimado”. Além disso, pego as variáveis de saldo antes e depois também para ver se a transferência de fato aconteceu. Agora sobre a transferência em si, precisamos primeiro aprovar ela e depois executá-la chamando o transferFrom, sem esquecer do parâmetro adicional que é o objeto de configurações da transação e onde posso dizer qual carteira será o from. Neste exemplo, a carteira accounts[1] está transferindo para si saldo da carteira accounts[0] conforme permissão prévia.

E para finalizar, vamos escrever o teste de falha em uma transferência delegada, o que é bem simples de fazer bastando não dar um approve antes do transferFrom.

Como essa tentativa de transferência irá disparar erro, vamos capturá-lo e fazer nossa asserção em cima do mesmo.

Agora experimente rodar a bateria de testes com ‘truffle test’ e espero que você tenha o meso resultado que eu abaixo.

E com isso finalizamos mais este tutorial. Se quiser aprender como fazer deploy desta moeda em blockchain local, recomendo aprender a usar o Ganache neste tutorial. Agora se quiser colocar em uma blockchain pública, recomendo fazer este tutorial aqui. E se quiser aprender a reduzir o consumo de gás nos seus smart contracts, este é o artigo certo.

Um abraço e sucesso!

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 *

6 Replies to “Como criar uma nova criptomoeda usando Solidity e Truffle (JS)”

José Eustaquio

Como sempre, post muito bom. Só gostaria de solicitar a verificação dos links no final sobre o deploy. Os links estão com erro.
Outra detalhe: não explica em qual pasta devem ser instalados os pacotes e o import do BN.js não consta do artigo.

Luiz Duarte

O link do Ganache realmente está quebrado, aquele tutorial ainda não saiu no blog, mas deve sair em breve. Possivelmente em algum momento troquei a ordem de publicação deles. O outro parece estar funcionando normalmente.

Sobre a pasta de instalação dos pacotes, em qualquer aplicação Node.js (o que inclui React e React Native também), você sempre instala os pacotes na raiz do projeto. Sobre o import, é o padrão mesmo, só usar um require, de qualquer forma incluí no artigo para facilitar.

Leonardo

Eu quero criar uma criptomoeda

Luiz Duarte

Se já tiver conhecimentos básicos de programação, só seguir o tutorial e depois fazer deploy em produção.

Nery Charlie B Neri

Por gentileza, gostaria de verificar a possibilidade de uma videoconferência –
falo em nome da Anadips.
Queremos que avalie um projeto da nossa entidade.

Muito grato

Nery
61982207837
[email protected]

Luiz Duarte

Boa noite Nery, tudo bem? Infelizmente não consigo absorver mais projetos do que os que já estou envolvido atualmente. Caso possa me passar um resumo da sua demanda e/ou do perfil que está buscando de profissional eu posso divulgar para alguns contatos na minha rede e eles entram em contato contigo. Pode enviar para [email protected]