# Solidity: linguagem de programação para contratos inteligentes

Solidity é utilizado para programar **contratos inteligentes sofisticados para operar na blockchain da Ethereum**. É uma linguagem de programação que oferece uma abordagem interessante que a diferencia das outras linguagens.

## O que é Solidity?

Solidity é uma linguagem de programação de alto nível para criar contratos inteligentes na blockchain Ethereum. Os «contratos inteligentes» são **contratos autoexecutáveis que automatizam a troca de ativos ou fundos entre duas ou mais partes**. Este tipo de contrato não necessita de um intermediário para garantir o seu cumprimento, razão pela qual são especiais.

O código-fonte do Solidity é compilado em bytecode e **inserido na blockchain do Ethereum como um contrato inteligente**. O contrato inteligente pode ser executado por qualquer nó da rede e o seu estado é armazenado na blockchain. Aqui está um exemplo de um contrato simples que simula uma máquina de venda de NFT:

```solidity
pragma Solidity 0.8.7;
contract NFTVendingMachine {
    // Declare state variables
    address public owner;
    mapping (address => uint) public nftBalance;
    // Run on deployment
    constructor() {
        owner = msg.sender;
        nftBalance[address(this)] = 100;
    }
    // Allow the owner to restock the NFT balance
    function restock(uint amount) public {
        require(msg.sender == owner, "Only the owner can restock.");
        nftBalance[address(this)] += amount;
    }
    // Allow anyone to purchase NFTs
    function purchase(uint amount) public payable {
        require(msg.value >= amount * 1 ether, "You must pay at least 1 ETH per NFT");
        require(nftBalance[address(this)] >= amount, "Not enough NFTs in stock to complete this purchase");
        nftBalance[address(this)] -= amount;
        nftBalance[msg.sender] += amount;
    }
}
```

## Em que casos se utiliza Solidity?

O Solidity foi desenvolvido especificamente para **criar aplicações descentralizadas**, DApps (*Distributed Applications*), que são executadas na Ethereum Virtual Machine (EVM). Os contratos inteligentes são ideais para gerir ativos digitais, criar bolsas de valores descentralizadas e implementar sistemas de votação, entre outros aspetos.

### Finanças Descentralizadas (DeFi)

Solidity é usado para desenvolver aplicações DeFi, como **mercados de valores descentralizados, plataformas de empréstimos e financiamentos, mercados de previsão e criptomoedas**. DeFi é um dos casos de uso mais populares da tecnologia blockchain. Solidity tornou-se uma ferramenta indispensável para criar aplicações DeFi na rede Ethereum.

### Tokens não fungíveis

Os tokens não fungíveis (NFT, non-fungible tokens) gozam de grande popularidade desde 2020. Os NFT são determinados ativos digitais armazenados na blockchain. Podem ser **obras de arte digitais, recordações desportivas ou artefactos do setor dos videojogos**. O Solidity é utilizado para criar os contratos inteligentes que suportam os NFT.

### Gestão da cadeia de abastecimento

É possível utilizar Solidity para criar contratos inteligentes com o objetivo de **supervisionar e gerir as cadeias de abastecimento**. Os contratos são utilizados para automatizar diferentes processos da cadeia de abastecimento. Entre eles, encontram-se o acompanhamento dos movimentos de mercadorias, a verificação da autenticidade dos produtos e o processamento dos pagamentos entre as diferentes partes.

### Sistemas de votação

O Solidity pode ser usado para criar contratos inteligentes que **implementam sistemas de votação seguros e transparentes na blockchain**. Os contratos podem ser usados para garantir que os votos sejam contados corretamente e que o processo de votação seja justo e transparente.

## Quais são as vantagens e desvantagens do Solidity?

Em geral, Solidity é uma linguagem de programação poderosa, desenvolvida para criar contratos inteligentes na blockchain Ethereum. No entanto, como toda tecnologia, Solidity oferece vantagens e desvantagens específicas que os programadores devem ter em conta ao criar contratos inteligentes. De qualquer forma, criar contratos inteligentes confiáveis requer um certo nível de **habilidade e atenção**.

A título de exemplo, vamos mostrar um **contrato inteligente que funciona como um buraco negro**: todo o Ether enviado para o contrato é irreversivelmente absorvido, uma vez que não é possível reembolsar o Ether.

```solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.9.0;
// This contract swallows all Ether sent to it
contract Blackhole {
    event Received(address, uint);
    receive() external payable {
            emit Received(msg.sender, msg.value);
    }
}
```

### Vantagens do Solidity

- **Flexibilidade**: Solidity é uma linguagem de programação muito versátil. Pode ser usada para criar diferentes contratos inteligentes com uma grande variedade de casos de uso.
- **Segurança**: Solidity foi desenvolvida precisamente a pensar na segurança. A linguagem inclui características como controlos de acesso, gestão de exceções e mecanismos de falha que ajudam os programadores a escrever contratos seguros.
- **Compatibilidade com Ethereum**: Solidity é atualmente a linguagem de programação por excelência para criar contratos inteligentes na blockchain Ethereum.
- **Comunidade sólida**: Solidity conta com uma grande comunidade de programadores de blockchain. Ou seja, dispõe de inúmeros recursos para aprender e resolver problemas.

### Desvantagens do Solidity

- **Curva de aprendizagem**: Solidity tem uma curva de aprendizagem relativamente alta para programadores que estão a lidar com blockchain e contratos inteligentes pela primeira vez.
- **Imutabilidade**: uma vez que um contrato inteligente é introduzido na blockchain, ele não pode ser modificado, portanto, os programadores devem ser extremamente cuidadosos ao redigi-lo e testá-lo.
- **Ausência de revisão formal**: Solidity não possui ferramentas integradas que revisam o código formalmente, portanto, os desenvolvedores precisam recorrer a ferramentas externas para garantir que seus contratos estejam bem escritos.
- **Ferramentas limitadas**: o ecossistema de ferramentas do Solidity ainda é relativamente pouco desenvolvido. Portanto, pode causar problemas com IDE, estruturas de testes e outras ferramentas de desenvolvimento.

## Como é a sintaxe básica do Solidity?

Solidity é uma **linguagem orientada a objetos, especializada em contratos inteligentes** e influenciada por JavaScript, Python e C++. A sintaxe do Solidity é semelhante à do JavaScript, embora apresente algumas peculiaridades interessantes.

### Variáveis em Solidity

À primeira vista, as variáveis do Solidity parecem funcionar como em outras linguagens semelhantes. No entanto, a maior diferença está no facto de que o ambiente de execução é a Ethereum Virtual Machine (EVM). Todas as **operações na EVM, bem como o armazenamento de dados, custam uma certa quantidade de «gas».** Portanto, ao programar, pode ser necessário ponderar como implementar uma operação da forma mais eficiente possível.

Além das variáveis «normais», o Solidity reconhece **constantes que devem ser definidas na compilação**. As constantes requerem menos gás para serem armazenadas:

```solidity
// Regular variable can be declared without defining
int a;
// Constant needs to be defined at declaration
int constant b = 51;
```

A situação das variáveis `inmutables` é semelhante. Estas consomem menos gás e **não permitem ser modificadas após terem sido atribuídas um valor**. Ao contrário das variáveis `constantes`, é possível atribuir-lhes um valor durante a execução.

### Estruturas de controlo em Solidity

Solidity é uma linguagem de programação imperativa, portanto, suporta as instruções de controlo habituais, por exemplo, **condicionais e loops**. A seguir, mostramos o código para escolher o maior de dois números, `a` ou `b`:

```solidity
int largerNumber = 0;
// If-else statement
if (a > b) {
    largerNumber = a;
} else {
        largerNumber = b;
}
```

O **loop `for` no Solidity** é semelhante à sintaxe em JavaScript ou C++:

```solidity
// Loop 10 times
for (int i = 0; i < 10; i++) {
    // …
}
```

O loop **`while` também segue a mesma estrutura**. Combinamos uma condição de interrupção com uma variável numérica para o contador:

```solidity
bool continueLoop = true;
int counter = 0;
// Loop at most 10 times
while (continueLoop && counter < 10) {
    // …
    counter++;
}
```

### Tipos simples em Solidity

Solidity é uma **linguagem de tipagem estática** e suporta os tipos de variáveis comuns às linguagens de programação. Os tipos de dados mais simples que representam valores individuais são os booleanos, numéricos e strings (cadeias de caracteres), entre outros.

Os booleanos em Solidity podem assumir o valor `true` ou `false`. Podem ser combinados entre si com os **operadores booleanos conhecidos** e utilizados em sentenças `if`:

```solidity
bool paymentReceived = true;
bool itemsStocked = true;
bool continueTransaction = paymentReceived && itemsStocked;
if (continueTransaction) {
    // ...
}
```

O Solidity suporta uma **ampla gama de tipos de números**. No caso dos números inteiros, distingue-se entre números com sinal (`int`) e sem sinal (`uint`) (estes últimos são sempre positivos). Além disso, o valor de um número pode ser representado em incrementos de 8 bits, de `int8` e `int16` a `int265`:

```solidity
uint8 smallNumber = 120;
int8 negativeNumber = -125;
int8 result = smallNumber + negativeNumber;
assert(result == -5)
```

As cadeias de caracteres em Solidity são usadas principalmente para criar mensagens de estado. A linguagem de programação suporta **aspas simples e duplas**, bem como o padrão de caracteres Unicode:

```Solidity
string message = 'Hello World';
string success = unicode"Transfer sent";
```

### Funções em Solidity

Tal como na maioria das linguagens de programação, as **funções são uma parte essencial do Solidity**. As funções são definidas de forma semelhante ao JavaScript, pelo que é necessário especificar cada tipo de argumento. Além disso, utiliza-se a palavra-chave `returns` para indicar o tipo de valor obtido como resposta:

```solidity
// Define a function
function addNumbers(int a, int b) returns (int) {
    return a + b;
}
```

As **chamadas para uma função** são feitas como de costume:

```solidity
// Call the function
int result = addNumbers(2, 3);
```

Curiosamente, **de forma análoga aos argumentos com nome, os valores de retorno também podem ter nome**. Neste caso, basta atribuir as variáveis correspondentes no corpo da função, não sendo necessário introduzir um retorno através de `return`:

```solidity
function divideNumbers(int dividend, int divisor) returns (int quotient) {
    quotient = dividend / divisor;
    // No `return` necessary
}
```

Semelhante às variáveis `constant` ou `immutable`, **as funções no Solidity podem ser marcadas para não alterarem o estado**. Para isso, são utilizadas as palavras-chave `view` e `pure`. Uma função `view` não altera o estado, enquanto uma função `pure` garante também não ler variáveis de estado.

### Contratos inteligentes em Solidity

Além dos tipos habituais, o Solidity possui vários **tipos especializados em contratos inteligentes**. O tipo mais comum é `address`, que atribui endereços Ethereum, onde os endereços `payable` podem receber transferências em Ether. Para isso, os endereços `payable` utilizam os métodos `balance()` e `transfer()`.

```solidity
// Get address of this contract
address mine = address(this);
// Get payable external address
address payable other = payable(0x123);
// Transfer if balances fulfill conditions
if (other.balance < 10 && mine.balance >= 100) {
    other.transfer(10);
}
```

A partir do tipo `address`, surge o tipo `contract` como estrutura essencial da linguagem. **Os contratos equivalem às classes nas linguagens de programação orientadas a objetos**. Eles são responsáveis por agrupar uma coleção de dados de estado e funções e protegê-los do mundo exterior. Os contratos contam com herança múltipla, como em Python ou C++. Os contratos **normalmente começam com uma linha `pragma`** que indica a versão permitida do Solidity, seguida da definição do contrato propriamente dito:

```solidity
// Make sure Solidity version matches
pragma Solidity >=0.7.1 <0.9.0;
// Contract definition
contract Purchase {
    // Public state variables
    address seller;
    address buyer;
    
    // View-function
    function getSeller() external view returns (address) {
        return seller;
    }
}
```

Os contratos inteligentes podem definir **dados de estado e funções**. Tal como em C++ e Java, é possível definir um dos três níveis de acesso em cada caso:

- `public`: é possível aceder à variável a **partir do contrato com permissões de leitura e escrita**. Além disso, é criada automaticamente uma função `view` como getter (capturador) para poder ler a variável a partir do exterior.
- `internal`: a variável está **protegida contra qualquer acesso externo**. É possível acessá-la com direitos de leitura e escrita, tanto a partir do contrato quanto dos contratos herdeiros.
- `private`: é semelhante a `internal`, mas **não é possível aceder à variável a partir dos contratos herdeiros**.

As funções também podem ser classificadas como `external`. Uma função `external` **funciona como parte da interface do contrato** e é utilizada para acesso externo. A função `receive` é uma forma bem conhecida de receber Ether:

```solidity
// Define without `function` keyword
receive() external payable {
    // Handle Ether
}
```

### Modificadores em Solidity

Os modificadores no Solidity permitem-lhe utilizar uma sintaxe mais precisa. Os modificadores funcionam de forma semelhante aos decoradores do Python: tal como os decoradores, os modificadores são utilizados para modificar a **chamada a uma função**. São frequentemente utilizados para verificar se uma condição é cumprida antes de executar uma função:

```solidity
contract Sale {
    uint price;
    address payable owner;
    modifier onlyOwner {
        // Will throw error if called by anyone other than the owner
        require(
            msg.sender == owner,
            "Only owner can call this function."
        );
        // The wrapped function's body is inserted here
        _;
    }
    
    // `onlyOwner` wraps `changePrice`
    function changePrice(uint newPrice) public onlyOwner {
        // We'll only get here if the owner called this function
        price = newPrice;
    }
}
```

### Gestão de transações com Solidity

O Solidity possui uma gestão de transações integrada, permitindo verificar se uma transferência de **Ether foi processada integralmente ou não foi processada de todo**. A linguagem utiliza a palavra-chave `revert`, que provoca o «roll-back» de uma transação. A palavra-chave `error` permite definir os seus próprios códigos de erro:

```solidity
// Custom error definition
error InsufficientPayment(uint256 paid, uint256 required);
// Contract representing a sale
contract Sale {
    uint price;
    // Purchase if enough ether transferred
    function purchase() public payable {
        if (msg.value < price) {
            revert InsufficientPayment(msg.value, price);
        }
        // Complete purchase
    }
}
```

Outro **padrão frequente** é o uso da função `require()`, que pode ser utilizada de forma semelhante à `revert`:

```solidity
// Using `require()` function
if (!condition) revert("Error message");
// Equivalent to
require(condition, "Error message");
```


This is a markdown version of: [https://www.ionos.com/pt-pt/digitalguide/paginas-web/desenvolvimento-web/solididade/](https://www.ionos.com/pt-pt/digitalguide/paginas-web/desenvolvimento-web/solididade/) for AI/LLM consumption.