# Estrutura de um smart contract em Solidity

Um contrato inteligente (smart contract) em Solidity, a linguagem de programação mais comum para contratos inteligentes na blockchain Ethereum, é basicamente um código que é executado na Ethereum Virtual Machine (EVM) quando acionado por uma transação.

Vamos descrever uma estrutura básica de um contrato inteligente em Solidity:

```solidity
// Declaração da versão do Solidity a ser usada
pragma solidity ^0.8.0;

// Declaração do contrato
contract MeuContrato {
    // Declaração de variáveis de estado globais
    uint256 public meuNumero; // Exemplo de variável de estado
   // atributos privados - só podem ser chamadas de dentro do contrato
    address private dono;   

    // Eventos - usado para notificar clientes externos sobre ações ocorridas dentro do contrato
    event NumeroAlterado(uint256 novoNumero);
    
    event ValorIncrementado(uint256 novoNumero);

    // Modificadores - são usados para alterar o comportamento de funções
    modifier apenasDono() {
        require(msg.sender == dono, "Apenas o dono pode chamar essa função");
        _; // Coloca o código da função aqui
    }

    // Declaração do construtor
    constructor() {
        // Inicializações do contrato
        meuNumero = 0;
        dono = msg.sender; // Quem fez a transação que criou o contrato
    }

    // Funções públicas - acessíveis externamente
    function setNumero(uint256 _novoNumero) public apenasDono {
        meuNumero = _novoNumero;
        emit NumeroAlterado(_novoNumero);
    }

    // Funções de consulta - não alteram o estado do contrato e são gratuitas para chamar
    function getNumero() public view returns (uint256) {
        return meuNumero;
    }

    // Funções internas - só podem ser chamadas de dentro do contrato
    function incrementarNumero(uint256 _valor) internal {
        meuNumero += _valor;
    }
    
   function incrementar(uint256 _valor) public {
   uint256 resultado = _valor + 1; // Variável local 'resultado'
  emit ValorIncrementado(resultado);
}
    
    function getNumeroIncrementa(uint256 _valor) private returns (uint256) {
            meuNumero += _valor;
            return meuNumero;
    }

}
```

Vamos detalhar a estrutura do smart contract, incluindo os principais elementos e conceitos envolvidos.

## 1. Declaração da versão do Solidity:

Em Solidity, `pragma` é uma diretiva de compilação usada para declarar a versão do compilador Solidity que será utilizada para compilar o contrato inteligente. A diretiva `pragma` é usada no início do arquivo Solidity e geralmente é a primeira instrução presente no código. A estrutura básica da diretiva `pragma` é a seguinte:

```solidity
pragma solidity ^0.8.0;
```

Aqui está o que cada parte da diretiva `pragma` significa:

* `pragma solidity`: Indica que estamos usando a linguagem Solidity.
* `^0.8.0`: Define a versão mínima compatível do compilador Solidity. O caractere `^` significa "compatível com", seguido pela versão específica do compilador. Por exemplo, `^0.8.0` indica que o contrato pode ser compilado usando uma versão do compilador Solidity 0.8.0 ou superior, mas não compatível com a versão 0.9.0.

## 2. Declaração do contrato:

A declaração de um smart contract em Solidity envolve a definição de um bloco de código encapsulado por chaves {}, contendo os elementos essenciais para o funcionamento do contrato. Por padrão, os contratos em Solidity são públicos, o que significa que podem ser visualizados e interagidos por qualquer pessoa na rede.

O contrato é declarado usando a palavra-chave `contract`, seguida pelo nome do contrato e, opcionalmente, parâmetros de inicialização.

```solidity
contract MeuContrato {
    // código do contrato vai aqui
}
```

**MeuContrato**: Define o nome do contrato, que deve ser único e seguir regras de nomenclatura específicas do Solidity. ***// código do contrato vai aqui***: Dentro das chaves, serão declaradas as variáveis, funções, eventos e demais elementos que compõem a funcionalidade do contrato. Podemos encontrar :

* Variáveis : Armazenam dados dentro do contrato, podendo ser de diferentes tipos como uint, bool ou address.
* Funções: Definem as ações que o contrato pode realizar, acessíveis a partir de transações externas ou chamadas internas.
* Modificadores: Controlam o acesso e o comportamento das funções, definindo restrições como payable ou nonReentrant.
* Eventos: Emitem sinais para a rede blockchain, notificando sobre eventos importantes como transferências de fundos ou alterações de estado.

## 3. Variáveis de estado:

Variáveis de estado são armazenadas permanentemente no blockchain. No exemplo abaixo, `meuNumero` é uma variável de estado pública, o que significa que seu valor pode ser lido por qualquer pessoa, mas só pode ser alterado por funções dentro do contrato.

```solidity
uint256 public meuNumero;
```

* **Armazenamento permanente** na blockchain.
* **Visibilidade:** `public`, `private` ou `internal`.
* **Tipos de dados:** Diversos, como `uint256`, `bool`, `address` e `string`.
* **Valor inicial:** Definido na declaração ou no construtor.
* **Modificadas** por funções do contrato.

## 4. Eventos:

Eventos são notificações que são emitidas quando certas condições ocorrem no contrato. Eles são úteis para comunicação com clientes externos ou outros contratos.

```solidity
event NumeroAlterado(uint256 novoNumero);
```

* São um mecanismo para registrar e notificar ocorrências importantes em um contrato inteligente.
* Permitem que outros contratos e aplicativos sejam notificados sobre mudanças de estado.
* São declarados com a palavra-chave `event` e podem ter parâmetros.
* A emissão de eventos é feita com a instrução `emit`.

```solidity
function setNumero(uint256 _novoNumero) public apenasDono {
        meuNumero = _novoNumero;
        emit NumeroAlterado(_novoNumero);
}
```

## 5. Modificadores:

Os modificadores são usados para alterar o comportamento das funções. Eles podem ser usados para verificar condições antes de executar uma função, como no exemplo abaixo, onde `apenasDono` garante que apenas o dono do contrato pode chamar a função decorada por esse modificador.

```solidity
modifier apenasDono() {
    require(msg.sender == dono, "Apenas o dono pode chamar essa função");
    _; // Coloca o código da função aqui
}
```

* **Funções sem corpo** que alteram o comportamento de outras funções.
* **Aplicados antes** das funções que desejam modificar.
* **Utilizam `_;`** para indicar onde o código original da função deve ser executado.

```solidity
   function setNumero(uint256 _novoNumero) public apenasDono {
        meuNumero = _novoNumero;
        emit NumeroAlterado(_novoNumero);
    }
```

## 6. Construtor:

O construtor é um tipo especial de função que é executado apenas uma vez durante a criação do contrato. É usado para inicializar variáveis de estado e realizar outras tarefas de configuração.

```solidity
constructor() {
    // Inicializações do contrato
    meuNumero = 0;
    dono = msg.sender; // Quem fez a transação que criou o contrato
}
```

Algumas características Essenciais:

* **Função especial** para inicializar contratos inteligentes.
* **Executada automaticamente** na criação do contrato.
* **Define valores iniciais** das variáveis de estado.
* **Pode ter parâmetros** para personalizar a inicialização.
* **Único por contrato.**

## 7. Funções :

Em um contrato, as unidades de código executáveis são conhecidas como funções. As funções descrevem uma única ação para obter uma tarefa. As funções do Solidity se comportam de modo semelhante às funções em outras linguagens de programação. Ao definir uma função, você tem a seguinte sintaxe:

```solidity
function nome_function(type1 var1, ...) 
[public,external,private,internal]  
[payable|pure|view] [returns (type var, type var ....)] 
{ ... }
```

O escopo das variáveis de estado e funções é controlado pelas seguintes palavras-chave possíveis:&#x20;

**public**  - Todos podem acessar.&#x20;

**external** - Não pode ser acessado internamente, apenas externamente. De funções internas, deve ser chamado com isto-->func\_name().&#x20;

**internal** - somente este contrato e os contratos derivados dele podem acessá-lo.&#x20;

**private** - pode ser acessado apenas a partir deste contrato, contratos herdados de outro não podem acessá-lo.

Pure, view, payable -ditam o comportamento das funções Solidity:&#x20;

**view**: A função NÃO alterará o armazenamento do contrato&#x20;

**pure**: A função NÃO LER as variáveis de armazenamento do contrato (é uma função auxiliar, por exemplo soma dois valores e retorna o resultado)&#x20;

**payable**: A função pode enviar e receber Ethers.

### Exemplos :

**public**

```solidity
function setNumero(uint256 _novoNumero) public apenasDono {
    meuNumero = _novoNumero;
    emit NumeroAlterado(_novoNumero);
}
```

Funções públicas são acessíveis externamente e podem ser chamadas por outros contratos ou usuários. No exemplo acima, `setNumero` é uma função pública que permite ao dono do contrato definir um novo valor para `meuNumero`.

**view**

```solidity
function getNumero() public view returns (uint256) {
    return meuNumero;
}
```

As funções de consulta não alteram o estado do contrato e são gratuitas para chamar. Elas geralmente retornam informações sobre o estado atual do contrato.

**internal**

```solidity
    // Funções internas - só podem ser chamadas de dentro do contrato
function incrementarNumero(uint256 _valor) internal {
     meuNumero += _valor;
}
```

As funções internas só podem ser chamadas de dentro do contrato. Elas são úteis para modularizar o código e reutilizar lógica em várias partes do contrato.

**private**

```solidity
  function getNumeroIncrementa(uint256 _valor) private returns (uint256)   {
            meuNumero += _valor;
            return meuNumero;
 }
```

As funções privadas só podem ser chamadas de dentro do contrato. Elas são úteis para encapsular lógica que não deve ser acessada externamente.

## 8. Variáveis locais:

Declarado dentro de uma função, não armazenado no blockchain.**Variáveis locais** em Solidity são:

* **Declaradas dentro de funções ou blocos**
* **Disponíveis apenas dentro do seu escopo**
* **Armazenadas na memória (não no blockchain)**
* **Excluídas quando o escopo termina**

```solidity
function incrementar(uint256 _valor) public {
  uint256 resultado = _valor + 1; // Variável local 'resultado'
  emit ValorIncrementado(resultado);
}
```

Dominar o Solidity é essencial para construir contratos inteligentes robustos, seguros e eficientes. A jornada de aprendizado em Solidity é contínua: explore recursos, pratique e torne-se um mestre na criação de smart contracts.
