Como usar a programação do Solidity
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;
}
}solidityPara 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);
}
}solidityVantagens 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;solidityO 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;
}solidityO for loop no Solidity corresponde à sintaxe conhecida do JavaScript ou do C++:
// Loop 10 times
for (int i = 0; i < 10; i++) {
// …
}solidityO 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++;
}solidityTipos 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) {
// ...
}solidityO 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)solidityAs 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";SolidityFunçõ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;
}solidityA 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
}soliditySemelhante 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);
}solidityCom 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;
}
}solidityOs 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, umaviewfunçã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: comointernal, 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
}solidityModificadores 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;
}
}solidityGerenciamento 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
}
}solidityOutro 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
