domingo, enero 09, 2022

Blockchain & SmartContracts: Cómo probar y desplegar un SmartContract en Ethereum

En el anterior artículo aprendimos lo básico para poder hacer nuestro primer Smart Contract con Solidity y creamos un simple Smart Contract pero no os conté cómo compilarlo y ejecutarlo para ver si funcionaba o no. En el artículo de hoy os voy a enseñar un par de conceptos más, que me parecen necesarios para que podáis leer vosotros mismos Smart Contracts. Después os enseñaré a probarlos y subirlos a la estrcutrua de BlockChain.

Figura 1: Blockchain & SmartContracts: Cómo probar
y desplegar un SmartContract en Ethereum

Para continuar si estabais siguiendo el artículo con vuestro ordenador os recomiendo que copies el contrato de este enlace y lo peguéis en Remix para continuar con la parte anterior.

Modificadores de acceso

En la última parte vimos los modificadores de acceso predeterminados de Solidity. Sin embargo, hay que añadir que predeterminados existen algunos más, junto con los que nosotros creemos, porque Solidity nos proporciona la posibilidad de implementar modificadores de acceso propios aunque estos solo pueden ser aplicados a funciones. Veamos ahora los modificadores que no os expuse.

Figura 2: Función _existUrl

Como podéis ver en la imagen esta es la función _existUrl que creamos y en ella especificamos que era private y retornaba un valor booleano, pero sin embargo podemos ver que además utilizamos la palabra reservada view.
  • view: Es un modificador de acceso solo aplicable a funciones, que manifiesta que la función no altera el estado del Smart Contract, es decir que no modifica las variables globales que definimos al principio del contrato. Porque recordemos que todo lo que guardemos como estado en el contrato se guardará permanentemente en la BlockChain y eso tiene un coste de computación que posteriormente se cobrará a aquel que llame a una función pública del contrato. Además de que si en esa función se llaman a otras se irá sumando el coste de modificar el estado de cada una de las funciones. Si añades este modificador y tu función no altera el estado del contrato entonces no cobrará ningún coste a quien haga una llamada a la función.
  • pure: Funciona de manera muy similar a view, solo que esta especifica que no lee ni escribe datos de la blockchain, por lo tanto solo realiza operaciones.
Modificadores “custom”

En el contrato podemos ver que usamos de manera repetida esta pieza de código:

Figura 3: Modificadores custom

En nuestro caso solo se repite dos veces pero en contratos con mayor lógica se repetiría un montón, además que los desarrolladores somos (o debemos ser) seres vagos por naturaleza con lo que repetir el mismo código varias veces va en contra de nuestra naturaleza. Por ello como buenos desarrolladores que somos vamos a extraer y encapsular esta lógica para que la próxima vez que queramos verificar, que quien llama la función es el dueño nos baste con escribir 9 letras.
 modifier onlyOwner(){
   require(msg.sender == owner, "Error, you are not the owner");
   _;
 }
  • Definición: Como podéis observar para definir un modificador solo hay que utilizar la palabra reservada modifier y el nombre que le queramos dar, además de abrir paréntesis por si le queremos pasar algún dato por parámetros. En este caso no le pasaremos ningún parámetro porque el modificador conservará la traza del objeto msg.
  • Cuerpo: Los modificadores no pueden retornar nada, solo deben servir para romper el flujo de ejecución de una función en caso de que ciertas condiciones no se cumplan.
  • Fin: Al final del modificador debemos escribir en la última línea “_;” lo cual significa que si nada ha roto el flujo de ejecución de la función esta puede continuar.
Ahora vamos a crear otros dos para que entendáis mejor el concepto, en este caso estos se encargaran de ver si existe o no la url, en estos si hacen falta los parámetros.
 modifier existsUrl(string memory _url){
   require(_existsUrl(_url), "The provided url does not exist");
   _;
 }
 modifier notExistsUrl(string memory _url){
   require(!_existsUrl(_url), "The url already exists");
   _;
 }
Una vez que hemos creado los modificadores tendremos un contrato así (se puede observar en las funciones cómo los he implementado):
pragma solidity ^0.8.3;
contract FirstContract {
 address public owner;
 string public ownerName = "Chiquito de la Calzada";
 uint256 public ownerAge = 23;
 string[] public posts;
 constructor(address _firstOwner){
   owner = _firstOwner;
 }
 modifier onlyOwner(){
   require(msg.sender == owner, "Error, you are not the owner");
   _;
 }
 modifier existsUrl(string memory _url){
   require(_existsUrl(_url), "The provided url does not exist");
   _;
 }
 modifier notExistsUrl(string memory _url){
   require(!_existsUrl(_url), "The url already exists");
   _;
 }
 function setOwnerState(
   address _newOwner,
   string memory  _ownerName,
   uint256  _age
 ) public onlyOwner {
   owner = _newOwner;
   ownerName = _ownerName;
   ownerAge = _age;
 }
 function addPostUrl(string memory _url) public onlyOwner notExistsUrl(_url) {
   posts.push(_url);
 }
 function deletePostUrl(string memory _url) public onlyOwner existsUrl(_url) {
   for(uint i=0; ilt;posts.length; i++){
     if(keccak256(abi.encodePacked(_url))
         ==
       keccak256(abi.encodePacked(posts[i]))){
       delete posts[i];
     }
   }
 }
 function getPosts() public view returns(string[] memory){
   return posts;
 }
 function _existsUrl(string memory _url) private view returns(bool) {
   for(uint i=0; ilt;posts.length; i++){
       if(keccak256(abi.encodePacked(_url)) == keccak256(abi.encodePacked(posts[i]))){
         return true;
       }
   }
   return false;
 }
}
Probar el contrato usando el IDE

Está muy bien que os haya enseñado todo esto, pero aun no os he contado cómo compilarlo y ejecutarlo para comprobar si es correcto lo que hemos escrito. La verdad es que hay muchas maneras, pero la más simple es utilizar Remix. Para ello solo hay que seguir estos pasos.

1. Creamos el contrato: En nuestro caso como hemos usado Remix como IDE deberemos de tener un archivo llamado “FirstContract.sol” dentro del directorio “contracts” al lado izquierdo de nuestra pantalla, si no fuera así podemos crear un nuevo archivo en el directorio y pegar el anterior contrato.

2. Compilamos el contrato: Ahora iremos a la pestaña “Solidity compiler” en la barra lateral izquierda (los nombres de las pestañas se ven haciendo "hover" sobre los iconos). Entonces nuestra pantalla se verá así

Figura 4: Solidity Compiler

2.1. Nos aseguramos que la versión del compilador seleccionada en la zona marcada “1º” sea igual o mayor a la que hemos establecido en el contrato.

Figura 5: Versión mayor que la establecida en el contrato

2.2. Si hemos seleccionado previamente el fichero FirstContract.sol en la pestaña de “File explorer” nos aparecerá la zona marcada “2º” si no pues volvemos a esa pestaña y abrimos el fichero, después volvemos a la pestaña de “Solidity Compiler” y aparecerá la zona ““.

Figura 6: Compile FirstContract.sol

2.3. Hacemos click en el botón de “Compile…” y entonces tendremos compilado el contrato.

3. Revisión del bytecode compilado: Ahora que la EVM ha compilado el contrato podemos ir a la pestaña “File explorer” y si abrimos el directorio “./contracts/artifacts” observaremos el archivo “FirstContract.json”, si lo abrimos veremos un montón de propiedades, la más importante de ellas es la propiedad de “bytecode” la cual contiene el contrato.

Figura 7: Fichero JON. Haz clic en la imagen para ver en grande.

Este archivo es muy importante de cara a la Web3.0 pues la mayoría de las librerías aparte de la dirección del contrato para conectarse a él te piden también el código compilado para poder acceder a las funciones del contrato.

4. Desplegamos en local el contrato: Ahora nos dirigiremos a la pestaña de “Deploy & run transactions” haciendo clic en el icono de en medio de la barra de la izquierda. En esta pestaña podremos desplegar el contrato en diferentes entornos. Una vez en esa pestaña nuestra pantalla se verá de la siguiente manera.

Figura 8: Testeto del SmartContract

4.1. Opciones de ejecución. Como podemos ver en la imagen he diferenciado entre diferentes apartados. El apartado “1º” es en el que se eligen el entorno en el que se va a ejecutar el contrato. Dejaremos por defecto la “JavaScript VM (London)”. Si hacemos clic en el desplegable veremos las siguientes opciones de entornos de ejecución.

Figura 9: Opciones de Ejecución
  • VMs: Son el entorno de ejecución en local, lo que significa que todo lo que hagamos en ese entorno no permanecerá si recargamos la página. Esta selección viene muy bien para hacer pruebas rápidas del contrato.
  • Injected Web3: Con esta selección Remix utilizara los proveedores de web3 que tengamos instalados en el navegador como por ejemplo Metamask. Cabe destacar que si por ejemplo utilizar Metamark y lo utilizan como Wallet para probar el contrato podréis seleccionar diferentes redes en las que colgar el contrato y estas pueden ser desde la TestNet de Rinkeby a la Mainnet de Ethereum. 
  • Web3 provider: Probablemente esta sea la menos interesante, con esta en vez de utilizar nuestro wallet podremos conectarnos directamente a un nodo de la red de Ethereum si conocemos la dirección IP en el que está el nodo. Cabe remarcarse que también puedes conectarte a un nodo de prueba local que esté corriendo en tu propio ordenador.
4.2. Si nos fijamos en el apartado “2º” y clicamos en el desplegable veremos un montón de cuentas de Ethereum con 100 de eth. Estas cuentas son locales y nos permiten probar nuestro contrato. Podemos hacer clic en la que queramos y esto hará que la cuenta que vamos a utilizar para testear el contrato sea esa.

Figura 10: Cuentas locales para testear nuestro SmartContract

4.3. Ahora nos aseguramos que en el desplegable de la sección “3º” tiene seleccionado “FirstContract.sol”.

4.4. Finalmente si copiamos la dirección de Ethereum que tenemos seleccionada y la pegamos en el input de la sección “4º” y le damos al botón de “Deploy” tendremos el contrato corriendo en local.

Figura 11: Despliegue de nuestro SmartContract

Probar el SmartContract

Ahora que tenemos corriendo en local el contrato podremos realizar transacciones al mismo - transacciones es el término que se da a realizar “querys” o "consultas" al contrato -. Si nos fijamos un poco en la cuenta de Ethereum que seleccionamos anteriormente veremos que ya no hay 100 eth sino 99.xxx y esto ocurrió justo después de darle al botón de “Deploy”. 

Al tocar el botón lo que ocurrió es que se inició una transacción en el nodo virtual que emula Remix y esta transacción le pedía a la red local que subiese un contrato y eso conlleva unos costes que nos retiraron de la cuenta, pero como todo es emulado/falso esos eth que se nos cobraron por la transacción se quitaron de la cuenta que Remix nos dio para probar. Si hubiéramos utilizado un Wallet este nos hubiera pedido confirmación para pagar los eth tanto si usábamos la red de Rinkeby como la Mainnet.

Figura 12: SmartContract Desplegado en local

Como tenemos el contrato desplegado si hacemos clic tal y  cómo se ha indicado en la imagen anterior y deslizamos el cursor veremos la barra de la izquierda de la siguiente manera.

Figura 13: Detalles del SmartContract desplegado en local

Como podemos ver tenemos un montón de botones e inputs nuevos con los que interactuar además de que si nos fijamos veremos que los botones naranjas que van acompañados de inputs son las funciones que declaramos como públicas y los botones en azul las variables globales del contrato que se guardan en la BlockChain.

Para interactuar con las funciones addPostUrl, deletePostUrl y setOwnerState debemos recordar que quien llame las funciones debe ser el dueño del contrato con lo que nos tenemos que asegurar que en el panel de Remix tengamos seleccionada la cuenta de Eth que le pasamos al constructor al hacer deploy.

Ahora curiosead un rato con las funciones para hacer pruebas con el contrato y además, id cambiando con la función setOwnerState el dueño del contrato para ver cómo funciona del todo la lógica de nuestro contrato. Otra cosa, cuando cambiéis de cuenta de eth en Remix a otra diferente a la que el contrato tiene como dueño habrá funciones que dejen de responderos con lo que tendréis que cambiar también el dueño del contrato.

Despliegue del contrato en la BlockChain pública

Ahora que hemos testeado el contrato y sabemos que no tiene bugs podemos subirlo a las diferentes “chains” de Ethereum como la principal o también llamada mainnet o también a las testNets como la de Rinkeby o “sidechains” como Polygon que utiliza un algoritmo de verificación de bloques distinto. Sea como fuere hace falta que tengamos un wallet con eth para poder desplegarlo en cualquier “chain” dado que el despliegue como tal es una transacción que tiene asociada unos costes o también comúnmente llamado "Gas". En testNets es muy fácil conseguir eth puesto que hay páginas (como esta) que con solo poner tu dirección te mandan ether a tu cuenta.

Dicho esto despleguémoslo en la cadena de Rinkeby, para ello solo nos hace falta un wallet que inyecte Web3 en el navegador, en nuestro caso recomiendo Metamask. Una vez creada la cuenta abrimos Metamask y cambiamos la cadena a la de Rinkeby de esta manera.

Figura 14: Despliegue del contrato

Entonces seguimos los mismos pasos que hicimos para desplegar el contrato en local y esta vez seleccionaremos “Injected Web3” como entorno para el despliegue. Acto seguido nos pedirá que iniciemos sesión con nuestro wallet y después si pagamos los fees tendremos desplegado el contrato en la cadena de Rinkeby de Ethereum. Esta vez hemos desplegado el contrato en Rinkeby pero podríamos haberlo hecho con cualquier otra seleccionando en Metamask una cualquiera.

Comentarios finales

Para recapitular, durante estos artículos hemos aprendido lo básico para crear contratos en Solidity y junto con Remix hemos aprendido a desplegar tanto en local como en la red de Ethereum. Ahora os recomiendo que indaguéis en conceptos más avanzados de Solidity como las estructuras, herencia, abstracciones, proxies… para que así podáis crear vosotros mismos vuestros SmartContracts.

Figura 15: Libro dedicado a "Bitcoin: La tecnología Blockchain y su investigación"
de Yaiza Rubio y Félix Brezo

Ahora que ya sabéis cómo se crean los SmartContracts de la red de Ethereum podemos ver en más detalle un montón de tecnologías nuevas como los NFTs, tokens como el de SandBox, Metaversos Descentralizados, intercambio de criptodivisas y muchas otras. Más artículos sobre este mundo Web3:
Si tenéis cualquier duda con algo de estos dos últimos posts o del mundillo de Web3.0 estaré encantado de responderos tanto en mi perfil de MyPublicInbox como en mi cuenta de Twitter (aparece en mi perfil de MyPublicInbox). Nos vemos en los siguientes artículos.

Autor: Chema Garabito. Desarrollador Full-Stack. Ideas Locas Telefónica CDO.

No hay comentarios:

Publicar un comentario