Entendendo as taxas em blockchains EVM/Ethereum (Gás)

Cripto

Entendendo as taxas em blockchains EVM/Ethereum (Gás)

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

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

Se tem uma coisa que tira as noites de sono dos desenvolvedores de smart contracts são as taxas de transações. Isso porque um smart contract com altas taxas tem baixo incentivo aos usuários utilizarem-no de fato. Entender como as taxas funcionam é o primeiro passo para que no futuro você possa aprender como reduzi-las, construindo smart contracts mais eficientes. Essa é uma habilidade que vale ouro neste mercado e muitos serviços de consultoria que já prestei eram justamente sobre isso.

É importante entender que este artigo não deve ser o seu primeiro contato com Solidity, pois ele aborda conceitos intermediários e alguns até avançados. Quando se está iniciando os estudos, foque apenas em fazer funcionar, deixe otimizações para um segundo momento, ok?

Se preferir, o vídeo abaixo começa ensinando a mesma coisa desse artigo, se preferir assistir ao invés de ler.

Vamos lá!

Curso Node.js e MongoDB

#1 – Por que existem taxas?

A primeira coisa que você tem de entender é o porque das taxas existirem, caso contrário mais nada vai fazer sentido neste artigo.

A rede blockchain é mantida por nodes (nós), que nada mais são do que computadores de pessoas rodando um aplicativo com a implementação de um nó daquela rede, como Geth/Go-Ethereum para rede Ethereum. Quanto mais nós uma blockchain possui, mais descentralizada e forte ela se torna, por isso é importante que exista interesse das pessoas em se tornarem nós.

O problema, é que se tornar um ó é algo que pode sair bem caro. Esses computadores consomem muita energia elétrica para fazer a blockchain funcionar, geralmente se tornando inúteis para outras atividades, portanto gerando custos aos seus proprietários, certo? Então porque razão o dono de uma máquina colocaria ela a serviço da blockchain se não fosse para receber algo por isso? Apenas pelos ideais libertários da web3? Talvez no início de tudo, sim, mas na escala que isso se tornou atualmente, certamente que não.

Quem fornece seu poder computacional para a blockchain o faz para se tornar um minerador, ou validador, dependendo da blockchain. Mineradores/validadores são pagos pelo seu trabalho de processamento das transações que os usuários desejam que sejam persistidas na blockchain. Esse valor é pago através das taxas cobradas junto às transações dos usuários e ele é proporcional ao “esforço computacional” daquela transação em si (CPU, memória, disco, etc).

Assim, entendemos que as taxas de transação existem porque são elas que financiam a própria existência da blockchain. Não apenas isso, mas a cobrança de taxas pelo seu uso também inibe muitos tipos de ataques comuns na web2, já que um atacante “burro” pagaria horrores para poder fazer um ataque de força bruta na blockchain, possivelmente tornando o ataque inviável.

Agora a pergunta que você deve ter é, como essas taxas são calculadas?

#2 – Como as taxas são calculadas?

Antes de falar do cálculo em si você precisa entender que nem todas chamadas à blockchain são cobradas. Operações de leitura de dados, as chamadas “calls” são gratuitas e atendidas imediatamente pelo nó que você consultar, sem passar por mempool e sem taxas. Somente as transactios (os “sends”) é que são cobradas, mesmo que 99% do código da função seja leitura e processamento, se uma instrução salvar dados no disco, ela exigirá uma transação para ser executada, sem exceção.

Então a pergunta mais correta agora é “como as taxas de transações são calculadas?” e uma outra pergunta que você pode pensar é “porque algumas transações são mais caras que outras?”. Vamos responder essa segunda primeiro e isso irá nos levar à resposta da primeira também.

Quando a transação de um usuário é apenas uma transferência de fundos, algo super corriqueiro e simples de ser feito, as taxas cobradas ao usuário e pagas ao minerador (ou validador, vou resumir sempre como minerador, ok?) são pequenas. Agora quando a transação de um usuário é algo complexo, que envolve muitos ciclos de CPU e escreve megabytes no disco, as taxas serão significativamente mais altas, por exemplo.

Indo mais no detalhe, mas sem entrar no bit e no byte, o que acontece é o seguinte: todo código Solidity, após compilado, é convertido em opcodes (operation codes) com comandos que serão convertidos em bytescodes (binário em hexadecimal) que serão interpretados pela EVM (Ethereum Virtual Machine) presente em cada node da blockchain. Cada comando consome uma quantidade de memória e de CPU para ser executado, fora os bytes a serem persistidos no disco, se for o caso. Quanto mais comandos e mais memória e disco, mais caro fica. Mas o quanto mais caro?

Para calcular as taxas de uma transação, a EVM usa uma tabela onde para cada comando, tem um custo em gás associado, como abaixo (tabela parcial).

Repare como fazer um POP na stack (uma das áreas de memória da EVM), tem um custo de 64 gás por KB. Repare que isso é muito mais barato do que escrever algo no disco (STORAGE), onde um SSTORE custa 640.000 gás por KB de dados. Sendo assim, o primeiro passo na estimativa de custos é justamente bater todas instruções com a tabela completa e somar tudo. O resultado final será quanto gás a sua transação irá consumir. Não sabe o que é gás? Já falarei sobre isso, espere um pouco.

Vamos pegar primeiro um exemplo. Considere o código Solidity abaixo, bem simples.

Quando compilado, isso vai virar os opcodes abaixo.

Os primeiros 3 comandos (2 PUSH1 e 1 MSTORE) são de inicialização do contrato na stack da EVM. Já o PUSH0 seguinte é justamente para subir uma variável de estado zerada para a memória (espaço para nosso i do contrato) e depois duplica ela (DUP1) no disco (SSTORE). Na sequência temos um CALLVALUE DUP1 ISZERO que se não me engano indica um constructor vazio (não declaramos um, mas ele sempre existe) e depois a coisa começa a complicar pois entramos na forma “opcode” de descrever as funções e seus comportamentos.

O objetivo aqui não é entender o funcionamento deste contrato em um baixo nível com exatidão, mas sim entender que Solidity vira esses opcodes e que eles são comparados com a tabela para entender o custo de processamento de uma função em gás.

Curso Beholder
Curso Beholder

#3 – O que é Gás?

Gás é uma unidade de medida de esforço computacional fixa, que portanto não sofre ação direta da variação cambial da criptomoeda da rede (ETH na Ethereum, por exemplo). Assim, o custo de 1 gás é sempre 1 gás, independente se o ETH está valendo $1000 ou $10.000 e permitindo com isso que a rede se autoregule conforme sua demanda e inovações futuras do algoritmo. Se estivesse atrelada a wei/ETH, hoje poderia estar ok, mas no futuro teriam de rever o algoritmo conforme atualizações da tabela.

Mas como saber o custo final, em ETH/wei?

Cada unidade de gás possui um preço atualizado regularmente pela rede. Quanto mais lotado está o mempool de transações esperando para serem processadas, mais alta é a cotação do gás. Agora se a rede estiver com pouco uso, o custo de gás baixa conforme algoritmo pré-determinado, para estimular mais seu uso. Também existe a possibilidade de você pagar gás extra para ganhar prioridade na mempool. Você pode acompanhar o preço atualizado do gás no explorador de blocos da sua blockchain.

Assim, se sua transação vai consumir 20.000 gás e o custo da unidade de gás é 200 gwei atualmente (geralmente usamos gwei no gás) o cálculo seria 20.000 * 200 = 4.000.000 gwei ou 0.004 ETH. Aí se quiser saber em dólares, basta fazer a conversão usando a cotação atual do ETH.

Outro ponto importante sobre o gás é que sua estimativa é determinística, ou seja, você pode inclusive simular os gastos em gás antes mesmo de enviar sua transação para a blockchain, desde que conheçamos as variáveis envolvidas e o algoritmo que será executado, que é exatamente o que as carteiras cripto fazem para lhe dar uma ideia das taxas a serem pagas. Assim, caso você não possua saldo suficiente para pagar pelas taxas, elas já lhe avisam que não é uma boa ideia enviar a transação. Isso porque caso você envie a transação mesmo assim, o contrato tentará executar a mesma com o gás enviado e quando o mesmo for esgotado, ela irá falhar e a quantidade gasta não será devolvida (este é o comportamento padrão para qualquer situação de erro em transações).

O custo de gás de uma transação inclusive pode ser estimado por você, durante a fase de desenvolvimento, usando libs web3 como Ethers, como no código abaixo, retirado de um projeto HardHat.

E com isso finalizamos este artigo, espero ter ajudado a clarificar esse assunto e se quiser aprender a reduzir o consumo de gás nos seus smart contracts, este é o artigo certo.

Até a próxima!

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 *