Es bien sabido que muchas cadenas de bloques tienen problemas de escalabilidad y congestión. Estos problemas tienen efectos de gran alcance, desde tiempos de transacción lentos hasta tarifas de transacción más altas y una experiencia de usuario degradada.
Una solución es que web3 sea multicadena usando cadenas L2 (capa dos). Los L2 de Ethereum, como Optimism , Arbitrum y Polygon , se construyen sobre la red de Ethereum, pero son más rápidos y económicos que Ethereum.
Sin embargo, como compensación, a menudo son menos seguros que Ethereum. Es por eso que los L2 manejan las actividades diarias de los usuarios mientras aún confían en Ethereum L1 como una base detrás de escena para una capa de disponibilidad de datos y liquidación segura y descentralizada.
Esta es una gran solución; sin embargo, hay muchos L2 solo en Ethereum; cada uno una red independiente con sus propios matices y experiencias.
Crear y usar dapps que interactúen y se muevan entre estas redes y Ethereum L1 puede ser tedioso, difícil y una mala experiencia para usuarios y desarrolladores.
Lo que necesitamos es que web3 se convierta en una experiencia multicadena , donde los consumidores no necesiten saber qué cadena están usando (y, francamente, no les importa) y donde los desarrolladores puedan confiar en la red que mejor se adapte a las necesidades de sus dapps. .
Al pasar a esta Internet multicadena de cadenas de bloques , web3 se convierte en una mejor experiencia para todos los involucrados.
Desafortunadamente, permitir que los dapps se muevan entre cadenas es un desafío técnico difícil. En este artículo, veremos una solución: usar puntos finales de Infura RPC y Truffle Boxes para construir y unir estas redes sin problemas.
Específicamente, usaremos Optimism Bridge Truffle Box para crear un proyecto en la red de prueba Ethereum Goerli y un puente con Optimism Goerli.
Como núcleo de nuestra solución de ejemplo, nos basaremos en Truffle Boxes : plantillas de "acceso directo" (como contratos, bibliotecas, módulos e incluso dapps totalmente funcionales) de ConsenSys que puede usar para crear su dapp.
Para soluciones multicadena, se construyen sobre Infura RPC Nodes para muchas de las redes L2.
Como se mencionó anteriormente, confiaremos específicamente en Optimism Bridge Truffle Box . Este cuadro tiene todos los contratos necesarios para interactuar con Optimism Bridge desde L1 y L2, y un conjunto de migraciones para implementar, llamar a funciones y pasar mensajes/valores entre las capas.
Incluso tiene un script de ayuda que hace todo lo que necesitamos para ver todo esto en acción. ¡Simplemente tenemos que abrirlo para obtener todo lo que necesitamos! Según Trufflesuite.com, la caja incluye:
Nota: un puente es una herramienta que permite que cadenas de bloques independientes se comuniquen entre sí, envíen tokens, NFT, etc.
Antes de comenzar, necesitamos los siguientes requisitos previos:
node -v && npm -v
Una vez que haya cumplido con los requisitos previos, visite el sitio web de Infura para iniciar sesión (o regístrese para obtener una nueva cuenta).
Después de registrarse con éxito, la página redirige al panel de control de Infura, donde podemos crear una nueva clave de API, como se muestra a continuación.
Haga clic en el botón "Crear una nueva clave" y complete la información requerida.
Después de crear su clave de API, la ID de su proyecto estará visible en su panel de control en la sección CLAVE DE API, como se muestra a continuación. Cópielo y guárdelo en algún lugar; lo necesitará más adelante en este tutorial.
A continuación, configuraremos una caja de puente de optimismo de trufa . Podemos ejecutar el comando unbox en cualquier directorio de su elección usando el siguiente comando.
npx truffle unbox optimism-bridge <DIRECTORY_NAME>
Reemplace <NOMBRE_DIRECTORIO> con el nombre del directorio de su elección. Alternativamente, puede instalar Truffle globalmente y ejecutar el comando unbox.
npm install -g truffle truffle unbox optimism-bridge <DIRECTORY_NAME>
El comando debe descargar y ejecutar npm install como parte del proceso de desempaquetado.
Ahora, ejecute el siguiente comando para cambiar el directorio al nuevo que acabamos de crear.
cd truffle-bridge-demo
Nota: truffle-bridge-demo es el nombre de nuestro directorio que se creó.
Deberíamos tener algo similar a lo que aparece a continuación.
Él . El paquete dotenv
npm se instaló, pero necesitaremos agregar cierta información al archivo .env creado después de desempaquetarlo.
El archivo truffle-config.ovm.js
espera que exista un valor GOERLI_MNEMONIC en el archivo .env para ejecutar comandos en las redes de prueba Ethereum Goerli y Optimism Goerli y una INFURA_KEY para conectarse a la red.
GOERLI_MNEMONIC="<your-wallet-mnemonic>" INFURA_KEY="<your-infura-key>"
Reemplace <your-infura-key> con la información que obtuvimos anteriormente de nuestro tablero de Infura. ( Nota : nunca comparta sus claves privadas (mnemotécnicas) con nadie y manténgalas seguras). Y reemplace <your-wallet-mnemonic> con su mnemotécnico como se ve a continuación:
Para recuperar el mnemotécnico de Metamask, haga clic en el icono que se muestra a continuación en su Metamask.
A continuación, haga clic en el botón Exportar clave privada para copiar el mnemotécnico.
Git ignora el archivo .env en este proyecto para ayudar a proteger sus datos privados. Es una buena práctica de seguridad evitar revelar sus claves privadas a GitHub.
Cuando desempaquetamos el proyecto, se crearon todos los contratos y guiones necesarios para nuestro proyecto. En este próximo paso, veamos los contratos individuales y las migraciones para comprender cómo se establecen los puentes y las interacciones entre las redes.
El contrato contract/ethereum/GreeterL1.sol
le muestra cómo enviar un mensaje a través del puente Optimism de L1 a L2.
//SPDX-License-Identifier: Unlicense // This contract runs on L1, and controls a Greeter on L2. pragma solidity ^0.8.0; import { ICrossDomainMessenger } from "@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol"; contract GreeterL1 { address crossDomainMessengerAddr = 0x5086d1eEF304eb5284A0f6720f79403b4e9bE294; address greeterL2Addr = 0xC0836cCc8FBa87637e782Dde6e6572aD624fb984; function setGreeting(string calldata _greeting) public { bytes memory message; message = abi.encodeWithSignature("setGreeting(string)", _greeting); ICrossDomainMessenger(crossDomainMessengerAddr).sendMessage( greeterL2Addr, message, 1000000 // within the free gas limit amount ); } // function setGreeting } // contract GreeterL1
La migraciónmigrations migrations/3_set_L2_greeting.js
utiliza el contrato anterior para enviar un mensaje de Ethereum a Optimism.
var Greeter = artifacts.require("GreeterL1"); /** * Set L2 Greeting * Run this migration on L1 to update the L1 greeting. */ module.exports = async function (deployer) { console.log("Updating the L2 Greetings contract from L1! 👋👋"); const instance = await Greeter.deployed(); const tx = await instance.setGreeting("👋 Greetings from Truffle!"); console.log(`🙌 Greeter txn confirmed on L1! ${tx.receipt.transactionHash}`); console.log(`🛣️ Bridging message to L2 Greeter contract...`); console.log( `🕐 In about 1 minute, check the Greeter contract "read" function: https://goerli-optimism.etherscan.io/address/0xC0836cCc8FBa87637e782Dde6e6572aD624fb984#readContract` ); };
A continuación, el contracts/optimism/GreeterL2.sol
envía un mensaje en la otra dirección (L2->L1) a través del puente Optimism.
//SPDX-License-Identifier: Unlicense // This contract runs on L2, and controls a Greeter on L1. pragma solidity ^0.8.0; import { ICrossDomainMessenger } from "@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol"; contract GreeterL2 { address crossDomainMessengerAddr = 0x4200000000000000000000000000000000000007; address greeterL1Addr = 0x7fA4D972bB15B71358da2D937E4A830A9084cf2e; function setGreeting(string calldata _greeting) public { bytes memory message; message = abi.encodeWithSignature("setGreeting(string)", _greeting); ICrossDomainMessenger(crossDomainMessengerAddr).sendMessage( greeterL1Addr, message, 1000000 // irrelevant here ); } // function setGreeting } // contract GreeterL2
La migraciónmigrations migrations/4_set_L1_greeting.js
utiliza el contrato anterior para enviar un mensaje de Optimism a Ethereum.
require("dotenv").config(); const sdk = require("@eth-optimism/sdk"); const ethers = require("ethers"); const Greeter = artifacts.require("GreeterL2"); const goerliMnemonic = process.env["GOERLI_MNEMONIC"]; const infuraKey = process.env["INFURA_KEY"]; const sleep = (milliseconds) => { return new Promise((resolve) => setTimeout(resolve, milliseconds)); }; /** * Set L1 Greeting * Run this migration on L1 to update the L1 greeting. */ module.exports = async function (deployer) { const newGreeting = "👋 Greetings from Truffle!"; //<---- CHANGE THIS VALUE TO YOUR NAME!!! const instance = await Greeter.deployed(); console.log("Updating the L1 Greetings contract from L2! 👋"); const tx = await instance.setGreeting(newGreeting); const txHash = tx.receipt.transactionHash; console.log(`🙌🙌 Greeter txn confirmed on L2! ${txHash}`); console.log( `🛣️ Bridging message to L1 Greeter contract.\n 🕐 This will take at least 1-5 min...` ); // Set providers for Optimism sdk const l1Provider = new ethers.providers.JsonRpcProvider( "https://goerli.infura.io/v3/" + infuraKey ); const l2Provider = new ethers.providers.JsonRpcProvider( "https://optimism-goerli.infura.io/v3/" + infuraKey ); // Connect an L1 signer const wallet = ethers.Wallet.fromMnemonic(goerliMnemonic); const l1Signer = wallet.connect(l1Provider); // Initialize sdk messenger const crossChainMessenger = new sdk.CrossChainMessenger({ l1ChainId: 5, l2ChainId: 420, l1SignerOrProvider: l1Signer, l2SignerOrProvider: l2Provider, }); let statusReady = false; // Sleep for 1 min during L2 -> L1 bridging await sleep(60000); // 60 seconds // Poll the L1 msg status while (!statusReady) { let status = null; status = await crossChainMessenger.getMessageStatus(txHash); statusReady = status == sdk.MessageStatus.READY_FOR_RELAY; if (!statusReady) { console.log( "Message not yet received on L1.\n 🕐 Retrying in 10 seconds..." ); await sleep(10000); // 10 seconds } } console.log("📬 Message received! Finalizing..."); // Open the message on L1 finalize = await crossChainMessenger.finalizeMessage(txHash); console.log( `🎉 Message finalized. Check the L1 Greeter contract "read" function: https://goerli.etherscan.io/address/0x7fA4D972bB15B71358da2D937E4A830A9084cf2e#readContract` ); };
En el directorio de scripts, también tenemos goerli_bridge_message.mjs
y goerli_bridge_value.js
para automatizar el proceso de compilación de contratos, ejecución de migraciones y envío de mensajes.
A continuación, implementaremos nuestro contrato en Goerli. El script de ayuda facilita la compilación, la migración y el puente de mensajes entre Ethereum Goerli y Optimism Goerli.
En esas redes, necesitaremos testnet ETH para usarlo. Para recibir algunos, use un grifo . También necesitaremos agregar el complemento Optimism a su cuenta de Infura.
A continuación, ejecutaremos el siguiente comando para iniciar el proyecto.
npm run deploy
A continuación se muestra una URL para confirmar (a través de Etherscan) el mensaje en puente después de la migración completa.
Se proporcionará un enlace para confirmar el mensaje en puente a través de Etherscan al completar la cuarta migración.
Hemos configurado, instalado, construido, implementado y recorrido con éxito el proyecto que desempaquetamos anteriormente. A continuación, verificaremos el proyecto en la red de prueba de Goerli Ethereum.
Diríjase al explorador de bloques Goerli Etherscan y pegue la dirección txn 0xbcc1746a9ebbfcfb71665225c1a353a8c8dc9a1aa528a3babcb5b046d615a353 que se mostró en nuestra CLI durante la implementación.
Un mundo web3 multicadena es crucial si queremos que la experiencia del usuario y del desarrollador siga mejorando. Y para lograrlo, necesitamos formas para que las dapps se comuniquen entre cadenas de forma rápida y sin problemas.
Con suerte, el ejemplo que vimos usando Optimism Bridge Truffle Box le mostró una manera relativamente fácil y rápida de comenzar. Para obtener más información, consulta la documentación oficial .
¡Que tengas un gran día!