14 de março de 2023
Índice
O que é uma EVM?
Por que entender a EVM é importante?
Uma análise de alto nível da EVM
Variáveis Globais
Armazenamento Persistente
Armazenamento Volátil
Contas na Ethereum
Transações na Ethereum
Ciclo de Vida das Transações
↳ Sucesso
↳ Falha
Chamadas de Contrato Inteligente
Chamadas internas
Chamadas externas
↳ Chamada
↳ StaticCall
↳ DelegateCall
O artigo a seguir é uma referência ao capítulo smartcontractshacking.com do curso sobre EVM por Johnny Time.
O que é uma EVM?
A Ethereum Virtual Machine (EVM), ou Máquina Virtual da Ethereum, é um componente essencial da blockchain Ethereum que executa contratos inteligentes escritos em linguagens de programação como Solidity. A EVM é um ambiente de sandbox projetado para garantir a execução segura e determinística de contratos inteligentes. Este artigo fornece uma visão geral dos fundamentos da Máquina Virtual da Ethereum, incluindo seus componentes e ciclo de vida da transação.
Por que entender a EVM é importante?
- Entendendo a tecnologia: a EVM é o ambiente de tempo de execução para a execução de contratos inteligentes na blockchain Ethereum. Ao entender a EVM, você pode obter uma compreensão mais profunda de como a Ethereum funciona e como os contratos inteligentes são executados.
- Desenvolvendo contratos inteligentes: se você planeja desenvolver contratos inteligentes para a blockchain Ethereum, precisará saber como a EVM funciona. Isso inclui entender as linguagens de programação usadas para escrever contratos inteligentes (como Solidity) e como compilá-los e implantá-los na rede Ethereum.
- Considerações de segurança: a EVM tem seu próprio conjunto de considerações de segurança, como o potencial para ataques de reentrância e _overflows _de números inteiros. Ao entender esses riscos, você pode escrever contratos inteligentes mais seguros e evitar vulnerabilidades comuns.
- Solução de problemas: se você encontrar problemas com contratos inteligentes na rede Ethereum, entender a EVM pode ajudá-lo a diagnosticar e resolver o problema.
Uma análise de alto nível da EVM
A EVM é uma máquina virtual composta por vários componentes, semelhante a uma máquina virtual em nosso computador normal.
Tanto a EVM quanto uma máquina virtual típica em um computador fornecem uma camada de abstração que permite que o software seja executado em diferentes hardwares e sistemas operacionais sem exigir que o software seja reescrito para cada plataforma específica. Ambos também usam um conjunto de instruções (opcodes) para realizar operações nos dados e ambos têm acesso à memória e ao armazenamento.
Os componentes de uma máquina virtual em um computador normal são:
- Hipervisor — a camada que cria e gerencia as máquinas virtuais.
- CPUs virtuais — emulam a CPU física do computador.
- Memória virtual — usada pela máquina virtual para alocar e gerenciar sua própria memória.
- Dispositivos virtuais — emulam os dispositivos físicos do computador, como placas de rede e discos rígidos.
- Rede virtual — permite que as máquinas virtuais se comuniquem entre si e com o mundo externo.
- Interface de gerenciamento — usada pelo administrador para gerenciar e monitorar as máquinas virtuais e seus recursos.
- Armazenamento virtual — usado pela máquina virtual para acessar e gerenciar seu próprio espaço de armazenamento, que pode ser físico ou virtual.
Na EVM, estes são os componentes de uma máquina virtual:
Componentes da EVM. Créditos Johnny Time @RealJohnnyTime
Variáveis Globais
As variáveis globais na EVM incluem:
- Número do bloco;
- Dificuldade;
- Origem da transação: identifica a conta EOA original que enviou a transação;
- Preço do gás.
Armazenamento Persistente
O armazenamento persistente na EVM inclui:
- Código do programa: armazenado na blockchain como bytecode.
- Armazenamento do programa: armazenamento e estado do contrato inteligente.
- Estado da máquina: informações da conta que estão sendo atualizadas, como nonces e saldos.
Armazenamento Volátil
O armazenamento volátil na EVM inclui:
- Contador do programa: indica o número de opcodes sendo calculados.
- Gás disponível: cada transação tem um gás especificado e cada opcode requer gás. Se não houver gás restante, a transação é revertida. Se houver gás restante, ele é devolvido.
- Pilha (stack): memória LIFO de 32 bytes que armazena variáveis locais. Ela tem uma profundidade máxima de 1024 e não pode armazenar arrays, estruturas de mapeamento ou strings.
- Memória: usada para armazenar coisas que não podem ser armazenadas na pilha, como arrays, estruturas de mapeamento e strings.
Na próxima seção, iremos nos aprofundar em como o Solidity é compilado em bytecode, que pode então ser processado pela EVM.
Compilação
A Máquina Virtual da Ethereum só é capaz de entender bytecode, não linguagens de programação como o Solidity.
Então, como uma linguagem de alto nível como o Solidity é processada pela EVM?
O Solidity ou outra linguagem de alto nível, como o Vyper, precisa primeiro ser compilada em uma série de instruções de máquina que a EVM pode integrar. Essas instruções também são chamadas de “opcodes”. Cada Opcode representa uma operação específica que a EVM pode realizar, como adicionar 2 números ou verificar o saldo de uma conta.
Depois que o código é compilado em opcodes, ele é implantado na blockchain Ethereum. Quando um usuário deseja interagir com o contrato inteligente, ele cria uma transação que inclui os dados relevantes e os envia para a rede.
Quando a transação é processada pela rede, a EVM recupera o bytecode associado ao contrato inteligente e o executa. A EVM lê cada opcode por vez e executa a operação correspondente. À medida que a EVM executa o código, ela atualiza o estado da blockchain modificando os saldos das contas ou atualizando o armazenamento do contrato.
No final da execução, a EVM retorna a saída do contrato inteligente para o usuário. Se o contrato modificar o estado da blockchain, as alterações serão armazenadas na rede Ethereum para todos os nós verem.
Portanto, quando um contrato inteligente é implantado, apenas o bytecode é implantado.
Processo de compilação do Solidity em bytecode para ser executado pela EVM. Créditos para Johnny Time @RealJohnnyTime.
Como plataformas como a Etherscan verificam se um contrato é válido? O processo envolve a apresentação do contrato, em que o Etherscan faz hashes e compara com o bytecode.
Verificando o código-fonte no Etherscan.
A seguir, abordaremos como as contas funcionam na Ethereum.
Contas na Ethereum
As contas na Ethereum são entidades que podem enviar e receber ether, a criptomoeda nativa da blockchain Ethereum.
Existem dois tipos de contas na Ethereum: contas de propriedade externa (EOAs) e contas de contrato.
As EOAs são de propriedade de indivíduos e controladas por chaves privadas. Elas podem enviar e receber ether (a criptomoeda nativa da Ethereum) e interagir com contratos inteligentes na rede Ethereum.
As contas de contrato, por outro lado, são contas que armazenam código e são controladas por esse código. Elas podem ser criadas enviando uma transação para a rede Ethereum com o código a ser armazenado na conta. Depois de criada, a conta do contrato tem seu próprio endereço e pode interagir com outras contas na rede, incluindo outros contratos inteligentes e EOAs.
Diferença entre as EOAs e contas de contratos inteligentes. Créditos para Johnny Time @RealJohnnyTime.
Uma diferença principal entre as EOAs e contas de contrato inteligente é que as EOAs só podem enviar e receber ether, enquanto as contas de contrato também podem executar código e modificar seu estado interno (ou seja, armazenamento) com base na lógica definida em seu código de contrato inteligente.
Outra diferença importante é como a EOA é capaz de acionar transações, mas o contrato inteligente não seria capaz de acionar transações. É isso o que o Account Abstraction (EIP 4337) pretende resolver!
Account Abstraction (Abstração de Conta)
Atualmente, todas as transações na Ethereum devem ser iniciadas e assinadas por uma conta de propriedade externa (EOA) com um saldo de ether para cobrir a taxa de transação. Isso significa que os contratos inteligentes, que não possuem saldo, não podem iniciar transações por conta própria.
O Account Abstraction propõe mudar isso permitindo que contratos inteligentes iniciem transações sem a necessidade de uma EOA. A ideia é abstrair o conceito de contas da blockchain subjacente e permitir que qualquer endereço, incluindo contratos inteligentes, inicie transações.
O Account Abstraction tem o potencial de tornar os contratos inteligentes mais versáteis e poderosos, pois eles podem iniciar transações por conta própria sem a necessidade de uma EOA. Isso pode abrir novos casos de uso para aplicativos descentralizados (dApps) e permitir novos tipos de interações entre contratos inteligentes e a rede Ethereum.
Para mais detalhes, confira este artigo incrível explicando o EIP 4337 abaixo:
https://blog.jarrodwatts.com/what-is-account-abstraction-and-how-does-eip-4337-work
Transações na Ethereum
As transações na Ethereum são mensagens enviadas entre duas contas na rede Ethereum. Elas representam uma unidade de transferência de valor ou a iniciação de uma operação de contrato inteligente. As transações incluem informações como os endereços do remetente e do destinatário, a quantidade de ether ou token que está sendo transferido e o preço e limite do gás para executar a transação. As transações são validadas e processadas por nós na rede e são registradas na blockchain como parte de um bloco. Uma vez confirmada a transação, seus efeitos são permanentes e não podem ser revertidos.
As transações são usadas para ativar a máquina virtual da Ethereum. Quando uma transação é enviada, ela pode conter um valor de mensagem e dados de mensagem, que ativam a EVM. Se for enviado ether para um contrato inteligente, ele precisará de uma função receive()
ou fallback()
, caso contrário, a transação falhará. Os dados também podem ser enviados para outra conta EOA ou um contrato inteligente.
Se uma transação contém dados que serão executados em outro contrato inteligente, a EVM executará a função se a assinatura for encontrada no contrato. Caso contrário, ela executará a função de fallback. O diagrama abaixo mostra a relação.
Relacionamento da transação
Então, quais são os estágios pelos quais uma transação na EVM passa antes de vermos uma mudança de estado na blockchain?
Ciclo de vida da transação
O ciclo de vida de uma transação em uma máquina virtual da Ethereum (EVM) pode ser dividido nas seguintes etapas:
- Criação: uma transação é criada e assinada por um ator externo, geralmente uma conta de propriedade externa (EOA) ou um contrato inteligente.
- Propagação: a transação é propagada através da rede de nós da Ethereum até ser captada por um minerador.
- Verificação: o minerador verifica a assinatura da transação e confere se a conta tem gás suficiente para pagar a taxa de transação. O nó executa cada opcode em ordem, reduzindo o gás restante após a execução de cada opcode. A pilha, a memória e o armazenamento são atualizados e a EVM é encerrada, limpando a pilha e a memória.
- Inclusão: a transação é incluída em um bloco, que é então adicionado à blockchain pelo minerador.
- Execução: uma vez que o bloco contendo a transação é adicionado à blockchain, a transação é executada pela EVM. A EVM executa o código contido no contrato inteligente associado à transação e atualiza o estado da rede Ethereum de acordo.
- Confirmação: a transação é considerada confirmada assim que for incluída em um bloco suficientemente profundo na blockchain. O número de confirmações necessárias depende do nível de segurança exigido para a transação.
- Conclusão: a transação é considerada concluída assim que for confirmada e o código do contrato inteligente for executado. A transação pode ser consultada por atores externos para obter informações sobre seu status de execução e resultados.
A fase de Conclusão pode ser bem-sucedida ou falhar.
Sucesso
Em uma fase de conclusão bem-sucedida:
- O armazenamento e o estado são atualizados.
- O gás restante é devolvido.
Falha
Em uma fase de conclusão com falha:
- Se não houver gás restante, a pilha e a memória são apagadas, a transação é revertida e não há reembolso do gás.
- Se sobrar gás, ele é devolvido após a transação.
Por fim, veremos como as funções de contrato inteligente estão sendo chamadas na Ethereum.
Chamadas de Contrato Inteligente
Existem dois tipos de chamadas de contratos inteligentes na Ethereum:
1. Chamadas internas:
Quando um contrato chama uma função dentro de si, isso é chamado de chamada interna. A memória e a pilha permanecem as mesmas e não há necessidade de uma nova instância da EVM.
Chamada de contrato interna. Créditos para Johnny Time @TheRealJohnnyTime.
2. Chamadas externas:
Quando um contrato chama uma função em outro contrato, isso é chamado de chamada externa. Existem três tipos de chamadas externas:
Chamada:
A função de chamada é usada para chamar outro contrato inteligente e obter uma resposta. Quando a função de chamada é executada, uma nova instância da EVM é criada para o contrato inteligente de destino, que inclui o código do contrato, armazenamento e uma nova pilha, memória e contador de programa. O parâmetro msg.sender
é definido como o endereço do contrato inteligente invocador e o parâmetro msg.value
é definido como o valor especificado na função de chamada.
Depois que o contrato inteligente de destino executa sua função, ele retorna uma resposta ao contrato inteligente que o invocou. Essa resposta pode conter dados ou não. Se o contrato inteligente de destino modificar o estado da blockchain, essa mudança de estado será refletida na memória do contrato inteligente de invocação.
Fluxo de contrato de chamada
StaticCall:
A função _staticcall _é usada para chamar outro contrato inteligente sem modificar o estado da blockchain. É semelhante à função de chamada, mas com uma grande diferença: não permite que alterações de estado sejam feitas no armazenamento do contrato de destino ou no estado da máquina. Isso é útil para leitura de dados de outros contratos inteligentes sem incorrer nos custos de gás associados às mudanças de estado.
Fluxo de contrato da StaticCall.
DelegateCall:
Esta é a chamada mais complicada. Houve muitos hacks do uso inseguro de delegatecall.
A função _delegatecall _é usada para chamar outro contrato inteligente e atualizar o estado do contrato inteligente invocador. Nesse caso, o contrato inteligente de destino é executado com o contexto do contrato inteligente invocador, o que significa que sua memória e pilha são definidas como as do contrato invocador e seu armazenamento é definido como o do contrato invocador. Os parâmetros msg.sender
e msg.value
também são definidos como os da mensagem anterior.
Fluxo de contrato da DelegateCall.
Uma vez que o contrato inteligente de destino tenha executado sua função, quaisquer atualizações feitas no armazenamento do contrato inteligente invocador serão refletidas na memória do contrato inteligente invocador. No entanto, o estado da máquina do contrato inteligente invocador não será modificado, o que significa que o custo do gás da operação será menor do que o de uma função de chamada regular.
Em conclusão, a máquina virtual da Ethereum (EVM) é um componente crucial da blockchain Ethereum que executa contratos inteligentes escritos em linguagens como o Solidity. Ao fornecer um ambiente de sandbox seguro e determinístico, a EVM permite que os desenvolvedores criem aplicativos descentralizados e contratos inteligentes na rede Ethereum. Compreender a EVM é essencial para qualquer pessoa que planeje desenvolver contratos inteligentes ou solucionar problemas com eles. A EVM consiste em vários componentes, incluindo variáveis globais, armazenamento persistente e seções voláteis, que trabalham juntos para executar contratos inteligentes. Ao aprender sobre a EVM e como ela funciona, os desenvolvedores podem criar contratos inteligentes mais seguros e eficientes e contribuir para o crescimento e evolução da rede Ethereum.
Créditos para Johnny Time por seu detalhamento sobre a EVM.
Esse artigo foi escrito por Yong kang Chia e traduzido por Isabela Curado Nehme. Seu original pode ser lido aqui.
Latest comments (0)