O Solidity é usado para criar contratos inteligentes complexos projetados para operar no Ethereum blockchain**. Essa linguagem apresenta estratégias exclusivas que a diferenciam de outras linguagens de programação.

O que é Solidity?

Solidity é uma linguagem de programação de alto nível para a criação de contratos inteligentes na blockchain da Ethereum. Os contratos inteligentes são contratos autoexecutáveis que automatizam a troca de ativos entre as partes. O que há de especial neles é que não são necessários intermediários para garantir a conformidade com o contrato inteligente.

Solidity source code é compilado em bytecode e implantado no blockchain da Ethereum como um contrato inteligente. Uma vez concluído, o contrato inteligente pode ser executado por qualquer nó da rede, e o estado é armazenado no blockchain. Mostramos um exemplo de um contrato simples que modela uma máquina de venda automática de NFT:

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;
    }
}
solidity

Para quais aplicativos o Solidity é adequado?

O Solidity foi projetado especificamente para criar aplicativos distribuídos ou DApps executados na Máquina Virtual Ethereum (EVM). Os contratos inteligentes são adequados para gerenciar ativos digitais, criar trocas descentralizadas e implementar sistemas de votação, entre outras coisas.

Finanças descentralizadas (DeFi)

O Solidity está sendo usado para desenvolver aplicativos DeFi, tais como câmbios descentralizados, plataformas de crédito e empréstimo, mercados de previsão e cryptocurrencies. O DeFi se tornou um dos casos de uso mais populares da tecnologia blockchain. Nesse processo, o Solidity se tornou uma ferramenta indispensável para a criação de aplicativos DeFi na rede Ethereum.

Tokens não fungíveis

O non-fungible token (NFT), tem desfrutado de grande popularidade desde a década de 2020. Os NFTs são ativos digitais exclusivos armazenados no blockchain. Eles podem ser obras de arte digital, memorabilia esportiva ou artefatos do setor de jogos. O Solidity é usado para criar os contratos inteligentes que alimentam os NFTs.

Gerenciamento da cadeia de entrega

O Solidity pode ser usado para criar contratos inteligentes para monitorar e gerenciar cadeias de suprimentos. Os contratos são usados para automatizar vários processos da cadeia de suprimentos. Isso inclui o rastreamento da movimentação de mercadorias, a verificação da autenticidade dos produtos e o processamento de pagamentos entre as partes.

Sistemas de reconciliação

O Solidity pode ser usado para criar contratos inteligentes que implementam sistemas de votação seguros e transparentes no 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 os prós e os contras do Solidity?

Embora a Solidity seja uma linguagem poderosa para a criação de contratos inteligentes no blockchain da Ethereum, ela tem suas vantagens e desvantagens específicas que os desenvolvedores devem considerar ao desenvolver contratos inteligentes. No entanto, a criação de contratos inteligentes seguros exige um nível específico de proficiência e cautela.

Como ilustração, abaixo está um contrato inteligente que funciona como um buraco negro. Qualquer Ether enviado para o contrato é consumido permanentemente, sem possibilidade de recuperar o Ether ou fazer um pagamento:

// 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);
    }
}
solidity

Vantagens da Solidez

  • Flexibilidade: o Solidity é uma linguagem versátil. Ela pode ser usada para desenvolver diferentes contratos inteligentes com uma variedade de casos de uso.
  • Segurança: o Solidity foi criado com foco na segurança, incorporando características como controles de acesso, tratamento de exceções e mecanismos de falha para ajudar os desenvolvedores a criar contratos seguros.
  • Compatibilidade com Ethereum: Atualmente, a Solidity é a linguagem preferida para a produção de contratos inteligentes no blockchain da Ethereum.
  • Comunidade distinta: Uma grande comunidade de desenvolvedores de blockchain trabalha com o Solidity, o que resulta em uma infinidade de recursos para aprendizado e solução de problemas.

Desvantagens do Solidity

  • Curva de aprendizado: Para os desenvolvedores que são novos no desenvolvimento de blockchain e contratos inteligentes, o Solidity tem uma curva de aprendizado relativamente acentuada.
  • Unchangeability: Depois que um contrato inteligente é implantado no blockchain, ele não pode mais ser modificado. Portanto, os desenvolvedores precisam ser extremamente cuidadosos ao escrever e testar.
  • Falta de verificação formal: o Solidity não tem ferramentas integradas para revisão formal de código. Isso exige que os desenvolvedores utilizem ferramentas externas para garantir a precisão de seus contratos.
  • Ferramentas limitadas: o ecossistema de ferramentas do Solidity ainda está em seus estágios iniciais, o que pode resultar em problemas com ambientes de desenvolvimento integrado (IDEs), estruturas de teste e outras ferramentas de desenvolvimento.

Qual é a sintaxe básica do Solidity?

O Solidity é uma linguagem de programação orientada a objetos projetada para contratos inteligentes. Ela se inspira em JavaScript, Python e C++. A sintaxe da linguagem é semelhante à do JavaScript, embora com algumas idiossincrasias intrigantes.

Variáveis no Solidity

À primeira vista, o manuseio de variáveis do Solidity pode parecer semelhante ao de outras linguagens de programação. No entanto, uma distinção fundamental surge do fato de que a Máquina Virtual Ethereum (EVM) serve como ambiente de execução. Todas as operações no EVM, inclusive o armazenamento de dados, incorrem em uma certa quantidade de custo de “gás”. Consequentemente, durante a programação, é preciso avaliar a eficiência de uma operação e determinar como ela pode ser implementada da forma mais eficiente possível.

Além das variáveis regulares, o Solidity tem constantes, que devem ser definidas durante a compilação. As constantes requerem menos gás para armazenamento:

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

O mesmo se aplica às immutable variáveis, pois elas exigem menos gás e não podem ser alteradas após a atribuição. Ao contrário das constant variáveis, a atribuição de variáveis imutáveis pode ser feita em tempo de execução.

Declarações de controle no Solidity

Como uma linguagem de programação imperativa, o Solidity oferece suporte a instruções de controle familiares, como branches e loops. Mostramos o código para selecionar o maior de dois números, a e b:

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

O for loop no Solidity corresponde à sintaxe conhecida do JavaScript ou do C++:

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

O while loop também funciona normalmente. Combinamos uma condição de encerramento com uma variável de contador numérico:

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

Tipos simples no Solidity

O Solidity é uma linguagem de tipagem estática e suporta os tipos comumente encontrados em linguagens de programação. Os tipos simples que representam valores únicos incluem booleanos, números e strings.

Os booleanos no Solidity mapeiam os valores true e false. Eles podem ser vinculados usando os operadores booleanos conhecidos e usados em if declarações:

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

O Solidity suporta uma ampla gama de tipos numéricos. Os números inteiros podem ser diferenciados entre números assinados (int) e números não assinados (uint) , sendo que o último só pode ser positivo. Além disso, o intervalo de um número pode ser especificado em etapas de 8 bits, de int8 via int16 até int265:

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

As strings são usadas no Solidity principalmente para gerar mensagens de status. A linguagem suporta aspas simples e duplas , bem como caracteres Unicode:

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

Funções no Solidity

As funções são um aspecto fundamental do Solidity, como na maioria das linguagens de programação. A definição de uma função é semelhante à do JavaScript, em que os tipos de argumentos devem ser explicitamente especificados. Além disso, uma palavra-chave returns é utilizada para indicar os tipos de valores.

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

A chamada de uma função é feita como de costume:

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

É interessante notar que, analogamente aos argumentos nomeados, os valores de retorno no Solidity também podem ser nomeados. Nessa situação, a atribuição das variáveis correspondentes no corpo da função é suficiente, e um retorno explícito via return é desnecessário:

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

Semelhante a constant ou immutable variáveis, no Solidity as funções podem ser marcadas como não modificadoras de estado. As palavras-chave view e pure são usadas para essa finalidade. Uma view função não altera o estado, enquanto uma pure função garante adicionalmente que não lerá as variáveis de estado.

Contratos inteligentes no Solidity

Além dos tipos padrão, o Solidity conhece um punhado de tipos especializados em contratos inteligentes. O tipo básico é address e mapeia endereços Ethereum. Os endereços que são payable podem receber transferências em Ether. Para essa finalidade, payable os endereços fornecem balance() e transfer() métodos.

// 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);
}
solidity

Com base no address tipo, o contract tipo existe como uma construção central da linguagem. Os contratos correspondem aproximadamente às classes em linguagens de programação orientadas a objetos. Assim, os contratos agrupam dados e funções de estado e os protegem do mundo externo. Os contratos oferecem suporte à herança múltipla, como é conhecido em Python ou C++.

Os contratos geralmente começam com uma pragma linha especificando a versão permitida do Solidity, seguida pela definição real:

// 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;
    }
}
solidity

Os contratos inteligentes podem definir dados e funções de estado. Como é sabido em C++ e Java, um dos três níveis de acesso pode ser definido em cada caso:

  • public: A variável pode ser acessada pela leitura e gravação de dentro do contrato. Além disso, uma view função é gerada automaticamente como um getter para acesso de leitura externa.
  • internal: a variável está protegida do acesso externo. O acesso de leitura e gravação é possível de dentro do contrato, bem como de contratos herdados.
  • private: como internal, mas não há acesso de contratos herdados

As funções podem ainda ser caracterizadas como external. Uma external função atua como parte da interface do contrato e é usada para acesso externo. A receive função para receber éter é um exemplo bem conhecido:

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

Modificadores no Solidity

O Solidity tem uma construção de linguagem intrigante na forma de modificadores, que se assemelham aos decoradores do Python. Assim como no Python, os modificadores no Solidity são utilizados para alterar a invocação de uma função. Elas são frequentemente empregadas para garantir que uma condição específica seja atendida antes da execução de uma função:

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;
    }
}
solidity

Gerenciamento de transações com o Solidity

O Solidity tem um gerenciamento de transações integrado. Ele pode ser usado para garantir que uma transferência de éter seja completamente liquidada ou não seja liquidada. A linguagem entende a revert palavra-chave, que aciona uma “reversão” de uma transação. Com a palavra-chave error , você pode definir seus próprios códigos de erro:

// 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
    }
}
solidity

Outro padrão encontrado com frequência é o uso da require() função. Ela pode ser usada de forma análoga a revert:

// Using `require()` function
if (!condition) revert("Error message");
// Equivalent to
require(condition, "Error message");
solidity
Este artigo foi útil?
Ir para o menu principal