Descripción de los conceptos básicos del lenguaje

Completado

Cualquier contrato de Solidity suele incluir lo siguiente:

  • Directivas pragma
  • Variables de estado
  • Functions
  • Eventos

Si bien es cierto que hay más elementos que es necesario conocer para programar contratos inteligentes de nivel de producción, con estos de aquí podremos comenzar con buen pie.

Con tener claros estos conceptos, podremos empezar a escribir contratos inteligentes para diferentes casos de uso de forma inmediata.

Directivas pragma

Pragma es la palabra clave que se usa para pedir al compilador que compruebe si su versión de Solidity coincide con la que necesitamos. Si es la misma, nuestro archivo de código fuente funcionará correctamente; si no, el compilador generará un error.

Procure incluir siempre la versión más reciente de Solidity en la definición del contrato. Para saber cuál es la versión actual de Solidity, visite el sitio web de Solidity. Use la versión más reciente en el archivo de código fuente.

Una directiva pragma de versión tiene el siguiente aspecto:

pragma solidity ^0.7.0;

Esta línea significa que el archivo de código fuente se compilará con un compilador que tiene una versión posterior a 0.7.0, hasta 0.7.9. A partir de la versión 0.8.0, lo más probable es que se introduzcan cambios importantes que el archivo de código fuente no sea capaz de compilar correctamente.

Variables de estado

Las variables de estado son esenciales en cualquier archivo de código fuente de Solidity. Los valores de variable de estado se almacenan permanentemente en el almacenamiento del contrato.

pragma solidity >0.7.0 <0.8.0;

contract Marketplace {
    uint price; // State variable  

Nota:

Los archivos de origen del contrato siempre empiezan con la definición contrato nombreDeContrato.

En este ejemplo, la variable de estado se denomina price, con el tipo uint. El tipo entero uint indica que esta variable es un entero sin signo con 256 bits, lo que significa que puede almacenar números positivos dentro del intervalo entre 0 y 2256-1.

En todas las definiciones de variables hay que especificar el tipo y el nombre de la variable.

También podemos especificar la visibilidad de una variable de estado de uno de los siguientes modos:

  • public: la variable forma parte de la interfaz del contrato y se puede acceder a ella desde otros contratos.
  • internal: solo se puede acceder a la variable internamente desde el contrato actual.
  • private: solo es visible en el contrato en el que se definen.

Functions

Dentro de un contrato, las unidades ejecutables de código se conocen como funciones. Las funciones describen una única acción para lograr una tarea. Son reutilizables, y se les puede llamar también desde otros archivos de código fuente, como una biblioteca. Las funciones de Solidity se comportan de forma similar a las funciones de otros lenguajes de programación.

Este es un sencillo ejemplo de cómo definir una función:

pragma solidity >0.7.0 <0.8.0;

contract Marketplace {
    function buy() public {
        // ...
    }
}

Este código muestra una función con el nombre buy que tiene visibilidad pública, lo que significa que otros contratos pueden acceder a ella. Las funciones pueden usar uno de los siguientes especificadores de visibilidad: public, private, internal y external.

Las funciones se pueden llamar de forma interna o externa desde otro contrato. Pueden aceptar parámetros, así como devolver variables para pasarse parámetros y valores entre ellas.

Este es un ejemplo de una función que acepta un parámetro (un entero llamado price) y devuelve un entero:

pragma solidity >0.7.0 <0.8.0;

contract Marketplace {
    function buy(uint price) public returns (uint) {
        // ...
    }
}

Modificadores de funciones

Podemos usar modificadores de funciones para cambiar el comportamiento de las funciones. Su cometido es comprobar una condición antes de que la función se ejecute. Un ejemplo sería una función que comprobara que solamente los usuarios designados como vendedores pueden incluir un artículo en un catálogo para su venta.

pragma solidity >0.7.0 <0.8.0;

contract Marketplace {
    address public seller;

    modifier onlySeller() {
        require(
            msg.sender == seller,
            "Only seller can put an item up for sale."
        );
        _;
    }

    function listItem() public view onlySeller {
        // ...
    }
}

Este ejemplo consta de los siguientes elementos:

  • Una variable de tipo address que almacena la dirección de Ethereum de 20 bytes del usuario vendedor. Profundizaremos en estas variables más adelante en este módulo.
  • Un modificador denominado onlySeller, que describe que solo un vendedor puede incluir un artículo en el catálogo.
  • Un símbolo especial (_;) para indicar dónde se inserta el cuerpo de la función.
  • Una definición de función que usa el modificador onlySeller.

Otros modificadores de función que se pueden usar en la definición de función son:

  • pure, para describir funciones que no permiten modificaciones o el acceso del estado.
  • view, para describir funciones que no permiten modificaciones del estado.
  • payable, para describir las funciones que pueden recibir Ethers.

Eventos

Los eventos describen las acciones que se realizan en el contrato. Al igual que las funciones, los eventos tienen parámetros que se deben especificar cuando se llama al evento.

Para llamar a un evento, debemos usar la palabra clave emit junto con el nombre del evento y sus parámetros.

pragma solidity >0.7.0 <0.8.0;

contract Marketplace {
    event PurchasedItem(address buyer, uint price);

    function buy() public {
        // ...
        emit PurchasedItem(msg.sender, msg.value);
    }
}

Cuando se llama a un evento, se captura como una transacción en el registro de transacciones, que es una estructura de datos especial en la cadena de bloques. Estos registros se asocian con la dirección del contrato, se incorporan a la cadena de bloques y permanecen allí para siempre. El registro y sus datos de evento no se pueden modificar, y no se puede acceder a ellos desde los contratos.