Implementar un puente EVM cruzado entre cadenas
Este tutorial es para fines de demostración sobre cómo construir un puente cruzado entre cadenas. No es para uso en producción. Debes asumir la responsabilidad total de garantizar la seguridad de tu puente.
Introducción
En este tutorial, estaremos construyendo un puente entre WAGMI y Fuji. Este puente nos ayudará a transferir la moneda nativa WGM envuelta en wWGM de ida y vuelta desde la cadena WAGMI a la cadena Fuji. Usando esta guía, tú puedes implementar un puente entre cualquier cadena basada en EVM para cualquier token ERC20.
La versión envuelta de una moneda nativa es su representación ERC20 anclada. Envolverla con el estándar ERC20 facilita ciertos procesos como transacciones delegadas. Puedes obtener fácilmente tokens envueltos enviando la moneda nativa a la dirección del contrato de token envuelto.
WAGMI es una cadena de prueba independiente basada en EVM desplegada en una Subnet personalizada en la red Avalanche.
Estaremos utilizando el repositorio de puentes de ChainSafe, para configurar fácilmente un puente robusto y seguro.
Flujo de trabajo del puente
Las cadenas WAGMI y Fuji no están interconectadas por defecto, sin embargo, podríamos hacer que se comuniquen. Los relayers observan eventos (mediante la consulta de bloques) en una cadena y realizan la acción necesaria utilizando esos eventos en la otra cadena. De esta manera, también podemos realizar el puente de tokens de una cadena a la otra cadena a través del uso de contratos inteligentes.
Aquí está el flujo de trabajo de alto nivel básico del puente -
- Los usuarios depositan tokens en el contrato del puente
- El contrato del puente le pide al contrato del controlador que realice la acción de depósito
- El contrato del controlador bloquea el token depositado en la caja fuerte del token
- El contrato del puente emite el evento
Deposit
- El relayer recibe el evento
Deposit
desde la cadena fuente - El relayer crea una propuesta de votación en la cadena de destino para acuñar un nuevo token
- Después de que los relayers alcanzan el umbral de votos, se ejecuta la propuesta
- Los tokens son acuñados a la dirección del receptor
El puente de tokens desde la cadena fuente a la cadena de destino implica el enfoque de bloquear y acuñar. Mientras que el puente de tokens desde la cadena de destino a la cadena fuente implica el enfoque de quemar y liberar. No podemos acuñir y quemar tokens que no controlamos. Por lo tanto, los bloqueamos en la caja fuerte de tokens en la cadena fuente. Y acuñamos el token correspondiente (que desplegaremos y, por lo tanto, controlaremos) en la cadena de destino.
Requisitos
Estos son los requisitos para seguir este tutorial -
- Configurar WAGMI y Fuji en Core
- Importar el token
wWGM
(activo) en la red WAGMI (Core). Aquí está la dirección -0x3Ee7094DADda15810F191DD6AcF7E4FFa37571e4
- Monedas
WGM
en la cadena WAGMI. Gotea1 WGM
desde el WAGMI Faucet. - Monedas
AVAX
en la cadena Fuji. Gotea10 AVAX
desde el Fuji Faucet. Si ya tienes un saldo de AVAX mayor que cero en Mainnet, pega tu dirección de C-Chain allí y solicita tokens de prueba. De lo contrario, por favor solicita un cupón de faucet en Guild. Los administradores y moderadores en el Discord oficial pueden proporcionar AVAX de testnet si los desarrolladores no pueden obtenerlo de las otras dos opciones. - Tokens
WGM
envueltos en la cadena WAGMI. Envía algunas monedasWGM
a la dirección del tokenwWGM
(ver segundo punto), para recibir la misma cantidad dewWGM
. Siempre mantén algunas monedasWGM
, para cubrir las tarifas de transacción.
Configuración del entorno
Creemos un nuevo directorio deploy-bridge
, donde guardaremos nuestros códigos de puente. Estaremos
utilizando los siguientes repositorios -
ChainSafe/chainbridge-deploy
- Esto nos ayudará a configurar nuestros contratos de puenteChainSafe/ChainBridge
- Esto nos ayudará a configurar nuestro relayer fuera de la cadena.
Instalando la herramienta de línea de comandos de ChainBridge
Usando el siguiente comando, podemos clonar e instalar la herramienta de línea de comandos de ChainBridge. Esto nos ayudará a configurar los contratos de puente y demostrar transferencias de puente. Una vez que los contratos de puente estén desplegados, puedes usar su ABI y dirección de contrato para configurar tu interfaz de usuario.
git clone -b v1.0.0 --depth 1 https://github.com/ChainSafe/chainbridge-deploy \
&& cd chainbridge-deploy/cb-sol-cli \
&& npm install \
&& make install
Esto construirá los contratos e instalará el comando cb-sol-cli
.
Configurando variables de entorno
Configuremos las variables de entorno para no tener que escribir sus valores cada vez que
emitimos un comando. Vuelve al directorio deploy-bridge
(directorio principal del proyecto) y crea un
nuevo archivo configVars
. Coloca el siguiente contenido dentro de él -
SRC_GATEWAY=https://subnets.avax.network/wagmi/wagmi-chain-testnet/rpc
DST_GATEWAY=https://api.avax-test.network/ext/bc/C/rpc
SRC_ADDR="<Tu dirección en WAGMI>"
SRC_PK="<tu clave privada en WAGMI>"
DST_ADDR="<Tu dirección en Fuji>"
DST_PK="<tu clave privada en Fuji>"
SRC_TOKEN="0x3Ee7094DADda15810F191DD6AcF7E4FFa37571e4"
RESOURCE_ID="0x00"
SRC_ADDR
yDST_ADDR
son las direcciones que desplegarán los contratos de puente y actuarán como relayers.SRC_TOKEN
es el token que queremos puentear. Aquí está la dirección de la versión envuelta ERC20 de la moneda WGM aka wWGM.RESOURCE_ID
podría ser cualquier cosa. Identifica nuestros tokens ERC20 puenteados en ambos lados (WAGMI y Fuji).
Cada vez que hagamos cambios en estas variables de configuración, tenemos que actualizar nuestro entorno bash. Ejecuta
el siguiente comando según la ubicación relativa del archivo. Estas variables son temporales
y solo están allí en la sesión terminal actual, y se eliminarán una vez que la sesión termine.
Asegúrate de cargar estas variables de entorno en cualquier lugar donde las vayas a usar en los comandos bash
(como $SRC_GATEWAY
o $SRC_ADDR
)
source ./configVars
Configurando la Cadena Fuente
Necesitamos configurar nuestra cadena fuente de la siguiente manera -
- Desplegar contratos de puente y controlador con
$SRC_ADDR
como relayer predeterminado y único - Registrar el token
wWGM
como un recurso en el puente
Desplegar Contratos Fuente
La herramienta de línea de comandos cb-sol-cli
nos ayudará a desplegar los contratos. Ejecuta el siguiente comando
en la sesión de terminal donde se cargan las variables de configuración. Agregará SRC_ADDR
como el relayer predeterminado
para relayar eventos desde la cadena WAGMI (fuente) a la cadena Fuji (destino).
Uno de los parámetros más importantes a tener en cuenta al implementar un contrato de puente es el valor de expiry
. Es el número de bloques después de los cuales una propuesta se considera cancelada. De forma predeterminada, está establecido en 100
. En Avalanche Mainnet, con este valor, las propuestas podrían expirar en 3-4 minutos. Deberías elegir un valor de vencimiento muy grande, según la cadena en la que estás implementando el puente. De lo contrario, tu propuesta se cancelará si no se reciben el número umbral de propuestas de voto a tiempo.
También debes tener en cuenta que a veces, durante una alta actividad de red, una transacción puede quedarse atascada durante mucho tiempo. Las transacciones de propuesta atascadas en este escenario podrían resultar en la cancelación de propuestas anteriores. Por lo tanto, los valores de vencimiento deben ser lo suficientemente grandes y los relayers deben emitir transacciones con un precio máximo de gas competitivo.
cb-sol-cli --url $SRC_GATEWAY --privateKey $SRC_PK --gasPrice 25000000000 deploy \
--bridge --erc20Handler \
--relayers $SRC_ADDR \
--relayerThreshold 1 \
--expiry 500 \
--chainId 0
La salida devolverá las direcciones de los contratos desplegados (Puente y Handler). Actualiza el archivo configVars
con estas direcciones agregando las siguientes 2 variables y cargándolas en el entorno.
SRC_BRIDGE="<dirección del contrato de puente resultante>"
SRC_HANDLER="<dirección del contrato de handler erc20 resultante>"
Asegúrate de cargarlas usando el comando source
.
Configurar Recurso en el Puente
Ejecuta el siguiente comando para registrar el token wWGM
como un recurso en el puente fuente.
cb-sol-cli --url $SRC_GATEWAY --privateKey $SRC_PK --gasPrice 25000000000 bridge register-resource \
--bridge $SRC_BRIDGE \
--handler $SRC_HANDLER \
--resourceId $RESOURCE_ID \
--targetContract $SRC_TOKEN
Configurando la Cadena de Destino
Necesitamos configurar nuestra cadena de destino de la siguiente manera:
- Desplegar el contrato de Puente y Handler con
$DST_ADDR
como relayer predeterminado y único - Desplegar el contrato ERC20 mintable y burnable que representa el token
wWGM
bridged - Registrar el token
wWGM
como un recurso en el puente - Registrar el token
wWGM
como mintable/burnable en el puente - Dar permisos al contrato Handler para mintear nuevos tokens
wWGM
Desplegar Contratos de Destino
Ejecuta el siguiente comando para desplegar los contratos de Puente, Handler y el token wWGM
en la cadena Fuji. Nuevamente, establecerá DST_ADDR
como el relayer predeterminado para relayer eventos desde la cadena Fuji (destino) a la cadena WAGMI (fuente). Para este ejemplo, tanto SRC_ADDR
como DST_ADDR
representan lo mismo.
cb-sol-cli --url $DST_GATEWAY --privateKey $DST_PK --gasPrice 25000000000 deploy\
--bridge --erc20 --erc20Handler \
--relayers $DST_ADDR \
--relayerThreshold 1 \
--chainId 1
Actualiza las variables de entorno con los detalles que obtendrás al ejecutar el comando anterior. No olvides cargar estas variables.
DST_BRIDGE="<dirección del contrato de puente resultante>"
DST_HANDLER="<dirección del contrato de handler erc20 resultante>"
DST_TOKEN="<dirección del contrato de token erc20 resultante>"
Configurando Recurso en el Puente
Ejecuta el siguiente comando para registrar el token wWGM
desplegado como un recurso en el puente.
cb-sol-cli --url $DST_GATEWAY --privateKey $DST_PK --gasPrice 25000000000 bridge register-resource \
--bridge $DST_BRIDGE \
--handler $DST_HANDLER \
--resourceId $RESOURCE_ID \
--targetContract $DST_TOKEN
Configurando el Token como Mintable y Burnable en el Puente
El puente tiene dos opciones cuando recibe un depósito de un token:
- Bloquear el token recibido en una cadena y mintear el token correspondiente en la otra cadena
- Quemar el token recibido en una cadena y liberar el token correspondiente en la otra cadena
No podemos mintear o quemar ningún token que no controlemos. Aunque podemos bloquear y liberar dichos tokens poniéndolos en una caja de seguridad de tokens. El puente tiene que saber qué token puede quemar. Con el siguiente comando, podemos establecer el recurso como burnable. El puente elegirá la acción en consecuencia, viendo el token como burnable o no.
cb-sol-cli --url $DST_GATEWAY --privateKey $DST_PK --gasPrice 25000000000 bridge set-burn \
--bridge $DST_BRIDGE \
--handler $DST_HANDLER \
--tokenContract $DST_TOKEN
Autorizando al Handler a Mintear Nuevos Tokens
Ahora permitamos que el handler mintee el token ERC20 (wWGM) desplegado en la cadena de destino. Ejecuta el siguiente comando.
cb-sol-cli --url $DST_GATEWAY --privateKey $DST_PK --gasPrice 25000000000 erc20 add-minter \
--minter $DST_HANDLER \
--erc20Address $DST_TOKEN
El desplegador de los contratos (aquí
SRC_ADDR
oDST_ADDR
) tiene los derechos de administrador. Un administrador puede agregar o eliminar un nuevo relayer, minter, admin, etc. También puede mintear nuevos tokens ERC20 en la cadena de destino. Puedes emitir estos comandos usandocb-sol-cli
con las opciones mencionadas en estos archivos. El comando de minteo no debe usarse manualmente, a menos que se requiera alguna intervención, cuando los relayers no pudieron mintear los tokens en la cadena de destino a tiempo.
Desplegar Relayer
Todas las configuraciones en cadena como desplegar puentes, handlers, tokens, etc. están completas. Pero las dos cadenas no están interconectadas. Necesitamos algún relayer fuera de cadena para comunicar mensajes entre las cadenas. El relayer buscará eventos de depósito en una cadena y enviará propuestas de voto para mintear o liberar el token correspondiente en otra cadena.
Dado que establecimos el umbral de relayers en 1, al desplegar el puente y el handler, requerimos una propuesta de voto de solo 1 relayer. Pero en producción, deberíamos usar un gran conjunto de relayers con un umbral alto para evitar la concentración de poder.
Con este propósito, utilizaremos el relayer de ChainSafe. Sigue los pasos descritos a continuación para desplegar el relayer.
Clonar y Construir el Relayer
Abre una nueva sesión de terminal, manteniendo la sesión anterior cargada con las variables de entorno. También debemos cargar las variables de entorno en esta sesión. Cárgalas en esta sesión también usando el comando source
.
Ahora, muévete al directorio deploy-bridge
y ejecuta el siguiente comando para clonar el repositorio del relayer (implementado en Go) y construir su binario.
git clone -b v1.1.1 --depth 1 https://github.com/ChainSafe/chainbridge \
&& cd chainbridge \
&& make build
Esto creará un binario dentro del directorio chainbridge/build
como chainbridge
.
Configurando el Relayer
El relayer requiere algunas configuraciones como cadena fuente, cadena de destino, dirección de puente, handler, etc. Ejecuta el siguiente comando. Creará un archivo config.json
con los detalles requeridos. Puedes actualizar estos detalles según tus necesidades.
echo "{
\"chains\": [
{
\"name\": \"WAGMI\",
\"type\": \"ethereum\",
\"id\": \"0\",
\"endpoint\": \"$SRC_GATEWAY\",
\"from\": \"$SRC_ADDR\",
\"opts\": {
\"bridge\": \"$SRC_BRIDGE\",
\"erc20Handler\": \"$SRC_HANDLER\",
\"genericHandler\": \"$SRC_HANDLER\",
\"gasLimit\": \"1000000\",
\"maxGasPrice\": \"50000000000\",
\"http\": \"true\",
\"blockConfirmations\":\"0\"
}
},
{
\"name\": \"Fuji\",
\"type\": \"ethereum\",
\"id\": \"1\",
\"endpoint\": \"$DST_GATEWAY\",
\"from\": \"$DST_ADDR\",
\"opts\": {
\"bridge\": \"$DST_BRIDGE\",
\"erc20Handler\": \"$DST_HANDLER\",
\"genericHandler\": \"$DST_HANDLER\",
\"gasLimit\": \"1000000\",
\"maxGasPrice\": \"50000000000\",
\"http\": \"true\",
\"blockConfirmations\":\"0\"
}
}
]
}" >> config.json
Verifica y confirma los detalles en el archivo config.json
.
En el comando anterior, puedes ver que
blockConfirmations
está configurado en0
. Esto funcionará bien para redes como Avalanche porque el bloque se confirma una vez que se ha comprometido. A diferencia de otras cadenas como Ethereum, que requiere 20-30 confirmaciones de bloque. Por lo tanto, utiliza esta configuración con precaución, dependiendo del tipo de cadena que estés utilizando.Puede causar problemas graves si se acuña o se libera un token correspondiente basado en un bloque no confirmado.
Configurar claves
Dale acceso al relayer a tus claves. Usando estas claves, el relayer propondrá eventos de depósito y ejecutará propuestas. Pedirá establecer una contraseña para encriptar estas claves. Cada vez que inicies el relayer, pedirá esta contraseña.
./build/chainbridge accounts import --privateKey $SRC_PK
./build/chainbridge accounts import --privateKey $DST_PK
Probemos el puente
La configuración está ahora completa, tanto en la cadena como fuera de ella. Ahora solo tenemos que iniciar el relayer y probar el puente. Para fines de prueba, usaremos cb-sol-cli
para hacer transacciones de depósito en el puente. Pero puedes crear tu propia interfaz y integrarla con el puente utilizando los ABIs.
Iniciar el relayer
Ejecuta el siguiente comando para iniciar el relayer. Imprimirá registros de todos los eventos asociados a nuestro puente, que ocurren en ambas cadenas. Así que mantén el relayer en funcionamiento y sigue los siguientes comandos en otra sesión de terminal.
./build/chainbridge --config config.json --verbosity trace --latest
Aprobar al Handler para gastar mis tokens
Ahora, depositemos tokens en el puente WAGMI. Pero antes de eso, necesitamos aprobar al handler para que gaste (bloquee o queme) tokens en nuestro nombre (aquí SRC_PK
). La cantidad aquí está en Wei (1 ether (WGM) = 10^18 Wei). Aprobaremos 0.1 wWGM.
cb-sol-cli --url $SRC_GATEWAY --privateKey $SRC_PK --gasPrice 25000000000 erc20 approve \
--amount 100000000000000000 \
--erc20Address $SRC_TOKEN \
--recipient $SRC_HANDLER
Depositar tokens en el puente
Una vez aprobado, podemos enviar una transacción de depósito. Ahora depositemos 0.1 wWGM en el puente. El handler bloqueará (transferirá a la caja fuerte de tokens) 0.1 wWGM desde nuestra dirección (aquí SRC_PK
) y acuñará los nuevos tokens en la cadena de destino para el destinatario (aquí DST_ADDR
).
cb-sol-cli --url $SRC_GATEWAY --privateKey $SRC_PK --gasPrice 25000000000 erc20 deposit \
--amount 100000000000000000 \
--dest 1 \
--bridge $SRC_BRIDGE \
--recipient $DST_ADDR \
--resourceId $RESOURCE_ID
Esta transacción transferirá 0.1 wWGM a la caja fuerte de tokens y emitirá un evento Deposit
, que será capturado por el relayer. Siguiendo este evento, enviará una propuesta de votación a la cadena de destino. Dado que el umbral es 1, el puente ejecutará la propuesta y acuñará nuevos wWGM a la dirección del destinatario. Aquí tienes una captura de pantalla de la salida del relayer.
De manera similar, podemos transferir los tokens de vuelta a la cadena WAGMI.
Conclusión
Similar al proceso anterior, puedes desplegar un puente entre cualquier par de cadenas basadas en EVM. Hemos utilizado la herramienta de línea de comandos para hacer aprobaciones y depósitos. Esto se puede extender aún más para construir una interfaz integrada con el puente. Actualmente, depende de un único relayer, que no es seguro. Necesitamos un gran conjunto de relayers y un umbral alto para evitar cualquier tipo de centralización.
Puedes aprender más sobre estos contratos e implementaciones leyendo la documentación de ChainBridge de ChainSafe.
Was this page helpful?