Linguagens de contratos inteligentes
Última edição: @guilhermevendramini(opens in a new tab), 17 de junho de 2024
Um grande aspecto sobre a Ethereum é que os contratos inteligentes podem ser programados usando linguagens relativamente amigáveis para o desenvolvedor. Se você tem experiência com Python ou qualquer linguagem de marcação(opens in a new tab), você pode encontrar uma linguagem com sintaxe familiar.
As duas linguagens mais ativas e mantidas são:
- Solidity
- Vyper
Desenvolvedores mais experientes também podem querer usar o Yul, uma linguagem intermediária para a Máquina Virtual Ethereum, ou Yul+, uma extensão para Yul.
Se você está curioso e gosta de ajudar a testar novas linguagens que ainda estão em grande desenvolvimento, você pode experimentar com Fe, uma linguagem de contrato inteligente emergente que ainda está na sua infância.
Pré-requisitos
Conhecimento anterior de linguagens de programação, especialmente de JavaScript ou Python, pode ajudá-lo a entender as diferenças nas linguagens de contratos inteligentes. Nós também recomendamos que você entenda os contratos inteligentes como um conceito, antes de se aprofundar nas comparações de linguagem. Introdução aos contratos inteligentes.
Solidity
- Linguagem de alto nível orientada para objetos para a implementação de contratos inteligentes.
- Linguagem de marcações mais profundamente influenciada por C++.
- Tipada estaticamente (o tipo de variável é conhecido em tempo de compilação).
- Suporte:
- Herança (você pode estender outros contratos).
- Bibliotecas (você pode criar código reutilizável que pode ser chamado de diferentes contratos – como funções estáticas dentro de uma classe estática em outras linguagens de programação orientadas a objetos).
- Tipos complexos definidos pelo usuário.
Links importantes
- Documentação(opens in a new tab)
- Portal da linguagem Solidity(opens in a new tab)
- Solidity como exemplo(opens in a new tab)
- GitHub(opens in a new tab)
- Solidity Gitter Chatroom(opens in a new tab) ponte para Solidity Matrix Chatroom(opens in a new tab)
- Dicas(opens in a new tab)
- Blog da Solidity(opens in a new tab)
- Solidity Twitter(opens in a new tab)
Exemplo de contrato
1// SPDX-License-Identifier: GPL-3.02pragma solidity >= 0.7.0;34contract Coin {5 // A palavra-chave "public" torna as variáveis6 // acessíveis a partir de outros contratos7 address public minter;8 mapping (address => uint) public balances;910 // Os eventos permitem que os clientes reajam a determinadas11 // alterações de contrato que você declara12 event Sent(address from, address to, uint amount);1314 // O código constructor só é executado quando o contrato15 // é criado16 constructor() {17 minter = msg.sender;18 }1920 // Envia uma quantidade de moedas recém criadas para um endereço21 // Só pode ser chamada pelo criador do contrato22 function mint(address receiver, uint amount) public {23 require(msg.sender == minter);24 require(amount < 1e60);25 balances[receiver] += amount;26 }2728 // Envia uma quantidade de moedas existentes29 // de qualquer solicitador para um endereço30 function send(address receiver, uint amount) public {31 require(amount <= balances[msg.sender], "Saldo insuficiente.");32 balances[msg.sender] -= amount;33 balances[receiver] += amount;34 emit Sent(msg.sender, receiver, amount);35 }36}Exibir tudoCopiar
Esse exemplo deve dar a você, uma ideia de como é a sintaxe de um contrato na Solidity. Para uma descrição mais detalhada das funções e variáveis, consulte a documentação(opens in a new tab).
Vyper
- Linguagem de programação Pythonic
- Digitação sólida
- Código de compilador pequeno e compreensível
- Geração de bytecode eficiente
- Deliberadamente, tem menos recursos do que Solidity, com o objetivo de tornar os contratos mais seguros e mais fáceis de auditar. Vyper não suporta:
- Modificadores
- Herança
- Montagem embutida
- Sobrecarga de função
- Sobrecarga do operador
- Chamada recursiva
- Repetições com comprimento infinito
- Pontos fixos binários
Para obter mais informações, leia a lógica do Vyper(opens in a new tab).
Links importantes
- Documentação(opens in a new tab)
- Vyper como exemplo(opens in a new tab)
- Mais Vyper por Exemplo(opens in a new tab)
- GitHub(opens in a new tab)
- Chat Discord da comunidade Vyper(opens in a new tab)
- Dicas(opens in a new tab)
- Ferramentas e frameworks de desenvolvimento de contratos inteligentes para Vyper
- VyperPunk - Aprenda a proteger e hackear contratos inteligentes Vyper(opens in a new tab)
- VyperExamples - Exemplos de vulnerabilidade Vyper(opens in a new tab)
- Vyper Hub para desenvolvimento(opens in a new tab)
- Exemplos de contratos inteligentes de maiores sucessos Vyper(opens in a new tab)
- Recursos incríveis com curadoria do Vyper(opens in a new tab)
Exemplo
1# Leilão aberto23# Parâmetros do leilão4# Beneficiário recebe dinheiro do licitante com lance mais alto5beneficiary: public(address)6auctionStart: public(uint256)7auctionEnd: public(uint256)89# Estado atual do leilão10highestBidder: public(address)11highestBid: public(uint256)1213# Definido como verdadeiro no final, não permite qualquer alteração14ended: public(bool)1516# Acompanha os lances reembolsados para que possamos seguir o padrão de saque17pendingReturns: public(HashMap[address, uint256])1819# Cria um leilão simples com `_bidding_time`20# segundos de tempo de licitação em nome do21# endereço do beneficiário `_beneficiary`.22@external23def __init__(_beneficiary: address, _bidding_time: uint256):24 self.beneficiary = _beneficiary25 self.auctionStart = block.timestamp26 self.auctionEnd = self.auctionStart + _bidding_time2728# Licita no leilão com o valor enviado29# junto com esta transação.30# O valor só será devolvido se o31# leilão não foi ganho.32@external33@payable34def bid():35 # Verifica se o período de licitação acabou.36 assert block.timestamp < self.auctionEnd37 # Verifica se o lance é alto o suficiente38 assert msg.value > self.highestBid39 # Rastreia o reembolso do licitante anterior40 self.pendingReturns[self.highestBidder] += self.highestBid41 # Rastreia o mais recente lance mais alto42 self.highestBidder = msg.sender43 self.highestBid = msg.value4445# Retira um lance previamente reembolsado. O padrão de retirada é46# usado aqui para evitar um problema de segurança. Se os reembolsos fossem diretamente47# enviados como parte do lance (bid()), um contrato de licitação malicioso poderia bloquear48# esses reembolsos e, assim, bloquear a entrada de novos lances mais altos.49@external50def withdraw():51 pending_amount: uint256 = self.pendingReturns[msg.sender]52 self.pendingReturns[msg.sender] = 053 send(msg.sender, pending_amount)5455# Termina o leilão e envia o lance mais alto56# para o beneficiário.57@external58def endAuction():59 # É uma boa diretriz para estruturar funções que interagem60 # com outros contratos (ou seja, eles chamam funções ou enviam Ether)61 # em três fases:62 # 1. verificando as condições63 # 2. realizando ações (condições potencialmente mutáveis)64 # 3. interagindo com outros contratos65 # Se essas fases forem misturadas, o outro contrato poderia retornar ao66 # contrato atual e modificar o estado ou causar67 # efeitos (pagamento em ether) para serem realizados várias vezes.68 # Se as funções chamadas internamente incluem interações69 # com contratos externos, também devem ser consideradas interações com70 # contratos externos.7172 # 1. Condições73 # Verifique se o horário de término do leilão foi atingido74 assert block.timestamp >= self.auctionEnd75 # Verifique se esta função já foi chamada76 assert not self.ended7778 # 2. Efeitos79 self.ended = True8081 # 3. Interação82 send(self.beneficiary, self.highestBid)Exibir tudoCopiar
Esse exemplo deve dar-nos uma noção do que é a sintaxe do contrato Vyper. Para uma descrição mais detalhada das funções e variáveis, consulte a documentação(opens in a new tab).
Yul e Yul+
Se você é novo na Ethereum e ainda não fez qualquer codificação com linguagens de contrato inteligentes, recomendamos começar com Solidity ou Vyper. Apenas olhe para Yul ou Yul+ quando estiver familiarizado com as melhores práticas de segurança inteligente do contrato e com as especificações de trabalho com a EVM.
Yul
- Linguagem intermediária para Ethereum.
- Suporta a EVM e eWASM(opens in a new tab), um WebAssembly com sabor de Ethereum e concebido para ser um denominador comum utilizável de ambas as plataformas.
- Alvo para fases de otimização de alto nível que podem beneficiar tanto as plataformas EVM como Ewasm de forma igual.
Yul+
- Uma extensão de baixo nível altamente eficiente para Yul.
- Inicialmente concebido para um optimistic rollup.
- Yul+ pode ser visto como uma proposta de atualização experimental para Yul, adicionando novos recursos.
Links Importantes
- Documentação(opens in a new tab)
- Documentação Yul+(opens in a new tab)
- Yul+ Playground(opens in a new tab)
- Yul+ Post de Introdução(opens in a new tab)
Exemplo de contrato
O exemplo a seguir simples implementa uma função de energia. Ele pode ser compilado usando solc --strict-assembly --bin input.yul
. O exemplo deve ser armazenado no arquivo input.yul.
1{2 function power(base, exponent) -> result3 {4 switch exponent5 case 0 { result := 1 }6 case 1 { result := base }7 default8 {9 result := power(mul(base, base), div(exponent, 2))10 if mod(exponent, 2) { result := mul(base, result) }11 }12 }13 let res := power(calldataload(0), calldataload(32))14 mstore(0, res)15 return(0, 32)16}Exibir tudo
Se você já é bem experiente com contratos inteligentes, uma implementação do ERC20 em Yul pode ser encontrada aqui(opens in a new tab).
Fe
- Linguagem estaticamente digitada para a Máquina Virtual Ethereum (EVM).
- Inspirado por Python e Rust.
- O objetivo é ser fácil de aprender -- mesmo para desenvolvedores que são novos no ecossistema Ethereum.
- Fe ainda está em seus estágios iniciais, a linguagem teve sua versão alfa em janeiro de 2021.
Links importantes
- GitHub(opens in a new tab)
- Anúncio da Fe(opens in a new tab)
- Fe 2021 Roadmap(opens in a new tab)
- Chat de Discord Fe(opens in a new tab)
- Fe Twitter(opens in a new tab)
Exemplo de contrato
O seguinte é um contrato simples implementado em Fe.
1type BookMsg = bytes[100]23contrate GuestBook:4 pub guest_book: map<address, BookMsg>56 event Signed:7 book_msg: BookMsg89 pub def sign(book_msg: BookMsg):10 eu mesmo. uest_book[msg.sender] = book_msg1112 emite Signed(book_msg=book_msg)1314 pub def get_msg(addr: address) -> BookMsg:15 remeter. uest_book[addr].to_mem()16Exibir tudo
Como escolher
Como com qualquer outra linguagem de programação, trata-se principalmente de escolher a ferramenta certa para o trabalho certo, assim como preferências pessoais.
Aqui estão algumas coisas a considerar se você ainda não tentou nenhuma das linguagens:
O que é que há de melhor em Solidity?
- Se você for um iniciante, há muitos tutoriais e ferramentas de aprendizagem disponíveis. Veja mais sobre isso na seção Aprenda programando.
- Ótima ferramenta de desenvolvedor disponível.
- Solidity tem uma grande comunidade de desenvolvedores, o que significa que você provavelmente encontrará respostas para as suas perguntas muito rapidamente.
O que há de melhor em Vyper?
- Uma ótima maneira de começar para desenvolvedores de Python que querem escrever contratos inteligentes.
- O Vyper tem um número menor de características que o torna ótimo para a rápida reprodução de ideias.
- A Vyper visa ser fácil de controlar e o máximo legível ao ser humano.
O que é ótimo sobre Yul e Yul+?
- Uma linguagem de baixo nível simples e funcional.
- Permite aproximar-se muito mais da EVM bruta, o que pode ajudar a otimizar o uso de gás de seus contratos.
Comparações de linguagens
Para comparações de sintaxe básica, o ciclo de vida do contrato, interfaces, operadores, estruturas de dados, funções, fluxo de controle e mais confira esta folha de crédito por auditoria(opens in a new tab)