Tutoriais Técnicos
Introdução
Embora a maioria das pessoas já tenha ouvido falar sobre o desenvolvimento de blockchain e do breve conceito sobre descentralização, a barreira para a entrada no mercado como um desenvolvedor de blockchain tem sido a batalha da maioria das pessoas, o que torna bastante difícil começar. Este artigo irá guiá-lo através das etapas necessárias para se tornar um desenvolvedor de blockchain criando na blockchain Celo.
Pré-requisitos
- Supõe-se que você seja um iniciante absoluto.
- Antes de prosseguir com este artigo, presume-se que você tenha um conhecimento básico do que o desenvolvimento de blockchain envolve.
- Ter algum conhecimento sobre Web2 é uma vantagem para começar a ler este artigo.
Requisitos
- O Remix IDE será usado neste tutorial.
Começando
A blockchain Celo é uma blockchain carbono negativa, compatível com EVM (Máquina Virtual Ethereum) voltada para usuários móveis. A compatibilidade EVM da Celo significa que qualquer contrato inteligente escrito para a blockchain Ethereum pode ser facilmente implantado na Celo. Com essa compatibilidade, as linguagens utilizadas na Ethereum também podem ser utilizadas na blockchain Celo, o que nos levará a explorar e compreender o Solidity (a linguagem mais popular na Ethereum).
O objetivo deste artigo é quebrar a barreira necessária para se iniciar o desenvolvimento de blockchain. É comum ver tutoriais explicando diferentes conceitos sobre a blockchain Celo, mas, na maioria dos casos, os iniciantes geralmente têm dificuldade em escolher qual artigo seguir e, no caso da documentação, na maioria das vezes, parece muito volumoso para iniciantes, daí o motivo deste artigo. Este artigo vinculará os iniciantes ao tutorial necessário para começar, ao mesmo tempo em que explica alguns conceitos básicos, o que, em troca, aumentará sua confiança em voltar à documentação oficial da Celo. No final deste tutorial, vamos escrever um contrato de tarefas simples para fundamentar nosso entendimento sobre os conceitos básicos do Solidity.
Arquitetura Celo
Antes de construir na blockchain Celo, é importante entender a pilha (stack) que compõe a Celo como um todo. A pilha Celo é dividida em três partes:
- Blockchain Celo
- Contrato Principal Celo (Celo Core Contract)
- Aplicações Celo
Começando com a blockchain Celo, é um protocolo criptográfico aberto que possibilita que o aplicativo faça transações e que permite que o contrato inteligente seja executado de forma segura e descentralizada. Compartilhando algumas características semelhantes com a Ethereum, utiliza um mecanismo de consenso de Prova de Participação (Proof-Of-Stake).
O Contrato Principal Celo é um conjunto de contratos inteligentes executados na blockchain Celo.Eles são parte do que compõe o protocolo, são atualizáveis e gerenciados pelo processo de governança descentralizada.
As Aplicações Celo são para os usuários finais desenvolverem na plataforma Celo. Antes que um usuário possa começar a construir na Plataforma Celo, é importante que já tenha algumas configurações necessárias, por exemplo: editor de código (VS Code), carteira compatível com EVM como Metamask ou carteira Celo.
Confira aqui para saber mais sobre a Arquitetura Celo.
Construindo na Celo
Em nossa seção anterior, falamos sobre a Aplicação Celo como parte da arquitetura Celo para usuários finais construírem contratos inteligentes e aplicativos descentralizados na Plataforma Celo. Antes de poder construir na plataforma Celo, é necessário conhecimento em linguagem compatível com EVM. Para este artigo, daremos uma visão geral dos fundamentos do Solidity.
Solidity é uma linguagem orientada a objetos, de alto nível e estaticamente tipada, para implementação de contratos inteligentes. Os contratos inteligentes são programas autoexecutáveis baseados em lógica condicionada. Aqui está um exemplo de contrato inteligente Solidity “Hello World” que você pode copiar e colar no seu IDE Remix, criar um arquivo em seu IDE Remix e colar o código abaixo.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract HelloWorld {
string public greet = "Hello World!";
}
Você criou com sucesso seu primeiro programa de contrato inteligente em Solidity. Antes de prosseguirmos, quero que você tome nota dos comentários no Solidity. Os comentário no Solidity podem ser declarados com “//” e “/* /”. Qualquer texto após // é tratado como um comentário, e qualquer texto entre os caracteres / e */ é tratado como um comentário. Essas declarações são ignoradas pela compilação do Solidity. É usado para explicar seu código.
Programas escritos na Celo e outras blockchains são chamados de “contrato”, então usarei a palavra contrato até o final deste tutorial.
Análise do Solidity
O Solidity, conforme mencionado acima, é uma linguagem estaticamente tipada, o que significa que os tipos de variáveis são declarados explicitamente e determinados em tempo de compilação, ao contrário da linguagem dinamicamente tipada, que realiza verificação de tipo em tempo de execução. Como a maioria das pessoas aprende através de exemplos, observando nosso contrato HelloWord acima, a variável greet é atribuída a um tipo de dados string, o que garante que greet aceite apenas valores de string. Nesse caso, alterar “Hello World!” para 34 lançará um TypeError:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract HelloWorld {
string public greet = 34; // Isto lançará um TypeError indicando que o tipo Type int_const 34 não é implicitamente convertível para o tipo string esperado.
}
O erro acima afirma que é impossível atribuir um número inteiro a uma variável string.
Tipos de Dados do Solidity
É importante conhecer os tipos disponíveis no Solidity para saber quais declarar para um caso de uso de variável específico. Esta seção nos guiará por todos os tipos de dados do Solidity com um exemplo adequado para compreender como o tipo pode ser incorporado em nosso contrato. Os tipos de dados do Solidity que temos são:
Boolean: este é um tipo de dados usado para declarar variáveis que aceitam verdadeiro ou falso, com operadores lógicos! (not), && (and), || (or), == (equal) e! = (not equal) como um valor.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract BoolPractice {
bool greeted = true;
}
Este código acima atribuiu true (verdadeiro) à variável greeted. Como você pode ver, isso é diferente do que temos com o tipo de dados string em nossa seção anterior, você pode estar preocupado com o fato de “public” ou “público” (visibilidade da função) não ser utilizado aqui, mas não tem nada a ver com a declaração e discutiremos sobre isso mais adiante neste tutorial.
Integer (int, uint): o tipo de dados inteiro (integer) é dividido em “inteiro com sinal” e “inteiro sem sinal”. O inteiro com sinal (int) pode ser declarado usando int8 até int256 com incremento de 8 bits, ou seja, int8, int16, int24, int32… até int256. Você pode escolher qual usar com base no valor que deseja armazenar. Aqui está um exemplo mostrando cada declaração com sua capacidade.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract IntegerPractice {
int8 storeInt8 = -24; // Isto pode pegar inteiros de -2^(8-1) to 2^(8-1)-1. Isso significa, inteiros de -128 a 127
int16 storeInt16 = 2000; // Isto pode pegar inteiros de -2^(16-1) to 2^(16-1)-1. Isso significa, inteiros de -32768 a 32767
}
Isso vai até o int256.
Isso também é verdadeiro para inteiros sem sinal (uint). O uint não aceita nenhum número inteiro negativo, ou seja,só aceita valores de zero até sua declaração máxima. Aqui está um exemplo mostrando cada declaração com sua capacidade.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract IntegerPractice {
uint8 storeUint8 = 70; // Isto pode pegar números inteiros de 0 a (2^8)-1,ou seja, 0 a 255.
uint16 storeUint16 = 5000; // Isto pode pegar números inteiros de 0 a (2^16)-1, ou seja, 0 a 65535.
}
E isso continua até uint256, pegando números inteiros de 0 a (2^256)-1.
Address: este tipo de dado é utilizado para declarar variáveis que aceitam apenas endereços Celo como valor.
Enum: enum é um tipo definido pelo usuário para enumerar valores discretos, bastante semelhante ao TypeScript Enum, para aqueles familiarizados com ele. Você pode ver isso como uma alternativa ao uso extensivo do booleano. Por exemplo:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract EnumPractice {
// Numa situação em que precisamos selecionar entre muitas opções para além do booleano _true_ ou _false_
// podemos criar um enum para resolver isso em vez de criar uma lista extensa de booleanos.
// Digamos que queremos selecionar uma das opções "success, pending, reject" (sucesso, pendente, rejeitado).
// Fazer isso com um booleano pode ser computacionalmente caro, ao invés disso podemos criar um enum.
// declaração de enum
enum Status {
success,
pending,
reject
}
// Podemos prosseguir para usar nossa declaração
Status myStatus = Status.pending;
}
Com o exemplo acima, após termos declarado nosso enum, a declaração do enum agora é vista como um tipo definido pelo usuário, ou seja, usando “Status” como um tipo. O mesmo padrão é aplicado para struct.
Struct: embora enum seja usado para enumerar valores discretos, struct é um tipo definido pelo usuário para agrupar diferentes variáveis. Por exemplo:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
contract StructPractice {
// declaração de struct
struct UserDetails {
string name;
uint256 age;
string place;
}
// usamos nossa declaração
UserDetails myDetails = UserDetails("kayzee", 9, "Metaverse");
}
No final deste tutorial, definitivamente incorporaremos a maioria desses tipos de dados do Solidity em nossa prática de contrato de votação para melhor compreensão, então não se preocupe muito.
Mapping: mapeamento (mapping) é um tipo de dados do Solidity que armazena dados como pares de chave-valor, em que a chave pode ser qualquer um dos tipos de dados incorporados, excluindo os tipos de dados de referência (reference) (os tipos de dados Reference e Value são explicados aqui).
Você pode considerar o mapeamento como uma “chave do carro” para o próprio “carro”. Com a chave do carro, você pode acessar o carro e fazer outras coisas com ele. (Penso que esse é o exemplo mais simples de como o mapeamento funciona, mas não vale a pena pensar demais.)
String: string é um tipo de dados para declarar variáveis do tipo string. Lembre-se de como nosso “Hello World!” está sendo declarado.
Array de bytes (fixo, dinâmico): bytes de tamanho fixo do array podem ser declarados com bytes1 até bytes32. bytes(n) significa que ele só pode receber n bytes de valor, ou seja, bytes1 só pode receber 1 byte de valor e assim por diante. O array de bytes dinâmico, por outro lado, pode receber qualquer valor de bytes sem limitação devido ao seu tipo. Isso nos levará a entender os tipos de Reference e Value.
Tipos Reference e Value do Solidity
No Solidity, os tipos de dados podem ser do tipo valor (value) ou do tipo referência (reference). Começando pela definição, as variáveis do tipo valor armazenam seus próprios dados, alguns dos quais são booleans, integers, address, enums, enquanto as do tipo referência, por outro lado, armazenam a localização dos dados (ou seja, fazem referência à memória ou ao local de armazenamento dos dados), sendo responsáveis por estruturas de dados complicadas, como arrays, mapping, struct, strings. Compreender os tipos referência e valor ajudará você a saber qual deles usar quando necessário. O uso do tipo de referência dentro de uma variável local (ou seja, dentro de uma função) deve ser acompanhada de um ponteiro.
Visibilidade
Embora isso seja básico, é importante combiná-lo com visibilidade para não ficarmos confusos quando começarmos a trabalhar em nosso contrato inteligente.
Em Solidity, podemos controlar quem tem acesso às funções e variáveis de estado no seu contrato e como interagem com elas, esse conceito é conhecido como Visibilidade.
A visibilidade de uma função pode ser definida como externa, pública, interna ou privada, enquanto as variáveis de estado (variáveis declaradas fora de uma função) só podem ser públicas, internas ou privadas, a palavra-chave externa não é aplicável a variáveis de estado. As variáveis de estado são internas por padrão.
Visibilidade externa: quando utilizada em uma função, a função só pode ser chamada de fora do contrato em que está declarada.
Visibilidade pública: funções e variáveis de estado declaradas com visibilidade pública podem ser acessíveis dentro e fora do contrato. Quando a visibilidade não é especificada para funções, a visibilidade padrão é pública.
Visibilidade interna: funções e variáveis internas só são acessíveis dentro do contrato em que são declaradas, embora possam ser acessadas a partir de contrato derivado. A referência à herança de contrato será feita no final deste tutorial.
Visibilidade privada: as funções declaradas com palavras-chave privadas só são acessíveis dentro do contrato em que são declaradas.
Prática de Código
Depois de percorrer a abordagem teórica, é importante trabalharmos em alguma prática para colocar nosso aprendizado em uso. Nosso contrato será o mais básico possível para melhor entendimento de tudo o que discutimos.
Para a prática de código usaremos o Remix IDE. O Remix IDE é um IDE online para desenvolvimento, implantação, depuração e teste de contratos inteligentes compatíveis com EVM.
Aqui está um link para o Remix - https://remix.ethereum.org/
Você deve ter algo como o que está abaixo:
Vamos trabalhar em um contrato inteligente de tarefas simples, um contrato inteligente onde as pessoas podem criar, ler, atualizar e excluir sua lista de tarefas. Clique com o botão direito na pasta do contrato no Remix IDE e crie um arquivo todo.sol, siga com o código abaixo e pratique.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18; // versão do compilador solidity que estamos usando
// Este é o ponto de partida do nosso contrato _Todo_
contract Todo {
// Mapping é usado para alinhar os criadores do _Todo_ com a lista de tarefas.
mapping(address => string[]) _todoDetails;
// Enquanto explicava, eu mencionei sobre o uso de um ponteiro junto com a declaração de tipo de dados de referência na variável local
// Um exemplo disso é o que temos em nossa declaração do parâmetro _addTodo_.
function addTodo(string memory _todo) public {
_todoDetails[msg.sender].push(_todo); // msg.sender é uma variável global. É o endereço que inicia a chamada de função (endereço do usuário)
}
// Esta função pode ser usada para atualizar o _Todo_ ao indicar o número do índice que _Todo_ pretende modificar
function updateTodo(uint256 index, string memory _todo) public {
_todoDetails[msg.sender][index] = _todo;
// o mapeamento pode ser acessado através de: _variablename[keyType]_. Isso lhe dará acesso ao valor
// tal qual o utilizamos acima.
}
// Esta função nos dá acessibilidade para ver nosso _Todo_ criado.
// A visibilidade externa é usada aqui, uma vez que só estamos chamando-a fora do contrato.
function checkTodo() external view returns(string[] memory){
return _todoDetails[msg.sender];
}
// Isto ajudará o usuário a excluir o seu _Todo_ quando necessário.
function deleteTodo() public {
uint256 getLength = _todoDetails[msg.sender].length;
for(uint256 i = 0; i < getLength; i++){
_todoDetails[msg.sender].pop();
}
}
}
Embora a implementação seja básica, pode ser lógica para iniciantes. Entender o código acima irá abri-lo a diferentes implementações combinadas com as práticas que explicamos ao falar sobre tipos de dados.
Guia Adicional
Confira o link abaixo para obter mais conhecimento sobre Celo e Solidity. Seguir o link passo a passo impulsionará sua jornada para se tornar um desenvolvedor profissional de blockchain construindo na blockchain Celo.
Go through this tutorial to understand the basics of Solidity 1
Solidity smart contract developer pathway
Conclusão
Este artigo foi criado para ser breve e ajudar um iniciante absoluto a quebrar a barreira necessária para começar a desenvolver na Celo. É aconselhável que você verifique o link externo fornecido neste artigo, qualquer possível problema encontrado pode ser resolvido.
Próximos passos
Depois de ler este artigo, acredito que você ganhará a confiança necessária para prosseguir com outro artigo relacionado à Celo. Aconselho você a se familiarizar com a documentação oficial da Celo e alguns tutoriais intermediários na Celo Academy.
Sobre o autor
Kazeem Olaniyi
Kazeem é um desenvolvedor de Blockchain que trabalha tanto no desenvolvimento de Front-end quanto de Contratos Inteligentes e que está interessado em resolver qualquer problema relacionado a blockchain que surja, o que o levou a ter um grande número de contribuições para diferentes organizações. Conecte-se comigo no LinkedIn: Kazeem Olaniyi.
Este artigo foi escrito por Kazeem Olaniyi e traduzido por Isabela Curado Nehme. Seu original pode ser lido aqui.
Latest comments (0)