📇#[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!arrow-up-right.

The macro does analysis on the provided smart contract code and generates proper code.

Argumentos do cabeçalhoarrow-up-right

A macro #[ink::contract] pode receber argumentos de cabeçalho adicionais separados por vírgulas:

compile_as_dependency: boolarrow-up-right

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:

#[ink::contract(compile_as_dependency = true)]
mod my_contract {
    #[ink(storage)]
    pub struct MyStorage;

    impl MyStorage {
        #[ink(constructor)]
        pub fn construct() -> Self { MyStorage {} }

        #[ink(message)]
        pub fn message(&self) {}
    }
    // ...
}

Valor padrão: Dependente da propagação do recurso do arquivo Cargo.toml.

env: impl Environmentarrow-up-right

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.

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 crate ink_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 Executorarrow-up-right

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:

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: Flipperarrow-up-right

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