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 Node.js e MongoDB

#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.

Um abraço e sucesso!

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 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.