WEB3DEV Español

Cover image for Una mejor forma de inicializar contratos actualizables
Hector
Hector

Posted on

Una mejor forma de inicializar contratos actualizables

Este artículo es una traducción de John Reynolds, 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_eshttps://twitter.com/web3dev_es en Twitter.

Diamantes EIP-2535

Vistazo General

El código del Contrato Inteligente es inmutable, lo que quiere decir que el código no puede ser cambiado luego que es desplegado. Esto crea retos cuando se desarrolla en el blockchain porque previene la habilidad de realizar mantenimientos o actualizaciones. Los contratos inteligentes también tienen un límite del tamaño del contrato de 24KB, introduciendo dilemas de escalabilidad. El estándar EIP-2535 ofrece un sofisticado patrón proxy que permite la adición, reemplazo y remoción de funciones mientras remueve cualquier limitación del tamaño del código.

Mientras que los contratos inteligentes son inmutables, pueden añadir y remover referencias a las funciones externas de otros contratos inteligentes y aun así preservar el contexto del almacenamiento usando llamadas delegate. Esta es la arquitectura estándar para los sistemas proxy.

Image description

El estándar Diamante EIP-2535 introduce un contrato proxy genérico, el Diamante, el cual incluye una función interna diamondCut() y expone una función fallback, la cual, despacha dinámicamente la función de llamada a las facetas invocadas desde el Diamante.

Image description

La función fallback, permite que las funciones de la faceta sean ejecutadas como si el Diamante las hubiese implementado. Los valores msg.sender y msg.value siguen siendo los mismos y el almacenamiento Diamante es leído y escrito.

Un contrato de diamante proxy es una sola fuente para todas las variables de estado de datos. Las facetas proveen el código y las definiciones de las variables de estado son utilizadas para leer y escribir al almacenamiento del contrato proxy diamante.

Image description
Un diamante contiene, en sí mismo, una función de selectores de mapeo a direcciones facetas. Las funciones son añadidas/reemplazadas/removidas modificando este mapeo.

DiamondCut

La función diamondCut es usada para añadir/reemplazar/remover cualquier número de facetas y funciones al diamante en una sola transacción, previniendo un estado inconsistente en el Diamante.

Image description

La función diamondCut() puede ejecutar una función externa con delegatecall durante una actualización. Esto es empleado para inicializar estados variables y hacer cualquier cambio necesario para una actualización.

Inicializando el Estado

El segundo y tercer argumento de la función diamondCut() son utilizados para inicializar el estado luego de una actualización. El argumento _init mantiene la dirección del contrato de la función para llamar e inicializar el estado del Diamante. El argumento _calldata tiene una función de llamada para enviar al contrato en _init.

Ejemplo: si una Faceta es añadida al Diamante empleando diamondCut(), el argumento _calldata provee la función de llamada para establecer el nombre del token y el valor símbolo y el argumento _init provee la dirección del contrato desde la función init. La función init es ejecutada en la misma transacción que diamondCut().

La ejecución calldata es saltada si el valor _init de la dirección (0), por lo tanto, _calldata puede contener 0 bytes o información personalizada.

DiamondInit

Luego de añadir/reemplazar/remover funciones, el argumento _calldata es ejecutado con delegatecall en _init. Esta ejecución está hecha para inicializar datos, configurar o remover cualquier cosa que no sea necesario. Las funciones DiamondInit pueden tener parámetros y pueden ser reusados como sea necesario, una vez desplegado.

Image description

El EIP-2535 también define la función DiamondMultiInit que ejecuta múltiples funciones de inicialización para una sola actualización. Esto puede ser útil cuando los usuarios quieren dar soporte a una función de inicialización única, por corte. DiamondMultiInit existe en una biblioteca para prevenir que sea borrada como resultado de un delegatecall a selfdestruct.

DiamondMultiInit

Image description

Durante la ejecución de una actualización, usar los argumentos _init y _calldata permite que ocurra la actualización de estado, en la misma transacción. Esto es importante porque previene que Diamante falle en un estado inconsistente, el cual podría surgir si las variables de estado no son inicializadas en sincronía con las funciones que son añadidas.

Conclusión

Los Diamantes EIP-2535 introducen un nuevo y mejor acercamiento para inicializar contratos actualizables. El estándar provee una función para inicializaciones de funciones solas o múltiples, luego de la función diamondCut(). Esta forma sincroniza las actualizaciones y la inicialización de estado en la misma transacción, ayudando a asegurar que Diamante siempre mantenga un estado consistente.

Recursos

https://eips.ethereum.org/EIPS/eip-2535

https://medium.com/gelato-network/exploring-eip-2535-diamond-standard-with-nick-mudge-a7bc0cfd1c

https://dev.to/mudgen/understanding-diamonds-on-ethereum-1fb

https://medium.com/derivadex/the-diamond-standard-a-new-paradigm-for-upgradeability-569121a08954

https://dev.to/mudgen/how-diamond-upgrades-work-417j

https://eip2535diamonds.substack.com/p/example-of-a-diamond-upgrade

https://github.com/mudgen/diamond-1-hardhat

https://github.com/mudgen/awesome-diamonds

Discussion (0)