📇#[ink::contract]
A macro #[ink::contract]
é o ponto de entrada para escrever contratos inteligentes ink!.
Se você é um iniciante que está tentando aprender ink!, recomendamos que você dê uma olhada no nosso extenso workshop de ink!.
Descrição
The macro does analysis on the provided smart contract code and generates proper code.
Usage
Argumentos do cabeçalho
A macro #[ink::contract]
pode receber argumentos de cabeçalho adicionais separados por vírgulas:
compile_as_dependency: bool
compile_as_dependency: bool
Indica ao gerador de código ink! para sempre compilar ou nunca compilar o smart contract como se fosse usado como uma dependência de outro smart contract ink!.
Normalmente, essa sinalização só é realmente útil para desenvolvedores ink! que desejam inspecionar a geração de código de smart contracts ink!. O autor não tem conhecimento de nenhum caso de uso prático específico para usuários que faça uso desse sinalizador, mas os escritores de contratos são encorajados a refutar essa afirmação.
Observe que é recomendado usar o recurso embutido da crate ink-as-dependency
para marcar as dependências de smart contracts listadas no Cargo.toml
de um contrato como dependências reais para ink!.
Exemplo de Uso:
Valor padrão: Dependente da propagação do recurso do arquivo Cargo.toml
.
env: impl Environment
env: impl Environment
Indica ao gerador de código ink! qual ambiente utilizar para o smart contract ink!. O ambiente deve implementar o traço Environment (definido em ink_env
) e fornecer todas as definições de tipos fundamentais necessárias, como Balance
, AccountId
, etc.
Ao usar uma implementação personalizada de Environment
para um smart contract, todos os tipos que ele expõe para o smart contract ink! e os tipos espelhados usados no tempo de execução devem estar alinhados em relação à codificação SCALE e semântica.
Usage Example:
Dada uma implementação personalizada do ambiente Environment
:
Um usuário pode implementar seu contrato ink! usando a implementação personalizada do Ambiente conforme demonstrado abaixo:
Valor padrão: DefaultEnvironment
definido no pacote ink_env
.
Análise
A macro #[ink::contract]
realiza uma análise completa do contrato inteligente de entrada em relação a argumentos inválidos e estrutura.
Algumas regras de exemplo incluem, mas não se limitam a:
Deve haver exatamente uma estrutura
#[ink(storage)]
. Essa estrutura define o layout do armazenamento em que o contrato inteligente ink! opera. O usuário pode utilizar uma variedade de recursos integrados, combiná-los de várias maneiras ou até mesmo fornecer suas próprias implementações de estruturas de dados de armazenamento. Para mais informações, visite a documentação do crateink_storage
.
Exemplo:
Deve haver pelo menos um método
#[ink(constructor)]
definido. Os métodos marcados com#[ink(constructor)]
são especiais, pois são despacháveis ao instanciar o contrato. Um contrato pode definir vários construtores desse tipo, o que permite que os usuários do contrato instanciem o contrato de várias maneiras diferentes.
Exemplo: Dada a definição do contrato Flipper
acima, adicionamos um #[ink(constructor)]
da seguinte maneira:
Deve haver pelo menos um método
#[ink(message)]
definido. Os métodos marcados com#[ink(message)]
são especiais, pois são despacháveis ao invocar o contrato. O conjunto de mensagens ink! definidas para um contrato ink! define a sua interface de programação de aplicação (API), com a qual os usuários podem interagir. Um contrato ink! pode ter vários métodos ink! definidos.
Nota: Uma mensagem ink! com um receptor &self
só pode ler o estado, enquanto uma mensagem ink! com um receptor &mut self
pode alterar o armazenamento do contrato.
Exemplo
Dado a definição do contrato Flipper
acima, adicionamos algumas definições #[ink(message)]
da seguinte forma:
Mensagens Pagáveis:
Uma mensagem ink! por padrão rejeitará chamadas que adicionem fundos ao contrato inteligente. Os autores de contratos ink! podem tornar uma mensagem ink! pagável adicionando o sinalizador "payable
" a ela. Um exemplo abaixo:
Observe que os construtores ink! são sempre implicitamente pagáveis e, portanto, não podem ser marcados como tal.
Controlando o seletor das mensagens:
Cada mensagem e construtor do ink! possui um seletor único que identifica de forma exclusiva a mensagem ou o construtor dentro do smart contract ink!. Esses seletores são usados principalmente para direcionar a chamada do contrato ao executá-lo.
O autor de um smart contract ink! pode controlar o seletor de uma mensagem ou construtor usando a flag selector
. Um exemplo é mostrado abaixo:
Interacting with the Contract Executor
A crate ink_env
fornece recursos para interagir com o executor do contrato que conecta os contratos inteligentes ink! com o mundo exterior.
Por exemplo, é possível consultar o chamador da chamada atual através de:
No entanto, ink! fornece uma maneira muito mais simples de interagir com o executor do contrato por meio do seu acessor de ambiente. Um exemplo abaixo:
Eventos
Um contrato inteligente ink! pode definir eventos que podem ser emitidos durante a execução do contrato. A emissão de eventos pode ser usada por ferramentas de terceiros para consultar informações sobre a execução e estado de um contrato.
O exemplo a seguir mostra um contrato ink! que define e emite um evento "Transferred
" no #[ink(constructor)]
.
Neste exemplo, o módulo erc20
define um contrato inteligente ink! para uma token ERC20 básica. O evento "Transferred" é definido como uma estrutura que contém informações sobre o remetente, destinatário e valor transferido. No construtor, o evento é emitido quando o contrato é instanciado, informando que uma transferência ocorreu do endereço do contrato para o endereço do chamador. O contrato também possui um método total_supply
que retorna o valor total de fornecimento do token.
Exemplo: Flipper
O código abaixo mostra a implementação completa do contrato inteligente Flipper ink!. Para nós, ele funciona como o "Olá, mundo!" dos contratos inteligentes ink!, pois é mínimo, mas ainda fornece alguma funcionalidade mais ou menos útil.
Ele controla um único valor bool
que pode ser false
ou true
e permite que o usuário inverta esse valor usando a mensagem Flipper::flip
ou recupere o valor atual usando Flipper::get
.
O código abaixo mostra a implementação completa do contrato inteligente ink! chamado Flipper. Para nós, ele atua como o "Olá, mundo!" dos contratos inteligentes ink!, pois é mínimo, mas ainda fornece alguma funcionalidade mais ou menos útil. Ele controla um único valor booleano que pode ser falso ou verdadeiro e permite que o usuário inverta esse valor usando a mensagem Flipper::flip
ou obtenha o valor atual usando a mensagem Flipper::get
.
Last updated