Ir al contenido principal

Explicación del estándar Diamond (EIP-2535) - Parte 2

Actualizado el
26 de noviembre de 2025

7 minutos de lectura

Aviso importante

Esta guía incluye referencias a la red de pruebas Goerli, que ya no se mantiene de forma activa. Aunque es posible que algunos pasos específicos relacionados con esta cadena ya no sean aplicables, el proceso general puede ser válido para otras cadenas. Te recomendamos que explores las alternativas actuales para tu implementación. Si te gustaría ver una versión actualizada de esta guía, ¡háznoslo saber!

Resumen

En la primera parte de la serie sobre el estándar Diamond, aprendimos qué son los contratos Diamond (es decir, «Multi-Facet Proxy») y cómo funcionan. En esta guía, aprenderás a crear, implementar y probar un contrato inteligente Diamond compatible con EIP-2535 utilizando el repositorio «diamond-1-hardhat» y «louper.dev», una herramienta para inspeccionar contratos inteligentes Diamond en cadenas basadas en EVM.

Tus funciones

  • Configurar y examinar el repositorio «diamond-1-hardhat»
  • Crear e implementar el conjunto de contratos inteligentes de Diamond
  • Comprueba el funcionamiento del contrato inteligente Diamond

Lo que necesitarás

Configuración del proyecto

En este tutorial, crearemos un contrato inteligente Diamond utilizando el repositorio diamond-1-hardhat (creado por Nick Mudge, autor de la EIP-2535). Si quieres ver otras implementaciones, echa un vistazo a estos otros recursos. Ten en cuenta que también existen los repositorios «diamond-2-hardhat» y «diamond-3-hardhat», que muestran métodos alternativos para implementar y desplegar un contrato inteligente Diamond (por ejemplo, con optimización del gas y con la implementación de funciones «loupe»).

Ahora, empecemos a configurar nuestro proyecto. Abre una ventana de terminal y ejecuta el siguiente comando para clonar el repositorio y acceder a él:

git clone https://github.com/mudgen/diamond-1-hardhat && cd diamond-1-hardhat

A continuación, instalé las dependencias necesarias:

npm install && npm install --save-dev @nomiclabs/hardhat-etherscan

Abre el proyecto en el editor de código que prefieras y abre el archivo hardhat.config.js. Añade la siguiente importación al principio del archivo:

require("@nomiclabs/hardhat-etherscan");

Requiere el complemento para la verificación automática de contratos inteligentes con Etherscan

A continuación, añade el siguiente código al final del objeto ` module.exports ` en el archivo `hardhat.config.js `:

networks: {
goerli: {
url: "YOUR_QUICKNODE_HTTP_ENDPOINT",
accounts: ["YOUR_PRIVATE_KEY"]
}
},
etherscan: {
// Your API key for Etherscan
// Obtain one at https://etherscan.io/
apiKey: "YOUR_ETHERSCAN_API_KEY"
}

Ahora nos tomaremos un momento para asegurarnos de que disponemos de suficiente ETH de la red de pruebas (en Goerli) y sustituiremos los valores provisionales anteriores por nuestra URL RPC, nuestra clave privada y nuestra clave API de Etherscan reales.

En primer lugar, recupera tu clave privada y sustitúyela por YOUR_PRIVATE_KEY en el texto anterior (si utilizas MetaMask, encontrarás las instrucciones aquí). A continuación, accede al grifo multicadena de Quicknode para obtener algo de ETH en la red de pruebas Goerli de Ethereum. Puedes conectar tu monedero o pegar tu dirección pública; sin embargo, ten en cuenta que necesitarás al menos 0,001 ETH en la red principal de Ethereum para utilizar el grifo de la red de pruebas.

También tendrás que introducir tus claves API de Etherscan.io (que necesitaremos más adelante para verificar nuestro Facet en louper.dev). Por último, necesitaremos acceso a la cadena de bloques de la red de pruebas Goerli de Ethereum. Puedes utilizar nodos públicos o implementar y gestionar tu propia infraestructura; sin embargo, si quieres tiempos de respuesta hasta 8 veces más rápidos, puedes dejarnos a nosotros el trabajo pesado. Regístrate aquí para crear una cuenta. Una vez que tengas tu URL RPC, sustitúyela por YOUR_QUICKNODE_HTTP_ENDPOINT en hardhat.config.js y guarda el archivo.

Una vez completadas todas estas tareas, ya tienes nuestro proyecto Hardhat configurado para implementarlo en la red de pruebas Goerli de Ethereum y verificar el código fuente mediante el complemento Hardhat-etherscan. A continuación, crearemos e implementaremos el conjunto de contratos inteligentes «diamond».

Crear e implementar el contrato inteligente Diamond

El repositorio «diamond-1-hardhat» es una implementación de referencia para los «Diamonds» de la EIP-2535. Contiene el código estándar necesario para crear un contrato «Diamond». Incluso incluye «Facets» de prueba que puedes utilizar; sin embargo, con fines didácticos, crearemos nuestro propio «Facet».

En la carpeta «contracts/facets», crea un archivo llamado «FacetA.sol» y añade el siguiente código:

pragma solidity ^0.8.0;

library LibA {

struct DiamondStorage {
address owner;
bytes32 dataA;
}


function diamondStorage() internal pure returns(DiamondStorage storage ds) {
bytes32 storagePosition = keccak256("diamond.storage.LibA");
assembly {
ds.slot := storagePosition
}
}
}

contract FacetA {
function setDataA(bytes32 _dataA) external {
LibA.DiamondStorage storage ds = LibA.diamondStorage();
ds.dataA = _dataA;
}

function getDataA() external view returns (bytes32) {
return LibA.diamondStorage().dataA;
}
}

¡Repasemos el código!

  • Línea 1: Establece nuestra versión de pragma. Ten en cuenta que al establecer la versión se indica al compilador que compruebe si la versión coincide con la requerida por el pragma. Si no coincide, el compilador genera un error.

  • Línea 3-17: Crea una biblioteca que implemente DiamondStorage. La biblioteca contiene una estructura que almacena las variables Facets y una función diamondStorage que especifica una posición aleatoria a partir del hash de una cadena, y establece la posición de nuestra estructura en el almacenamiento del contrato.

  • Líneas 19-28: Crea un contrato que implemente dos funciones: `setDataA`, que toma un valor de tipo `bytes32` y establece el almacenamiento de diamantes definido anteriormente, y `getDataA`, que lee el valor almacenado mediante `setDataA`.

Ahora que ya hemos creado nuestro Facet, podemos pasar a compilar e implementar los contratos inteligentes. El proceso para implementar un contrato inteligente de Diamond e incorporar nuestro Facet será el siguiente:


  • Implementar DiamondInit.sol
  • Implementar DiamondCutFacet.sol
  • Implementar DiamondLoupeFacet.sol
  • Implementar OwnershipFacet.sol
  • Implementar Diamond.sol
  • Implementar FacetA.sol
  • Llama a la función diamondCut para añadir FacetA

En tu terminal, ve al directorio raíz del proyecto y ejecuta el comando «npx hardhat compile»; deberías obtener una respuesta similar a esta:

A continuación, para implementar los contratos, ejecuta el comando: npx hardhat run scripts/deploy.js --network goerli. La implementación puede tardar un par de minutos, pero cuando haya finalizado, verás en la terminal las direcciones de cada uno de los contratos implementados.

A continuación, vamos a implementar el contrato Facet. En tu carpeta «scripts», crea un archivo llamado «deployFacet.js» e introduce el siguiente código:

/* global ethers */
/* eslint prefer-const: "off" */

async function deployFacet() {
const FacetA = await ethers.getContractFactory('FacetA');
const facetA = await FacetA.deploy();
await facetA.deployed();
console.log('facetA deployed:', facetA.address);

return facetA.address;
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
deployFacet().catch((error) => {
console.error(error);
process.exitCode = 1;
});

Guarda el archivo y ejecuta el comando «npx hardhat run scripts/deployFacet.js --network goerli» para realizar el despliegue. El resultado debería incluir la dirección de tu contrato FacetA desplegado:

Antes de añadir nuestra Facet a Diamond, comprobemos el código fuente en Etherscan. Ejecuta el siguiente comando con la dirección de tu contrato inteligente FacetA:

npx hardhat verify --network goerli DEPLOYED_CONTRACT_ADDRESS

Recibirás un enlace a una página de Etherscan en la que podrás consultar tu código fuente verificado.

Ahora que todos los contratos necesarios están desplegados, tendrás que utilizar la función diamondCut para añadir tu contrato Facet (FacetA.sol) a tu Diamond. Para ello, utilizaremos louper.dev (una herramienta para inspeccionar e interactuar con los contratos inteligentes de Diamond). Accede a louper.dev e introduce la dirección de tu contrato Diamond y la red en la que lo has desplegado (por ejemplo, goerli).

A continuación, haz clic en la pestaña «Editar» y, después, en el botón «Conectar monedero ». Una vez conectado el monedero, haz clic en el botón «Añadir Facet » e introduce la dirección de FacetA que habías desplegado anteriormente. A continuación, haz clic en el botón «Obtener ABI de Facet ».

Después de hacer clic en «Fetch Facet Info», selecciona las dos funciones y haz clic en «Upgrade Diamond» (tendrás que autorizar la transacción en tu monedero).

Esta transacción llama a la diamondCut función del contrato Diamond.

Una vez confirmada la transacción, podrás pasar a la siguiente sección, donde probarás la faceta recién añadida en tu contrato Diamond.

Pruebas del contrato «Diamond»

Ahora que nuestro contrato «Diamond» tiene información sobre nuestro contrato «FacetA», podemos probar las funciones «setDataA » y «getDataA ». Ve a la pestaña «Write» de tu contrato «Diamond» en louper.dev y conecta tu monedero. Selecciona «FacetA» en el menú desplegable, haz clic en la sección para expandirla e introduce el valor 0x68656c6c6f206469616d6f6e6473000000000000000000000000000000000000 (que se convierte en «hello diamonds» en formato de cadena descodificada). Por último, firma la transacción en tu monedero MetaMask.

Una vez confirmada la transacción, ve a la pestaña «Read» de tu contrato Diamond en louper.dev. A continuación, selecciona «FacetA» en la lista desplegable y haz clic en el botón «Query» de la faceta «getDataA ». ¡Deberías ver la cadena que habías establecido anteriormente!

Reflexiones finales

¡Enhorabuena! Ahora ya sabes más sobre el estándar Diamond y cómo aplicarlo. ¿Tienes alguna idea, alguna pregunta o te apetece presumir de lo que has aprendido? Cuéntanoslo en Discord o ponte en contacto con nosotros a través de Twitter.

¡Nos encanta recibir comentarios!

Si tienes algún comentario o pregunta sobre esta guía, háznoslo saber. ¡Nos encantaría saber tu opinión!

Comparte esta guía