Tu primer contrato inteligente con Solidity

domingo, 2 de enero de 2022

En este tutorial vamos a aprender como crear tu primer contrato inteligente, será muy sencillo. Este contrato se encargara simplemente de guardar mensajes y mostrarlos por la consola.

  1. Paso 1: Crear un entorno de desarrollo

Primero vamos a crear una carpeta, abre tu terminal de comandos y escribe el nombre del proyecto, puede ser el nombre que tu quieras, en nuestro caso lo dejaremos como mi-primer-contrato-inteligente:

mkdir mi-primer-contrato-inteligente

Nos moveremos dentro de esta carpeta:

cd mi-primer-contrato

Una vez dentro de la carpeta iniciaremos un archivo de configuración del proyecto:

npm init -y

Finalmente, sin salir de la carpeta, instalaremos hardhat:

npm install --save-dev hardhat

Hardhat se encargara de darnos un entorno de pruebas, creando una red loca de Ethereum, así no gastaremos ETHER del que cuesta haciendo pruebas.

Una vez este instalado hardhat vamos a iniciar un nuevo proyecto con la siguiente línea:

npx hardhat

A continuación se nos preguntará que proyecto queremos iniciar, en nuestro caso será el básico (Create a basic sample project). Después de esto aceptamos todo, como con los términos y condiciones de uso de cualquier software, así tendremos la estructura básica para comenzar a trabajar.

Finalmente, ejecutamos npx hardhat accounts para que nos muestre una lista de direcciones de carteras para hacer las pruebas.

Si tenemos instalado VSCODE, en el mismo terminal escribiremos: code .

Esto abrirá el proyecto con nuestro VSCODE, deberíamos de tener la siguiente estructura:

└───contracts
│   │   Greeter.sol
└───scripts
|   │   sample-script.js
└───test
|   │   sample-test.js
│   .gitingore
│   hardhat.config.js
|   package-lock.json
|   package.json
|   README.md

Vamos a borrar los archivos dentro de contracts, scripts, y test. Dentro de contracts creamos un nuevo archivo con la extensión .sol, lo llamaremos como el proyecto pero en CamelCase: MiPrimerContratoInteligente.sol.

offtopic: En lo personal no me gusta el camel case porque es como BuRlArSe dE uNa PErsOna.

  1. Paso 2: Escribir nuestro contrato inteligente

Primera línea de nuestro contrato: debemos escribir la licencia del código que estamos escribiendo, yo siempre opto por la licencia MIT.

// SPDX-License-Identifier: MIT

Segunda línea de nuestro contrato: debemos especificar la versión de Solidity compatible con nuestro contrato. En nuestro caso usaremos cualquier versión superior a la 0.8.0, pero en función del proyecto que vayas a realizar querrás dejar abierta la posibilidad o no de limitar estas versiones.

pragma solidity ^0.8.0;

Tercera línea de nuestro contrato (que no sea literal puedes dejar espacios): Importamos la ayuda que nos da Hardhat para mostrar datos por consola:

import "hardhat/console.sol";

Cuarta línea de nuestro contrato: Aquí empieza lo bueno, vamos a declarar nuestro contrato, usando la palabra reservada contract:

contract MiPrimerContratoInteligente {}

Técnicamente ya podríamos decir que has escrito tu primer contrato inteligente, así que muchas gracias por haber seguido este tutorial ^^

… o podemos aprovechar me he bebido un buen café para hacer que este contrato haga lo que te había dicho que iba a hacer.

Dijimos (dije) que el contrato se iba a encargar de guardar mensajes y de mostrarlos por la consola así que vamos a por ello. Lo primero será declarar una variable dentro del contrato que acabamos de declarar, donde podamos guardar esos mensajes. Como vamos a guardar más de un mensaje usaremos un Array, este array se encargara de guardar el mensaje y el remitente, así que tenemos que estructurarlo para que acepte este formato, para ello vamos a crear esta estructura con el nombre Message.

struct Message {
  string text;
  address sender;
}

Como Solidity es un lenguaje fuertemente tipado tenemos que declarar explícitamente el tipo que va a aceptar nuestra variable, para el mensaje usaremos una string y para guardar la cartera del remitente usaremos address, es un tipo especial proporcionado por Solidity para guardar direcciones de carteras.

Ahora vamos a crear nuestro array de mensajes, para ello utilizaremos la estructura creada previamente para declara un array que contenga solo este tipo de estructura:

Message[] public messages;

Ya podemos guardar los mensajes pero ahora, ¿Cómo le hacemos para que eso suceda?. Vamos a escribir una función que tome como parámetro el mensaje a guardar, la dirección del remitente se incluye automáticamente así que no la necesitamos como parámetro.

function sendMessage (string memory _message) public {}

Dentro de esta función tomaremos el parámetro del mensaje y lo mostraremos por consola, esto lo podemos hacer porque importamos esa funcionalidad de hardhat en la tercera línea de nuestro contrato.

console.log("El usuario %s ha dicho: %s", msg.sender, _message);

Como la dirección del usuario se carga implícitamente así que solo tenemos que acceder a ella usando msg.sender.

Ahora vamos a guardar ese mensaje en nuestro array de mensajes por si quisiéramos mostrar la lista de mensajes en alguna aplicación:

messages.push(Message(_message, msg.sender));

Como puedes ver este método es muy parecido al que usa javascript para añadir elementos a un array, de hecho casi todo aquí es bastante parecido a javascript, hasta tu te pareces a javascript.

Si queremos conseguir esos mensajes guardados, tendremos que crear una función para leer esa lista de mensajes. Lo mas interesante a tener en cuenta aquí es como especificamos el formato que tiene que tener el Array que estamos pidiendo:

function getMessages() public view returns (Message[] memory) {
  return messages;
}

Oficialmente acabas de escribir tu primer contrato inteligente usando Solidity (ahora sí). Pero queda un ultimo paso.

  1. Paso 3: Probar el contrato.

Para probar el contrato vamos a crear un script dentro de nuestra carpeta de scripts, se encargara de probar nuestro contrato en una red local de Ethereum.

Vamos a crear un archivo llamado run.js (puedes ponerle el nombre que tu quieras), dentro vamos a escribir lo siguiente:

const main = async () => {}

const runMain = async () => {
    try {
        await main();
        process.exit(0);
    } catch (error) {
        console.log(error);
        process.exit(1);
    }
};

runMain();

Esta será la estructura básica que usaremos para todos nuestros scripts de ahora en adelante. Dentro de main vamos a llamar a nuestro contrato de la siguiente manera:

const miPrimerContratoFactory = await hre.ethers.getContractFactory("MiPrimerContratoInteligente");

Luego vamos a publicar nuestro contrato y a esperar a que se haya publicado correctamente:

const miPrimerContrato = await miPrimerContratoFactory.deploy();
await miPrimerContrato.deployed();

Finalmente vamos a llamar a las funciones que programamos en nuestro contrato para asegurarnos de que funciona correctamente:

let sendMsg = await miPrimerContrato.sendMessage('Hola Mundo');
await sendMsg.wait();  
    
let allMessages = await miPrimerContrato.getMessages();
console.log(allMessages);

Ahora ha llegado el momento de la verdad, vamos a publicar este contrato para probarlo, solo tenemos que ejecutar nuestro script de pruebas. Vuelve a la terminal donde tienes abierto el directorio del proyecto y escribe la siguiente línea:

npx hardhat run scripts/run.js

Voilà! Welcome to Web3 🚀

Hasta aquí el tutorial, espero que este bocadito te haya abierto el apetito por el internet del futuro. Ahora ya puedes crear tu propia aplicación descentralizada o tu propio banco! Gracias por llegar hasta aquí, si tienes alguna duda échale un ojo al repositorio o envíame un correo ✌