# Contratos Atualizáveis

Embora os contratos inteligentes sejam projetados para serem imutáveis, muitas vezes é necessário realizar uma atualização de um contrato inteligente.&#x20;

O desenvolvedor pode precisar corrigir um bug crítico ou introduzir um novo recurso.&#x20;

Para esse tipo de cenário, o ink! possui diferentes estratégias de atualização.

* [Encaminhamento por Proxy](https://use.ink/basics/upgradeable-contracts#proxy-forwarding)
  * [Propriedades](https://use.ink/basics/upgradeable-contracts#properties)
* [Substituindo o Código do Contrato com](https://use.ink/basics/upgradeable-contracts/#replacing-contract-code-with-set_code_hash) [`set_code_hash()`](https://use.ink/basics/upgradeable-contracts#replacing-contract-code-with-set_code_hash)
  * [Propriedades](https://use.ink/basics/upgradeable-contracts#properties-1)
  * [Compatibilidade de Armazenamento](https://use.ink/basics/upgradeable-contracts#storage-compatibility)
  * [Uma pequena observação sobre o determinismo dos endereços de contrato](https://use.ink/basics/upgradeable-contracts#a-little-note-on-the-determinism-of-contract-addresses)
* [Exemplos](https://use.ink/basics/upgradeable-contracts#examples)

### Encaminhamento por Proxy <a href="#proxy-forwarding" id="proxy-forwarding"></a>

Este método depende da capacidade dos contratos de encaminhar chamadas para outros contratos.

#### Propiedades[​](https://use.ink/basics/upgradeable-contracts#properties) <a href="#properties" id="properties"></a>

* Encaminha qualquer chamada que não corresponda a um seletor próprio para outro contrato.
* O outro contrato precisa estar implantado na cadeia on-chain.
* O estado é armazenado no armazenamento do contrato para o qual as chamadas são encaminhadas.

```rust
User ---- tx ---> Proxy ----------> Implementation_v0
                     |
                      ------------> Implementation_v1
                     |
                      ------------> Implementation_v2
```

Nosso contrato de proxy terá esses 2 campos de armazenamento:

```rust
#[ink(storage)]
pub struct Proxy {
    /// The `AccountId` of a contract where any call that does not match a
    /// selector of this contract is forwarded to.
    forward_to: AccountId,
    /// The `AccountId` of a privileged account that can update the
    /// forwarding address. This address is set to the account that
    /// instantiated this contract.
    admin: AccountId,
}
```

Então, precisamos de uma maneira de alterar o endereço de um contrato para o qual encaminhamos as chamadas e o seletor de mensagem real para encaminhar a chamada:

```rust
impl Proxy {
    /// Changes the `AccountId` of the contract where any call that does
    /// not match a selector of this contract is forwarded to.
    #[ink(message)]
    pub fn change_forward_address(&mut self, new_address: AccountId) {
        assert_eq!(
            self.env().caller(),
            self.admin,
            "caller {:?} does not have sufficient permissions, only {:?} does",
            self.env().caller(),
            self.admin,
        );
        self.forward_to = new_address;
    }

    /// Fallback message for a contract call that doesn't match any
    /// of the other message selectors.
    ///
    /// # Note:
    ///
    /// - We allow payable messages here and would forward any optionally supplied
    ///   value as well.
    /// - If the self receiver were `forward(&mut self)` here, this would not
    ///   have any effect whatsoever on the contract we forward to.
    #[ink(message, payable, selector = _)]
    pub fn forward(&self) -> u32 {
        ink::env::call::build_call::<ink::env::DefaultEnvironment>()
            .call_type(
                Call::new()
                    .callee(self.forward_to)
                    .transferred_value(self.env().transferred_value())
                    .gas_limit(0),
            )
            .call_flags(
                ink::env::CallFlags::default()
                    .set_forward_input(true)
                    .set_tail_call(true),
            )
            .fire()
            .unwrap_or_else(|err| {
                panic!(
                    "cross-contract call to {:?} failed due to {:?}",
                    self.forward_to, err
                )
            });
        unreachable!(
            "the forwarded call will never return since `tail_call` was set"
        );
    }
}
```

<mark style="color:purple;">DICA: Dê uma olhada no padrão de seletor no atributo macro: ao declarar</mark> <mark style="color:purple;"></mark><mark style="color:purple;">`selector = _`</mark><mark style="color:purple;">, especificamos que todas as outras mensagens devem ser tratadas por este seletor de mensagem.</mark>

Usando esse padrão, você pode introduzir outras mensagens em seu contrato de proxy. Todas as mensagens que não forem correspondidas no contrato de proxy serão encaminhadas para o endereço de contrato especificado.

### Substituindo o Código do Contrato por `set_code_hash()`[​](https://use.ink/basics/upgradeable-contracts#replacing-contract-code-with-set_code_hash) <a href="#replacing-contract-code-with-set_code_hash" id="replacing-contract-code-with-set_code_hash"></a>

Seguindo a filosofia de atualização da [runtime da Lunes](https://docs.substrate.io/maintain/runtime-upgrades/), o ink! também oferece uma maneira fácil de atualizar o código do seu contrato por meio da função especial [`set_code_hash()`](https://paritytech.github.io/ink/ink_env/fn.set_code_hash.html).

Seguindo a filosofia de atualização de [tempo de execução do Substrate](https://docs.substrate.io/maintain/runtime-upgrades/) que é a mesma da Lunes, o ink! também oferece uma maneira fácil de atualizar o código do seu contrato por meio da função especial [`set_code_hash()`](https://paritytech.github.io/ink/ink_env/fn.set_code_hash.html).

#### Propriedades[​](https://use.ink/basics/upgradeable-contracts#properties-1) <a href="#properties-1" id="properties-1"></a>

* Atualiza o código do contrato usando `set_code_hash()`. Isso efetivamente substitui o código que é executado para o endereço do contrato.
* O outro contrato precisa estar implantado na cadeia on-chain.
* O estado é armazenado no armazenamento do contrato originalmente instanciado.

Basta adicionar a seguinte função ao contrato que você deseja atualizar no futuro.

```rust
/// Modifies the code which is used to execute calls to this contract address (`AccountId`).
///
/// We use this to upgrade the contract logic. We don't do any authorization here, any caller
/// can execute this method. In a production contract you would do some authorization here.
#[ink(message)]
pub fn set_code(&mut self, code_hash: [u8; 32]) {
    ink::env::set_code_hash(&code_hash).unwrap_or_else(|err| {
        panic!(
            "Failed to `set_code_hash` to {:?} due to {:?}",
            code_hash, err
        )
    });
    ink::env::debug_println!("Switched code hash to {:?}.", code_hash);
}
```

#### Compatibilidade de Armazenamento[​](https://use.ink/basics/upgradeable-contracts#storage-compatibility) <a href="#storage-compatibility" id="storage-compatibility"></a>

É responsabilidade do desenvolvedor garantir que o armazenamento do novo contrato seja compatível com o armazenamento do contrato que está sendo substituído.

<mark style="color:purple;">CUIDADO: Você não deve alterar a ordem em que as variáveis de estado do contrato são declaradas, nem seu tipo!</mark>&#x20;

<mark style="color:purple;">Violar essa restrição não impedirá uma compilação bem-sucedida, mas resultará</mark> <mark style="color:purple;"></mark><mark style="color:purple;">**na mistura de valores**</mark> <mark style="color:purple;"></mark><mark style="color:purple;">ou</mark> <mark style="color:purple;"></mark><mark style="color:purple;">**na falha ao ler o armazenamento corretamente**</mark><mark style="color:purple;">. Isso pode resultar em erros graves na aplicação que utiliza o contrato.</mark>

Se o armazenamento do seu contrato parece assim:

```rust
#[ink(storage)]
pub struct YourContract {
    x: u32,
    y: bool,
}
```

Os procedimentos listados abaixo tornarão o contrato **inválido**

Alterando a ordem das variáveis:

```rust
#[ink(storage)]
pub struct YourContract {
    y: bool,
    x: u32,
}
```

Removendo uma variável existente:

```rust
#[ink(storage)]
pub struct YourContract {
    x: u32,
}
```

Alterando o tipo de uma variável:

```rust
#[ink(storage)]
pub struct YourContract {
    x: u64,
    y: bool,
}
```

Introduzindo uma nova variável antes de qualquer uma das existentes:

```rust
#[ink(storage)]
pub struct YourContract {
    z: Vec<u32>,
    x: u32,
    y: bool,
}
```

#### Uma pequena observação sobre a determinismo dos endereços de contrato.[​](https://use.ink/basics/upgradeable-contracts#a-little-note-on-the-determinism-of-contract-addresses) <a href="#a-little-note-on-the-determinism-of-contract-addresses" id="a-little-note-on-the-determinism-of-contract-addresses"></a>

<mark style="color:purple;">NOTA: Se o seu contrato utiliza essa abordagem, não é mais válido assumir que um endereço de contrato identifica um hash de código específico. Consulte a issue para obter mais detalhes.</mark>

### Exemplos[​](https://use.ink/basics/upgradeable-contracts#examples) <a href="#examples" id="examples"></a>

Exemplos de contratos atualizáveis podem ser encontrados no [repositório do ink!](https://github.com/paritytech/ink-examples/tree/main/upgradeable-contracts).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lunes-labs.gitbook.io/dao-lunes-labs-pt/developers/para-desenvolvedores/smart-contract-ink-4.x/fundamentos/contratos-atualizaveis.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
