Solidity: crie contratos inteligentes para a blockchain da Ethereum

Lucas Vieira
5 min readFeb 25, 2018

--

Solidity é uma linguagem de programação que permite desenvolver contratos inteligentes para a blockchain da Ethereum. Blockchain, por sua vez, nada mais é que um grande banco de dados distribuído, presente em todos os computadores ao mesmo tempo. Ele contém dados sobre todo o histórico de transações e para que uma nova informação seja gravada ela precisa ser validada pelos computadores (nós) participantes da rede. O principal objetivo da blockchain é a descentralização como medida de segurança estabelecendo assim confiança entre duas ou mais partes, o que por conseguinte evita intermediários. Pretendo falar mais sobre essa tecnologia em um outro post pois neste aqui quero fazer uma introdução aos principais conceitos da linguagem Solidity.

A Ethereum é uma plataforma que facilita a construção de aplicações descentralizadas (Dapps), tenho um outro post falando mais sobre isso, para ler clique aqui. Essa plataforma possui uma máquina virtual chamada EVM (Ethereum Virtual Machine) que executa os contratos. Esses contratos são imutáveis e funcionam exatamente como foram programados sem qualquer possibilidade de censura, fraude ou interferência de terceiros. Sem mais delongas, um contrato simples chamado HelloWorld seria assim:

pragma solidity ^0.4.19;contract HelloWorld {

}

Esse contrato, vazio, obviamente não faz nada. Entretanto o objetivo aqui é aprender as principais características da linguagem. Vamos com calma. A primeira linha indica a versão do programa, isso é necessário para prevenir problemas com futuras versões do compilador, visto que por ser uma tecnologia nova a Ethereum está sempre lançando atualizações.

Variáveis de estado e inteiros

As variáveis de estado (state variables) são permanentemente armazenadas no contrato. Isto significa que elas são escritas na blockchain Ethereum. É como se você estivesse gravando essas variáveis em um banco de dados. Mais à frente veremos que é possível (e as vezes necessário) especificar se queremos salvar uma variável permanentemente ou não.

contract Example {uint numero = 100;}

O tipo uint é um unsigned integer, ou seja, seu valor não pode ser negativo. Também existe um tipo int para inteiros negativos. Em Solidity uint na verdade é uma abreviação para uint256. Um inteiro não negativo de 256 bits. Você também pode declarar uint8, uint16 e uint32.

Operações Matemáticas

Operações matemáticas em Solidity é como na maioria das linguagens:

  • Adição: x + y
  • Subtração: x — y
  • Multiplicação: x * y
  • Divisão: x / y
  • Módulo: x % y

E como no python você pode calcular o exponencial com o operador **:

uint x = 5 ** 2; // 5² = 25

Structs

Um exemplo de struct em Solidity:

struct Pessoa {
uint idade;
string nome;
}

Observe que declarei nome como sendo string. Strings podem ter um tamanho arbitrário, e são por padrão UTF-8. Exemplo:

string bemVindo = “Olá, seja bem-vindo!”;

Arrays

Existem dois tipos de arrays. Os arrays fixos e os dinâmicos:

// Arrays de tamanho 3 e 5:
uint[3] arrayFixo;
string[5] stringArray;
// Um array dinâmico:
uint[] arrayDinâmico;

Você também pode criar um array de uma struct. Exemplo usando a struct Pessoa:

Pessoa[] pessoas; // Array dinâmico, você pode continuar adicionando

Arrays públicos

Você pode criar um array público e a Solidity irá criar automaticamente um método getter para ele.

Pessoa[] public pessoas;

Outros contratos na rede blockchain poderão ler mas não escrever neste array.

Function Declarations

Uma função em Solidity tem uma sintaxe assim:

function soma(uint _num1, uint _num2) {

}

Essa é uma função chamada soma que recebe dois parâmetros uint. Por enquanto o corpo da função está vazio. Há uma convenção de começar o nome do parâmetro da função com um underline (_), para diferenciar eles de variáveis globais. O uso do underline, claro, não é obrigatório.

Essa função seria chamada assim:

soma(2,5);

Em Solidity, as funções por padrão são públicas. Isso significa que qualquer pessoa ou contrato pode chamar a função do seu contrato e executar o código dela. Porém isso nem sempre é desejável e pode deixar seu contrato vulnerável à ataques, por isso é sempre uma boa prática deixar suas funções privadas e só deixá-las públicas quando você quiser.

uint[] nums;function _adicionaNoArray(uint _numero) private {
nums.push(_numero);
}

Isso significa que somente outras funções dentro do contrato poderão chamar essa função para adicionar números no vetor. Como nos nomes dos parâmetros os nomes das função privadas também começam com um underline (_), por convenção apenas.

Retornar valores

Para retornar valores de uma função usa-se a seguinte sintaxe:

string mensagem = “Olá, seja bem-vindo”;function boasVindas() public returns (string) {
return mensagem;
}

Em Solidity na declaração da função contém o tipo a ser retornado (neste caso string).

Modificadores de funções

A função acima não altera nada e nem escreve nada no contrato e por isso deve-se declarar a função como uma view function.

Function boasVindas() public view returns (string) {

}

Também existem as chamadas funções “puras”. Essas função não estão nem sequer acessando nenhum dado. Exemplo:

function _multiplica(uint _a, uint _b) private pure returns (uint) {
return _a * _b;
}

Pode ser difícil se lembrar de quando usar pure ou view, por isso o compilador da Solidity dá um warning quando for preciso utilizar esses modificadores.

Trabalhando com structs e arrays

struct Pessoa {
uint idade;
string nome;
}
Pessoa[] public pessoas;

Com essa struct vamos ver como criar novas pessoas e colocá-las em um array.

// Cria uma nova pessoa
Pessoa lucas = Pessoa(21, “Lucas”);
// adiciona a nova pessoa ao array
pessoas.push(lucas)

Também podemos fazer tudo em uma só linha:

pessoas.push(Pessoa(21, “Lucas”));

É importante ressaltar que array.push() adiciona algo no final do array, assim os elementos ficam na ordem em que são inseridos. Exemplo:

uint[] numeros;numeros.push(1);
numeros.push(2);
numeros.push(3);
// numeros agora é igual a [1, 2, 3]

Keccak256 e Typecasting

A Ethereum tem uma função de hash built in keccak256. Uma função de hash basicamente mapeia um input do tipo string em um número hexadecimal aleatório de 256 bits. Uma pequena alteração na string provoca uma grande mudança no hash. Exemplo:

//6e91ec6b618bb462a4a6ee5aa2cb0e9cf30f7a052bb467b0ba58b8748c00d2e5
keccak256(“aaah”);
//b1f078126895a1424524de5321b339ab00408010b7cf0e6ed451514981e58aa9
keccak256(“aaaah”);

Como pode ver os valores retornados são completamente diferentes.

Typecasting

As vezes é necessário converter uma variável.

uint8 a = 5;
uint b = 6;
// exibe um erro pois a * b retorna um uint e não um uint8
uint8 c = a * b;
// temos que fazer um cast de b para uint8
uint8 c = a * uint8(b);

Eventos

Eventos são uma maneira do seu contrato comunicar ao front-end que alguma coisa aconteceu na blockchain. O código do front-end fica “ouvindo” por um determinado evento e quando ele acontece faz alguma coisa. Exemplo:

// declara o evento
event inteirosAdicionados(uint x, uint y, uint result);
function add(uint _x, uint _y, uint _result) public {
uint _result = _x + _y;
// dispara o evento
inteirosAdicionados(_x, _y, _result);
return result;
}

E então o seu código no front-end teria algo parecido com isso:

SeuContrato.inteirosAdicionados(function (err, res) => {
// faz alguma coisa com o res
})

Esse exemplo do front-end está em javaScript. Existe uma biblioteca do javascript chamada Web3.js que serve para interagir com contratos inteligentes. Em posts futuros quero abordar essa biblioteca, mas por hoje isso é tudo.

Como em qualquer outra linguagem a Solidity tem suas próprias características. Ainda faltou abordar muitos conceitos da linguagem como inheritance, mappings, addresses, mais sobre visibilidade de funções com external e internal, constructor, condicionais e o for loop. por isso vou fazer uma continuação desse artigo. Deixe alguma sugestão nos comentários, se encontrar algum erro ou sentir que faltou alguma coisa, será muito bom complementar este post.

--

--

Lucas Vieira

Computer science student. Currently learning, coding and testing blockchain applications