WEB3DEV Español

Cover image for Escribe tu Primer Contrato Inteligente usando Opcodes: Una Guía Completa
Hector
Hector

Posted on

Escribe tu Primer Contrato Inteligente usando Opcodes: Una Guía Completa

Image description

Los Contratos Inteligentes son bloques de construcción de la tecnología blockchain. Mientras muchos desarrolladores usan lenguajes populares como Solidity, hay otra forma de escribir contratos inteligentes: usar opcodes. En esta guía para novatos explicaremos cómo escribir, probar y desplegar un contrato inteligente usando sólo opcodes.

¿Qué son los Opcodes y Por Qué Usarlos?

Opcodes, corto para códigos de operación (operation codes), son instrucciones básicas que la Máquina Virtual de Ethereum (Ethereum Virtual Machine, EVM) entiende. Pueden parecer complejas pero ofrecen beneficios únicos:

1: Conocimiento Profundo del EVM

Trabajar directamente con Opcodes provee un conocimiento profundo sobre cómo la EVM opera y ofrece conocimiento que puede ser invaluable para los desarrolladores, investigadores y educadores.

¿2: Optimización de Gas?

Los Opcodes permiten a los desarrolladores tener la habilidad de optimizar el código para la eficiencia de gas, reduciendo los costos de la transacción.

3: Funcionalidad Personalizada

Los Opcodes permiten un nivel de personalización y control que puede que no se logre a través de lenguajes de alto nivel. Los desarrolladores pueden hacer funcionalidades específicas, de acuerdo a sus requerimientos únicos.

4: Análisis de Seguridad

Examinando el bytecode de un contrato, los auditores y expertos de seguridad pueden identificar vulnerabilidades y asegurar que el contrato se comporte como debe.

Guía Paso a Paso sobre Cómo Escribir un Contrato Inteligente Usando Opcodes

Escribir contratos inteligentes usando opcodes puede ser abrumador pero, desglosemos la tarea y aprendamos cómo podemos desplegar nuestro primer contrato inteligente usando opcodes.

1: Entendiendo los Opcodes EVM

Entender los opcodes es el primer paso. Hay cerca de 120 opcodes, cada uno con diferentes funcionalidades. Aquí hay algunos ejemplos:

Image description

Para aprender más sobre opcodes, puedes revisar esta guía completa. Practica usando la EVM playground para familiarizarte con los opcodes.

2: Escribe el Opcode para el Contrato Inteligente

Ahora que estás cómodo con los opcodes, esboza la lógica de tu contrato. Determina qué funciones quieres realizar y cómo los datos serán almacenados y manipulados.

Para esta guía, vamos a escribir un opcode muy simple para invocar dos números.

Así es como se ve:

PUSH1 0X02
PUSH2 0X03
ADD
Enter fullscreen mode Exit fullscreen mode

Vamos a simplificar estas líneas:

  1. PUSH1 0x02 empuja el valor 0x02 al stack
  2. PUSH1 0x03 empuja el valor 0x03 al stack
  3. ADD estalla los dos valores superiores desde el stack, los junta y empuja el resultado al stack.

3: Calcula el Bytecode para el Opcode

Una vez tengamos el opcode para nuestro contrato. Entendamos cómo podemos calcular el bytecode para el opcode dado:

  1. PUSH 0x02
  • PUSH1 El opcode para PUSH1 es 0x60
  • 0x02 El valor a ser empujado al stack
  • Combinado, esto da el bytecode 0x6002
  1. PUSH1 0x03
  • PUSH1: El opcode para PUSH1 es 0x60.
  • 0x03: El valor a ser empujado al stack.
  • Combinado, esto da el bytecode 0x6003.
  1. ADD
  • ADD: El opcode de ADD es 0x01.
  • No hay un valor asociado, así que el bytecode simplemente es 0x01.

Juntando todo esto, el bytecode completo para los opcodes dados es:

0x6002600301
Enter fullscreen mode Exit fullscreen mode

Este bytecode puede ser usado para desplegar o interactuar con un contrato en la red de Ethereum.

4: Despliega el contrato

Remix no provee una forma directa de compilar opcodes crudos. Así que vamos a usar un contrato wrapper el cual incluirá el bytecode como constructor. Esto nos permitirá desplegar los opcodes.

Aquí está cómo se vería nuestro contrato wrapper:

pragma solidity ^0.8.0;
Enter fullscreen mode Exit fullscreen mode
contract DeployOpcodes {
   uint256 public sum;
   constructor() {
       deployOpcodes();
   }
   function deployOpcodes() private {
       assembly {
           let x := mload(0x40) // Encuentra el lugar de almacenamiento vacío
           mstore(x, 0x02) // Primer número a añadir
           mstore(add(x, 0x20), 0x03) // Segundo número a añadir
           let result := add(mload(x), mload(add(x, 0x20))) // Sum the numbers
           sstore(sum.slot, result) // Almacena el resultado en el estado de la variable "sum"
       }
   }
   function getSum() public view returns (uint256) {
       return sum;
   }
}
Enter fullscreen mode Exit fullscreen mode

En este contrato, tenemos varios componentes claves:

  1. Declaración del Contrato **DeployOpcodes:** Este es el nombre de nuestro contrato y es donde alojaremos todas las funciones y variables relacionados a nuestro despliegue de opcodes.

  2. Función Privada **deployOpcodes:** Dentro de esta función, vamos a trabajar directamente con la Máquina Virtual de Ethereum (EVM) usando el lenguaje assembly. Aquí hay un desglose de qué hace cada línea:

  • a. Bloque de Asamblea: Empezamos con el keyword assembly, permitiéndonos escribir códigos EVM de bajo nivel.

  • b. Encontrar una Ubicación para de Almacenamiento Vacío: La línea let x := mload(0x40) carga el valor de la ubicación de la memoria 0x40, un lugar especial en la EVM que usualmente contiene el “puntero de memoria libre”. Asignando este valor a la variable x, encontraremos una ubicación de almacenamiento vacío.

  • c Almacenar el Primer Número: Luego, mstore(x, 0x02) almacena el valor 0x02 en la ubicación de la memoria apuntado por x. Esto representa el primer número a añadir.

  • d Almacenar el Segundo Número: La línea mstore(add(x, 0x20), 0x03) almacena el valor 0x03 en la ubicación de la memoria x + 0x20. Esto representa el segundo número a añadir.

  • e Calcular la Suma: Con let result := add(mload(x), mload(add(x, 0x20))), cargamos los valores en las ubicaciones de la memoria x y x+0x20, juntarlos y asignar el resultado a una variable llamada result.

  • f Almacenar el Resultado: Finalmente, sstore(sum.slot, result) almacena el valor result en la ranura de almacenamiento correspondiente al estado de la variable sum. Esto nos permite retirar la suma luego.

¡Ahora usar Remix es fácil! ¡Compila el código y luego pulsa el botón Deploy!

Image description

Puedes ver que tenemos la función getSum, el cual nos retornará el valor 5.

Así es como escribimos nuestros contratos inteligentes usando opcodes.

Escribir contratos inteligentes usando opcodes no sólo es un ejercicio académico; es una herramienta poderosa para los desarrolladores que quieran optimizar, personalizar y realmente entender sus contratos inteligentes.

Si encontraste esta guía útil, ¡por favor dame un aplauso y sígueme para tener más conocimiento!

Pari Tomar (Twitter, LinkedIn)

Este artículo es una traducción de Pari Tomar, hecha por Héctor Botero. Puedes encontrar el artículo original aquí.
Sería genial escucharte en nuestro Discord, puedes contarnos tus ideas, comentarios, sugerencias y dejarnos saber lo que necesitas.
Si prefieres puedes escribirnos a @web3dev_es en Twitter.

Discussion (0)