Pular para o conteúdo principal
Change page

Anatomia dos contratos inteligentes

Um contrato inteligente é um programa que roda em um endereço na Ethereum. Eles são compostos por dados e funções que podem ser executados ao receber uma transação. Aqui está uma visão geral do que compõe um contrato inteligente.

Pré-requisitos

Certifique-se de ter lido sobre contratos inteligentes primeiro. Este documento pressupõe que você já esteja familiarizado com linguagens de programação como JavaScript ou Python.

Dados

Quaisquer dados do contrato devem ser atribuídos a um local: seja para storage ou memory. É custoso modificar o armazenamento em um contrato inteligente, então você precisa considerar onde seus dados devem residir.

Armazenamento

Dados persistentes são chamados de armazenamento (storage) e são representados por variáveis de estado. Esses valores são armazenados permanentemente na blockchain. Você precisa declarar o tipo para que o contrato possa rastrear quanto armazenamento na blockchain ele precisa quando for compilado.

// Exemplo em Solidity
contract SimpleStorage {
    uint storedData; // Variável de estado
    // ...
}
# Exemplo em Vyper
storedData: int128

Se você já programou em linguagens orientadas a objetos, provavelmente estará familiarizado com a maioria dos tipos. No entanto, address deve ser novo para você se for iniciante no desenvolvimento na Ethereum.

Um tipo address pode conter um endereço Ethereum, o que equivale a 20 bytes ou 160 bits. Ele retorna em notação hexadecimal com um 0x inicial.

Outros tipos incluem:

  • booleano
  • inteiro
  • números de ponto fixo
  • matrizes de bytes de tamanho fixo
  • matrizes de bytes de tamanho dinâmico
  • literais racionais e inteiros
  • literais de string
  • literais hexadecimais
  • enums

Para mais explicações, dê uma olhada na documentação:

Memória

Valores que são armazenados apenas durante o tempo de vida da execução de uma função do contrato são chamados de variáveis de memória. Como não são armazenados permanentemente na blockchain, eles são muito mais baratos de usar.

Aprenda mais sobre como a Máquina Virtual Ethereum (EVM) armazena dados (Armazenamento, Memória e a Pilha) na documentação da Solidity (opens in a new tab).

Variáveis de ambiente

Além das variáveis que você define no seu contrato, existem algumas variáveis globais especiais. Elas são usadas principalmente para fornecer informações sobre a blockchain ou a transação atual.

Exemplos:

PropriedadeVariável de estadoDescrição
block.timestampuint256Timestamp da época do bloco atual
msg.senderaddressRemetente da mensagem (chamada atual)

Funções

Nos termos mais simples, as funções podem obter informações ou definir informações em resposta a transações recebidas.

Existem dois tipos de chamadas de função:

  • internal – estas não criam uma chamada na EVM
    • Funções internas e variáveis de estado só podem ser acessadas internamente (ou seja, de dentro do contrato atual ou de contratos derivados dele)
  • external – estas criam uma chamada na EVM
    • Funções externas fazem parte da interface do contrato, o que significa que podem ser chamadas de outros contratos e por meio de transações. Uma função externa f não pode ser chamada internamente (ou seja, f() não funciona, mas this.f() funciona).

Elas também podem ser public ou private

  • Funções public podem ser chamadas internamente de dentro do contrato ou externamente por meio de mensagens
  • Funções private são visíveis apenas para o contrato em que estão definidas e não em contratos derivados

Tanto as funções quanto as variáveis de estado podem ser tornadas públicas ou privadas

Aqui está uma função para atualizar uma variável de estado em um contrato:

// Exemplo em Solidity
function update_name(string value) public {
    dapp_name = value;
}
  • O parâmetro value do tipo string é passado para a função: update_name
  • É declarada como public, o que significa que qualquer um pode acessá-la
  • Não é declarada como view, então pode modificar o estado do contrato

Funções de visualização

Essas funções prometem não modificar o estado dos dados do contrato. Exemplos comuns são funções "getter" – você pode usar isso para receber o saldo de um usuário, por exemplo.

// Exemplo em Solidity
function balanceOf(address _owner) public view returns (uint256 _balance) {
    return ownerPizzaCount[_owner];
}
dappName: public(string)

@view
@public
def readName() -> string:
  return dappName

O que é considerado modificar o estado:

  1. Escrever em variáveis de estado.
  2. Emitir eventos (opens in a new tab).
  3. Criar outros contratos (opens in a new tab).
  4. Usar selfdestruct.
  5. Enviar ether por meio de chamadas.
  6. Chamar qualquer função não marcada como view ou pure.
  7. Usar chamadas de baixo nível.
  8. Usar assembly inline que contém certos opcodes.

Funções construtoras

As funções constructor são executadas apenas uma vez quando o contrato é implantado pela primeira vez. Como o constructor em muitas linguagens de programação baseadas em classes, essas funções geralmente inicializam variáveis de estado com seus valores especificados.

# Exemplo em Vyper

@external
def __init__(_beneficiary: address, _bidding_time: uint256):
    self.beneficiary = _beneficiary
    self.auctionStart = block.timestamp
    self.auctionEnd = self.auctionStart + _bidding_time

Funções integradas

Além das variáveis e funções que você define no seu contrato, existem algumas funções integradas especiais. O exemplo mais óbvio é:

  • address.send() – Solidity
  • send(address) – Vyper

Elas permitem que os contratos enviem ETH para outras contas.

Escrevendo funções

Sua função precisa de:

  • variável de parâmetro e tipo (se aceitar parâmetros)
  • declaração de internal/external
  • declaração de pure/view/payable
  • tipo de retorno (se retornar um valor)

Um contrato completo pode ser parecido com isto. Aqui, a função constructor fornece um valor inicial para a variável dapp_name.

Eventos e logs

Os eventos permitem que seu contrato inteligente se comunique com seu frontend ou outros aplicativos inscritos. Uma vez que uma transação é validada e adicionada a um bloco, os contratos inteligentes podem emitir eventos e registrar informações em log, que o frontend pode então processar e utilizar.

Exemplos comentados

Estes são alguns exemplos escritos em Solidity. Se você quiser brincar com o código, pode interagir com eles no Remix (opens in a new tab).

Olá, mundo

Token

Ativo digital único

Leitura adicional

Confira a documentação da Solidity e do Vyper para uma visão geral mais completa dos contratos inteligentes: