Pular para o conteúdo principal
Change page

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.

Exemplo de contrato

1// SPDX-License-Identifier: GPL-3.0
2pragma solidity >= 0.7.0;
3
4contract Coin {
5 // A palavra-chave "public" torna as variáveis
6 // acessíveis a partir de outros contratos
7 address public minter;
8 mapping (address => uint) public balances;
9
10 // Os eventos permitem que os clientes reajam a determinadas
11 // alterações de contrato que você declara
12 event Sent(address from, address to, uint amount);
13
14 // O código constructor só é executado quando o contrato
15 // é criado
16 constructor() {
17 minter = msg.sender;
18 }
19
20 // Envia uma quantidade de moedas recém criadas para um endereço
21 // Só pode ser chamada pelo criador do contrato
22 function mint(address receiver, uint amount) public {
23 require(msg.sender == minter);
24 require(amount < 1e60);
25 balances[receiver] += amount;
26 }
27
28 // Envia uma quantidade de moedas existentes
29 // de qualquer solicitador para um endereço
30 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 tudo
Copiar

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

Exemplo

1# Leilão aberto
2
3# Parâmetros do leilão
4# Beneficiário recebe dinheiro do licitante com lance mais alto
5beneficiary: public(address)
6auctionStart: public(uint256)
7auctionEnd: public(uint256)
8
9# Estado atual do leilão
10highestBidder: public(address)
11highestBid: public(uint256)
12
13# Definido como verdadeiro no final, não permite qualquer alteração
14ended: public(bool)
15
16# Acompanha os lances reembolsados para que possamos seguir o padrão de saque
17pendingReturns: public(HashMap[address, uint256])
18
19# Cria um leilão simples com `_bidding_time`
20# segundos de tempo de licitação em nome do
21# endereço do beneficiário `_beneficiary`.
22@external
23def __init__(_beneficiary: address, _bidding_time: uint256):
24 self.beneficiary = _beneficiary
25 self.auctionStart = block.timestamp
26 self.auctionEnd = self.auctionStart + _bidding_time
27
28# Licita no leilão com o valor enviado
29# junto com esta transação.
30# O valor só será devolvido se o
31# leilão não foi ganho.
32@external
33@payable
34def bid():
35 # Verifica se o período de licitação acabou.
36 assert block.timestamp < self.auctionEnd
37 # Verifica se o lance é alto o suficiente
38 assert msg.value > self.highestBid
39 # Rastreia o reembolso do licitante anterior
40 self.pendingReturns[self.highestBidder] += self.highestBid
41 # Rastreia o mais recente lance mais alto
42 self.highestBidder = msg.sender
43 self.highestBid = msg.value
44
45# Retira um lance previamente reembolsado. O padrão de retirada é
46# usado aqui para evitar um problema de segurança. Se os reembolsos fossem diretamente
47# enviados como parte do lance (bid()), um contrato de licitação malicioso poderia bloquear
48# esses reembolsos e, assim, bloquear a entrada de novos lances mais altos.
49@external
50def withdraw():
51 pending_amount: uint256 = self.pendingReturns[msg.sender]
52 self.pendingReturns[msg.sender] = 0
53 send(msg.sender, pending_amount)
54
55# Termina o leilão e envia o lance mais alto
56# para o beneficiário.
57@external
58def endAuction():
59 # É uma boa diretriz para estruturar funções que interagem
60 # com outros contratos (ou seja, eles chamam funções ou enviam Ether)
61 # em três fases:
62 # 1. verificando as condições
63 # 2. realizando ações (condições potencialmente mutáveis)
64 # 3. interagindo com outros contratos
65 # Se essas fases forem misturadas, o outro contrato poderia retornar ao
66 # contrato atual e modificar o estado ou causar
67 # efeitos (pagamento em ether) para serem realizados várias vezes.
68 # Se as funções chamadas internamente incluem interações
69 # com contratos externos, também devem ser consideradas interações com
70 # contratos externos.
71
72 # 1. Condições
73 # Verifique se o horário de término do leilão foi atingido
74 assert block.timestamp >= self.auctionEnd
75 # Verifique se esta função já foi chamada
76 assert not self.ended
77
78 # 2. Efeitos
79 self.ended = True
80
81 # 3. Interação
82 send(self.beneficiary, self.highestBid)
Exibir tudo
Copiar

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

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.

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) -> result
3 {
4 switch exponent
5 case 0 { result := 1 }
6 case 1 { result := base }
7 default
8 {
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.

Exemplo de contrato

O seguinte é um contrato simples implementado em Fe.

1type BookMsg = bytes[100]
2
3contrate GuestBook:
4 pub guest_book: map<address, BookMsg>
5
6 event Signed:
7 book_msg: BookMsg
8
9 pub def sign(book_msg: BookMsg):
10 eu mesmo. uest_book[msg.sender] = book_msg
11
12 emite Signed(book_msg=book_msg)
13
14 pub def get_msg(addr: address) -> BookMsg:
15 remeter. uest_book[addr].to_mem()
16
Exibir 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)

Leitura adicional

Este artigo foi útil?