# Cosmos SDK Module Source: https://docs.hyperlane.xyz/docs/alt-vm-implementations/cosmos-sdk The SDK module enables seamless interchain communication by integrating Hyperlane directly into Cosmos SDK-based chains. This module provides a permissionless way for Cosmos chains to communicate with external ecosystems, including EVM and other blockchains. While Hyperlane already supports Cosmos chains via [CosmWasm](https://github.com/many-things/cw-hyperlane?tab=readme-ov-file), this module expands accessibility by enabling Cosmos SDK chains—regardless of CosmWasm support—to leverage Hyperlane’s interoperability capabilities. ## Key Features * **Hyperlane Compatibility:** This module fully implements the Hyperlane messaging protocol, enabling seamless cross-chain functionality across all Hyperlane-compatible chains. * **Hyperlane Warp Routes (HWR):** Leveraging the core functionality, tokens can be created and transferred across all Hyperlane-compatible chains. * **End-to-End Interop Solution**: Implements messaging, transport, and security modules of the Hyperlane cross-chain interoperability framework for Cosmos SDK-based chains. * **Permissionless & Open-Source**: Anyone can deploy and configure the module to fit their needs without relying on intermediaries. * **Built by KYVE**: Developed by the [KYVE](https://www.kyve.network/) team to extend Cosmos interoperability beyond IBC. ## Module Overview /img/cosmos-sdk-implementation/hyperlane-cosmos (8).svg ### `x/core` The `core` module is intended to implement the fundamental functionalities of the Hyperlane protocol to dispatch and process messages, which can then be used by applications like `warp`. It includes mailboxes and registers hooks that are implemented in the submodules. #### Mailbox * Responsible for dispatching and processing messages * Ensures replay protection * Specifies `default` or `required` hooks like `IGP` or `MerkleTreeHook` * Calls registered `PostDispatch` hooks * Important methods: * `dispatch()` * `process()` ![/img/cosmos-sdk-implementation/hyperlane-cosmos (2).svg](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJiYWNrZ3JvdW5kOiAjZmZmZmZmOyBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOyBjb2xvci1zY2hlbWU6IGxpZ2h0OyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjE0MXB4IiBoZWlnaHQ9IjE4MXB4IiB2aWV3Qm94PSItMC41IC0wLjUgMTQxIDE4MSI+PGRlZnMvPjxyZWN0IGZpbGw9IiNmZmZmZmYiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHg9IjAiIHk9IjAiIHN0eWxlPSJmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7Ii8+PGc+PGcgZGF0YS1jZWxsLWlkPSIwIj48ZyBkYXRhLWNlbGwtaWQ9IjEiPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNzUiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTUzIj48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTU0Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy01NSIvPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTU3Ij48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTU4Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy01OSIvPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNjIiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTYwIi8+PC9nPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNzEiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTYzIj48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTY0Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy02NSIvPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTY2Ij48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTY3Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy02OCIvPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNjkiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTcwIi8+PC9nPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNzIiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTc4Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy03OSI+PGc+PHBhdGggZD0iTSAwIDMwIEwgMCAwIEwgMTQwIDAgTCAxNDAgMzAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0iYWxsIiBzdHlsZT0iZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBzdHJva2U6IHJnYigwLCAwLCAwKTsiLz48cGF0aCBkPSJNIDAgMzAgTCAwIDE4MCBMIDE0MCAxODAgTCAxNDAgMzAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgc3R5bGU9InN0cm9rZTogcmdiKDAsIDAsIDApOyIvPjxwYXRoIGQ9Ik0gMCAzMCBMIDE0MCAzMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIiBzdHlsZT0ic3Ryb2tlOiByZ2IoMCwgMCwgMCk7Ii8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxMzhweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxNXB4OyBtYXJnaW4tbGVmdDogMXB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBjZW50ZXI7IGNvbG9yOiAjMDAwMDAwOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7OyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+PGZvbnQ+TWFpbGJveDwvZm9udD48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iNzAiIHk9IjE5IiBmaWxsPSJsaWdodC1kYXJrKCMwMDAwMDAsICNmZmZmZmYpIiBmb250LWZhbWlseT0iJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7IiBmb250LXNpemU9IjEycHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPk1haWxib3g8L3RleHQ+PC9zd2l0Y2g+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTgwIj48Zz48cmVjdCB4PSIwIiB5PSIzMCIgd2lkdGg9IjE0MCIgaGVpZ2h0PSIzMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBmbGV4LXN0YXJ0OyB3aWR0aDogMTMwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNDVweDsgbWFyZ2luLWxlZnQ6IDZweDsiPjxkaXYgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMDsgdGV4dC1hbGlnbjogbGVmdDsgbWF4LWhlaWdodDogMjZweDsgb3ZlcmZsb3c6IGhpZGRlbjsgY29sb3I6ICMwMDAwMDA7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtIZWx2ZXRpY2EmcXVvdDs7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyB3b3JkLXdyYXA6IG5vcm1hbDsgIj48c3BhbiBzdHlsZT0idGV4dC13cmFwLW1vZGU6IG5vd3JhcDsiPmlkPC9zcGFuPjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI2IiB5PSI0OSIgZmlsbD0ibGlnaHQtZGFyaygjMDAwMDAwLCAjZmZmZmZmKSIgZm9udC1mYW1pbHk9IiZxdW90O0hlbHZldGljYSZxdW90OyIgZm9udC1zaXplPSIxMnB4Ij5pZDwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTgxIj48Zz48cmVjdCB4PSIwIiB5PSI2MCIgd2lkdGg9IjE0MCIgaGVpZ2h0PSIzMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBmbGV4LXN0YXJ0OyB3aWR0aDogMTMwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNzVweDsgbWFyZ2luLWxlZnQ6IDZweDsiPjxkaXYgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMDsgdGV4dC1hbGlnbjogbGVmdDsgbWF4LWhlaWdodDogMjZweDsgb3ZlcmZsb3c6IGhpZGRlbjsgY29sb3I6ICMwMDAwMDA7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtIZWx2ZXRpY2EmcXVvdDs7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyB3b3JkLXdyYXA6IG5vcm1hbDsgIj48c3BhbiBzdHlsZT0idGV4dC13cmFwLW1vZGU6IG5vd3JhcDsiPjxmb250Pm93bmVyPC9mb250Pjwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iNiIgeT0iNzkiIGZpbGw9ImxpZ2h0LWRhcmsoIzAwMDAwMCwgI2ZmZmZmZikiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCI+b3duZXI8L3RleHQ+PC9zd2l0Y2g+PC9nPjwvZz48L2c+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy04MiI+PGc+PHJlY3QgeD0iMCIgeT0iOTAiIHdpZHRoPSIxNDAiIGhlaWdodD0iMzAiIGZpbGw9Im5vbmUiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjwvZz48Zz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgZmxleC1zdGFydDsgd2lkdGg6IDEzMHB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEwNXB4OyBtYXJnaW4tbGVmdDogNnB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBsZWZ0OyBtYXgtaGVpZ2h0OiAyNnB4OyBvdmVyZmxvdzogaGlkZGVuOyBjb2xvcjogIzAwMDAwMDsgIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O0hlbHZldGljYSZxdW90OzsgY29sb3I6ICMwMDAwMDA7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IHdvcmQtd3JhcDogbm9ybWFsOyAiPmRlZmF1bHRfaXNtPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjYiIHk9IjEwOSIgZmlsbD0ibGlnaHQtZGFyaygjMDAwMDAwLCAjZmZmZmZmKSIgZm9udC1mYW1pbHk9IiZxdW90O0hlbHZldGljYSZxdW90OyIgZm9udC1zaXplPSIxMnB4Ij5kZWZhdWx0X2lzbTwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTgzIj48Zz48cmVjdCB4PSIwIiB5PSIxMjAiIHdpZHRoPSIxNDAiIGhlaWdodD0iMzAiIGZpbGw9Im5vbmUiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjwvZz48Zz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgZmxleC1zdGFydDsgd2lkdGg6IDEzMHB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEzNXB4OyBtYXJnaW4tbGVmdDogNnB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBsZWZ0OyBtYXgtaGVpZ2h0OiAyNnB4OyBvdmVyZmxvdzogaGlkZGVuOyBjb2xvcjogIzAwMDAwMDsgIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O0hlbHZldGljYSZxdW90OzsgY29sb3I6ICMwMDAwMDA7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IHdvcmQtd3JhcDogbm9ybWFsOyAiPmRlZmF1bHRfaG9vazwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI2IiB5PSIxMzkiIGZpbGw9ImxpZ2h0LWRhcmsoIzAwMDAwMCwgI2ZmZmZmZikiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCI+ZGVmYXVsdF9ob29rPC90ZXh0Pjwvc3dpdGNoPjwvZz48L2c+PC9nPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctODQiPjxnPjxyZWN0IHg9IjAiIHk9IjE1MCIgd2lkdGg9IjE0MCIgaGVpZ2h0PSIzMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBmbGV4LXN0YXJ0OyB3aWR0aDogMTMwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTY1cHg7IG1hcmdpbi1sZWZ0OiA2cHg7Ij48ZGl2IHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDA7IHRleHQtYWxpZ246IGxlZnQ7IG1heC1oZWlnaHQ6IDI2cHg7IG92ZXJmbG93OiBoaWRkZW47IGNvbG9yOiAjMDAwMDAwOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7OyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+cmVxdWlyZWRfaG9vazwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI2IiB5PSIxNjkiIGZpbGw9ImxpZ2h0LWRhcmsoIzAwMDAwMCwgI2ZmZmZmZikiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCI+cmVxdWlyZWRfaG9vazwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+) #### Submodules Interchain Security and Post Dispatch are submodules with dedicated keepers and restricted access to the core keeper. This architecture was designed to facilitate extensibility, allowing developers to integrate their own implementations seamlessly. #### `01_interchain_security` This submodule implements the ISM logic and is responsible for verifying that interchain messages being delivered on the destination chain were *actually sent* on the origin chain. The modular design allows developers to easily add custom ISM implementations. Currently, three ISM types are available: `MessageIdMultisig`, `MerkleRootMultisig`, and `Noop`. ``` type IInterchainSecurityModule interface { Verify(ctx context.Context, ismId HexAddress, metadata []byte, message HyperlaneMessage) (bool, error)} ``` **`MultisigIsm`** * Verifies that `m` of `n` validators have signed the validity of a message * `MessageIdMultisig` → censorship-friendly, minimizes gas * `MerkleRootMultisig` → censorship resistance guarantee * Important methods: * `verify()` ![/img/cosmos-sdk-implementation/hyperlane-cosmos (3).svg](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJiYWNrZ3JvdW5kOiAjZmZmZmZmOyBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOyBjb2xvci1zY2hlbWU6IGxpZ2h0OyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjE0MXB4IiBoZWlnaHQ9IjE1MXB4IiB2aWV3Qm94PSItMC41IC0wLjUgMTQxIDE1MSI+PGRlZnMvPjxyZWN0IGZpbGw9IiNmZmZmZmYiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHg9IjAiIHk9IjAiIHN0eWxlPSJmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7Ii8+PGc+PGcgZGF0YS1jZWxsLWlkPSIwIj48ZyBkYXRhLWNlbGwtaWQ9IjEiPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNzUiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTUzIj48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTU0Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy01NSIvPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTU3Ij48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTU4Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy01OSIvPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNjIiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTYwIi8+PC9nPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNzEiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTYzIj48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTY0Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy02NSIvPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTY2Ij48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTY3Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy02OCIvPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTcyIi8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy03OCIvPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNzkiPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctODAiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTgxIi8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy04MiIvPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctODMiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTg0Ii8+PC9nPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktMSI+PGc+PHBhdGggZD0iTSAwIDMwIEwgMCAwIEwgMTQwIDAgTCAxNDAgMzAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0iYWxsIiBzdHlsZT0iZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBzdHJva2U6IHJnYigwLCAwLCAwKTsiLz48cGF0aCBkPSJNIDAgMzAgTCAwIDE1MCBMIDE0MCAxNTAgTCAxNDAgMzAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgc3R5bGU9InN0cm9rZTogcmdiKDAsIDAsIDApOyIvPjxwYXRoIGQ9Ik0gMCAzMCBMIDE0MCAzMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIiBzdHlsZT0ic3Ryb2tlOiByZ2IoMCwgMCwgMCk7Ii8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxMzhweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxNXB4OyBtYXJnaW4tbGVmdDogMXB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBjZW50ZXI7IGNvbG9yOiAjMDAwMDAwOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7OyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+PGZvbnQ+TXVsdGlzaWcgSVNNPC9mb250PjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI3MCIgeT0iMTkiIGZpbGw9ImxpZ2h0LWRhcmsoIzAwMDAwMCwgI2ZmZmZmZikiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TXVsdGlzaWcgSVNNPC90ZXh0Pjwvc3dpdGNoPjwvZz48L2c+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0yIj48Zz48cmVjdCB4PSIwIiB5PSIzMCIgd2lkdGg9IjE0MCIgaGVpZ2h0PSIzMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBmbGV4LXN0YXJ0OyB3aWR0aDogMTMwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogNDVweDsgbWFyZ2luLWxlZnQ6IDZweDsiPjxkaXYgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMDsgdGV4dC1hbGlnbjogbGVmdDsgbWF4LWhlaWdodDogMjZweDsgb3ZlcmZsb3c6IGhpZGRlbjsgY29sb3I6ICMwMDAwMDA7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtIZWx2ZXRpY2EmcXVvdDs7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyB3b3JkLXdyYXA6IG5vcm1hbDsgIj48c3BhbiBzdHlsZT0idGV4dC13cmFwLW1vZGU6IG5vd3JhcDsiPmlkPC9zcGFuPjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI2IiB5PSI0OSIgZmlsbD0ibGlnaHQtZGFyaygjMDAwMDAwLCAjZmZmZmZmKSIgZm9udC1mYW1pbHk9IiZxdW90O0hlbHZldGljYSZxdW90OyIgZm9udC1zaXplPSIxMnB4Ij5pZDwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IkFtd3lucm0yQ29wMWFhV011VVNZLTMiPjxnPjxyZWN0IHg9IjAiIHk9IjYwIiB3aWR0aD0iMTQwIiBoZWlnaHQ9IjMwIiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PGc+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGZsZXgtc3RhcnQ7IHdpZHRoOiAxMzBweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA3NXB4OyBtYXJnaW4tbGVmdDogNnB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBsZWZ0OyBtYXgtaGVpZ2h0OiAyNnB4OyBvdmVyZmxvdzogaGlkZGVuOyBjb2xvcjogIzAwMDAwMDsgIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O0hlbHZldGljYSZxdW90OzsgY29sb3I6ICMwMDAwMDA7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IHdvcmQtd3JhcDogbm9ybWFsOyAiPjxzcGFuIHN0eWxlPSJ0ZXh0LXdyYXAtbW9kZTogbm93cmFwOyI+PGZvbnQ+b3duZXI8L2ZvbnQ+PC9zcGFuPjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI2IiB5PSI3OSIgZmlsbD0ibGlnaHQtZGFyaygjMDAwMDAwLCAjZmZmZmZmKSIgZm9udC1mYW1pbHk9IiZxdW90O0hlbHZldGljYSZxdW90OyIgZm9udC1zaXplPSIxMnB4Ij5vd25lcjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IkFtd3lucm0yQ29wMWFhV011VVNZLTQiPjxnPjxyZWN0IHg9IjAiIHk9IjkwIiB3aWR0aD0iMTQwIiBoZWlnaHQ9IjMwIiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PGc+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGZsZXgtc3RhcnQ7IHdpZHRoOiAxMzBweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMDVweDsgbWFyZ2luLWxlZnQ6IDZweDsiPjxkaXYgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMDsgdGV4dC1hbGlnbjogbGVmdDsgbWF4LWhlaWdodDogMjZweDsgb3ZlcmZsb3c6IGhpZGRlbjsgY29sb3I6ICMwMDAwMDA7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtIZWx2ZXRpY2EmcXVvdDs7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyB3b3JkLXdyYXA6IG5vcm1hbDsgIj52YWxpZGF0b3JzPC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjYiIHk9IjEwOSIgZmlsbD0ibGlnaHQtZGFyaygjMDAwMDAwLCAjZmZmZmZmKSIgZm9udC1mYW1pbHk9IiZxdW90O0hlbHZldGljYSZxdW90OyIgZm9udC1zaXplPSIxMnB4Ij52YWxpZGF0b3JzPC90ZXh0Pjwvc3dpdGNoPjwvZz48L2c+PC9nPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktNSI+PGc+PHJlY3QgeD0iMCIgeT0iMTIwIiB3aWR0aD0iMTQwIiBoZWlnaHQ9IjMwIiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PGc+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGZsZXgtc3RhcnQ7IHdpZHRoOiAxMzBweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMzVweDsgbWFyZ2luLWxlZnQ6IDZweDsiPjxkaXYgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMDsgdGV4dC1hbGlnbjogbGVmdDsgbWF4LWhlaWdodDogMjZweDsgb3ZlcmZsb3c6IGhpZGRlbjsgY29sb3I6ICMwMDAwMDA7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtIZWx2ZXRpY2EmcXVvdDs7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyB3b3JkLXdyYXA6IG5vcm1hbDsgIj50aHJlc2hvbGQ8L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iNiIgeT0iMTM5IiBmaWxsPSJsaWdodC1kYXJrKCMwMDAwMDAsICNmZmZmZmYpIiBmb250LWZhbWlseT0iJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7IiBmb250LXNpemU9IjEycHgiPnRocmVzaG9sZDwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+) #### `02_post_dispatch`[​](#02_post_dispatch "Direct link to 02_post_dispatch") This submodule implements the PostDispatch interface and the hook instances like the `InterchainGasPaymaster` or `MerkleTreeHook`. The modular design allows developers to easily add custom PostDispatch hook implementations. ``` type PostDispatchHook interface { HookType() uint8 SupportsMetadata(metadata any) bool PostDispatch(ctx sdk.Context, metadata util.StandardHookMetadata, message util.HyperlaneMessage, maxFee sdk.Coins) (sdk.Coins, error) QuoteDispatch(ctx context.Context, hookId HexAddress, metadata util.StandardHookMetadata, message HyperlaneMessage) (sdk.Coins, error)} ``` **`InterchainGasPaymaster`** * Allows message sender to pay fees to the relayer to deliver a message on the destination chain * `DestinationGasConfig` is used to determine the correct `InterchainGasPayment` * Important methods: * `postDispatch()` * `payForGas()` * `claim()` ![/img/cosmos-sdk-implementation/hyperlane-cosmos (9).svg](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJiYWNrZ3JvdW5kOiAjZmZmZmZmOyBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOyBjb2xvci1zY2hlbWU6IGxpZ2h0OyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjE0MXB4IiBoZWlnaHQ9IjE1MXB4IiB2aWV3Qm94PSItMC41IC0wLjUgMTQxIDE1MSI+PGRlZnMvPjxyZWN0IGZpbGw9IiNmZmZmZmYiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHg9IjAiIHk9IjAiIHN0eWxlPSJmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7Ii8+PGc+PGcgZGF0YS1jZWxsLWlkPSIwIj48ZyBkYXRhLWNlbGwtaWQ9IjEiPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNzUiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTUzIj48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTU0Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy01NSIvPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTU3Ij48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTU4Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy01OSIvPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNjIiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTYwIi8+PC9nPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNzEiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTYzIj48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTY0Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy02NSIvPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTY2Ij48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTY3Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy02OCIvPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTcyIi8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy03OCIvPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNzkiPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctODAiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTgxIi8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy04MiIvPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctODMiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTg0Ii8+PC9nPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktMSI+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0yIi8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0zIi8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS00Ii8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS01Ii8+PC9nPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktNyI+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS04Ii8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS05Ii8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0xMCIvPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktMTEiLz48ZyBkYXRhLWNlbGwtaWQ9IkFtd3lucm0yQ29wMWFhV011VVNZLTEyIi8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0xMyIvPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktMTQiLz48ZyBkYXRhLWNlbGwtaWQ9IkFtd3lucm0yQ29wMWFhV011VVNZLTE1Ii8+PC9nPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktMTciLz48ZyBkYXRhLWNlbGwtaWQ9IkFtd3lucm0yQ29wMWFhV011VVNZLTIwIi8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0yMSI+PGc+PHBhdGggZD0iTSAwIDMwIEwgMCAwIEwgMTQwIDAgTCAxNDAgMzAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0iYWxsIiBzdHlsZT0iZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBzdHJva2U6IHJnYigwLCAwLCAwKTsiLz48cGF0aCBkPSJNIDAgMzAgTCAwIDE1MCBMIDE0MCAxNTAgTCAxNDAgMzAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgc3R5bGU9InN0cm9rZTogcmdiKDAsIDAsIDApOyIvPjxwYXRoIGQ9Ik0gMCAzMCBMIDE0MCAzMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIiBzdHlsZT0ic3Ryb2tlOiByZ2IoMCwgMCwgMCk7Ii8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxMzhweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxNXB4OyBtYXJnaW4tbGVmdDogMXB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBjZW50ZXI7IGNvbG9yOiAjMDAwMDAwOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7OyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+PGZvbnQ+SUdQPC9mb250PjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI3MCIgeT0iMTkiIGZpbGw9ImxpZ2h0LWRhcmsoIzAwMDAwMCwgI2ZmZmZmZikiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+SUdQPC90ZXh0Pjwvc3dpdGNoPjwvZz48L2c+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0yMiI+PGc+PHJlY3QgeD0iMCIgeT0iMzAiIHdpZHRoPSIxNDAiIGhlaWdodD0iMzAiIGZpbGw9Im5vbmUiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjwvZz48Zz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgZmxleC1zdGFydDsgd2lkdGg6IDEzMHB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDQ1cHg7IG1hcmdpbi1sZWZ0OiA2cHg7Ij48ZGl2IHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDA7IHRleHQtYWxpZ246IGxlZnQ7IG1heC1oZWlnaHQ6IDI2cHg7IG92ZXJmbG93OiBoaWRkZW47IGNvbG9yOiAjMDAwMDAwOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7OyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+PHNwYW4gc3R5bGU9InRleHQtd3JhcC1tb2RlOiBub3dyYXA7Ij5pZDwvc3Bhbj48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iNiIgeT0iNDkiIGZpbGw9ImxpZ2h0LWRhcmsoIzAwMDAwMCwgI2ZmZmZmZikiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCI+aWQ8L3RleHQ+PC9zd2l0Y2g+PC9nPjwvZz48L2c+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0yMyI+PGc+PHJlY3QgeD0iMCIgeT0iNjAiIHdpZHRoPSIxNDAiIGhlaWdodD0iMzAiIGZpbGw9Im5vbmUiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjwvZz48Zz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgZmxleC1zdGFydDsgd2lkdGg6IDEzMHB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDc1cHg7IG1hcmdpbi1sZWZ0OiA2cHg7Ij48ZGl2IHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDA7IHRleHQtYWxpZ246IGxlZnQ7IG1heC1oZWlnaHQ6IDI2cHg7IG92ZXJmbG93OiBoaWRkZW47IGNvbG9yOiAjMDAwMDAwOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7OyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+PHNwYW4gc3R5bGU9InRleHQtd3JhcC1tb2RlOiBub3dyYXA7Ij48Zm9udD5vd25lcjwvZm9udD48L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjYiIHk9Ijc5IiBmaWxsPSJsaWdodC1kYXJrKCMwMDAwMDAsICNmZmZmZmYpIiBmb250LWZhbWlseT0iJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7IiBmb250LXNpemU9IjEycHgiPm93bmVyPC90ZXh0Pjwvc3dpdGNoPjwvZz48L2c+PC9nPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktMjQiPjxnPjxyZWN0IHg9IjAiIHk9IjkwIiB3aWR0aD0iMTQwIiBoZWlnaHQ9IjMwIiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PGc+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGZsZXgtc3RhcnQ7IHdpZHRoOiAxMzBweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMDVweDsgbWFyZ2luLWxlZnQ6IDZweDsiPjxkaXYgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMDsgdGV4dC1hbGlnbjogbGVmdDsgbWF4LWhlaWdodDogMjZweDsgb3ZlcmZsb3c6IGhpZGRlbjsgY29sb3I6ICMwMDAwMDA7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtIZWx2ZXRpY2EmcXVvdDs7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyB3b3JkLXdyYXA6IG5vcm1hbDsgIj5kZW5vbTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI2IiB5PSIxMDkiIGZpbGw9ImxpZ2h0LWRhcmsoIzAwMDAwMCwgI2ZmZmZmZikiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCI+ZGVub208L3RleHQ+PC9zd2l0Y2g+PC9nPjwvZz48L2c+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0yNSI+PGc+PHJlY3QgeD0iMCIgeT0iMTIwIiB3aWR0aD0iMTQwIiBoZWlnaHQ9IjMwIiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PGc+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGZsZXgtc3RhcnQ7IHdpZHRoOiAxMzBweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxMzVweDsgbWFyZ2luLWxlZnQ6IDZweDsiPjxkaXYgc3R5bGU9ImJveC1zaXppbmc6IGJvcmRlci1ib3g7IGZvbnQtc2l6ZTogMDsgdGV4dC1hbGlnbjogbGVmdDsgbWF4LWhlaWdodDogMjZweDsgb3ZlcmZsb3c6IGhpZGRlbjsgY29sb3I6ICMwMDAwMDA7ICI+PGRpdiBzdHlsZT0iZGlzcGxheTogaW5saW5lLWJsb2NrOyBmb250LXNpemU6IDEycHg7IGZvbnQtZmFtaWx5OiAmcXVvdDtIZWx2ZXRpY2EmcXVvdDs7IGNvbG9yOiAjMDAwMDAwOyBsaW5lLWhlaWdodDogMS4yOyBwb2ludGVyLWV2ZW50czogYWxsOyB3aGl0ZS1zcGFjZTogbm9ybWFsOyB3b3JkLXdyYXA6IG5vcm1hbDsgIj5jbGFpbWFibGVfZmVlczwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI2IiB5PSIxMzkiIGZpbGw9ImxpZ2h0LWRhcmsoIzAwMDAwMCwgI2ZmZmZmZikiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCI+Y2xhaW1hYmxlX2ZlZXM8L3RleHQ+PC9zd2l0Y2g+PC9nPjwvZz48L2c+PC9nPjwvZz48L2c+PC9nPjwvc3ZnPg==) ![/img/cosmos-sdk-implementation/hyperlane-cosmos (10).svg](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJiYWNrZ3JvdW5kOiAjZmZmZmZmOyBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOyBjb2xvci1zY2hlbWU6IGxpZ2h0OyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjE0MXB4IiBoZWlnaHQ9IjE1MXB4IiB2aWV3Qm94PSItMC41IC0wLjUgMTQxIDE1MSI+PGRlZnMvPjxyZWN0IGZpbGw9IiNmZmZmZmYiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHg9IjAiIHk9IjAiIHN0eWxlPSJmaWxsOiByZ2IoMjU1LCAyNTUsIDI1NSk7Ii8+PGc+PGcgZGF0YS1jZWxsLWlkPSIwIj48ZyBkYXRhLWNlbGwtaWQ9IjEiPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNzUiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTUzIj48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTU0Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy01NSIvPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTU3Ij48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTU4Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy01OSIvPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNjIiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTYwIi8+PC9nPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNzEiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTYzIj48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTY0Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy02NSIvPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTY2Ij48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTY3Ii8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy02OCIvPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTcyIi8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy03OCIvPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctNzkiPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctODAiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTgxIi8+PGcgZGF0YS1jZWxsLWlkPSIzRkVGei1qamhNVVJCR3p3SjlmNy04MiIvPjxnIGRhdGEtY2VsbC1pZD0iM0ZFRnotampoTVVSQkd6d0o5ZjctODMiLz48ZyBkYXRhLWNlbGwtaWQ9IjNGRUZ6LWpqaE1VUkJHendKOWY3LTg0Ii8+PC9nPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktMSI+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0yIi8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0zIi8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS00Ii8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS01Ii8+PC9nPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktNyI+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS04Ii8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS05Ii8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0xMCIvPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktMTEiLz48ZyBkYXRhLWNlbGwtaWQ9IkFtd3lucm0yQ29wMWFhV011VVNZLTEyIi8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0xMyIvPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktMTQiLz48ZyBkYXRhLWNlbGwtaWQ9IkFtd3lucm0yQ29wMWFhV011VVNZLTE1Ii8+PC9nPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktMTciLz48ZyBkYXRhLWNlbGwtaWQ9IkFtd3lucm0yQ29wMWFhV011VVNZLTIwIi8+PGcgZGF0YS1jZWxsLWlkPSJBbXd5bnJtMkNvcDFhYVdNdVVTWS0yMSI+PGc+PHBhdGggZD0iTSAwIDMwIEwgMCAwIEwgMTQwIDAgTCAxNDAgMzAiIGZpbGw9IiNmZmZmZmYiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0iYWxsIiBzdHlsZT0iZmlsbDogcmdiKDI1NSwgMjU1LCAyNTUpOyBzdHJva2U6IHJnYigwLCAwLCAwKTsiLz48cGF0aCBkPSJNIDAgMzAgTCAwIDE1MCBMIDE0MCAxNTAgTCAxNDAgMzAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgc3R5bGU9InN0cm9rZTogcmdiKDAsIDAsIDApOyIvPjxwYXRoIGQ9Ik0gMCAzMCBMIDE0MCAzMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHBvaW50ZXItZXZlbnRzPSJub25lIiBzdHlsZT0ic3Ryb2tlOiByZ2IoMCwgMCwgMCk7Ii8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBjZW50ZXI7IHdpZHRoOiAxMzhweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiAxNXB4OyBtYXJnaW4tbGVmdDogMXB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBjZW50ZXI7IGNvbG9yOiAjMDAwMDAwOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7OyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+PGZvbnQ+TWVya2xlVHJlZUhvb2s8L2ZvbnQ+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjcwIiB5PSIxOSIgZmlsbD0ibGlnaHQtZGFyaygjMDAwMDAwLCAjZmZmZmZmKSIgZm9udC1mYW1pbHk9IiZxdW90O0hlbHZldGljYSZxdW90OyIgZm9udC1zaXplPSIxMnB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5NZXJrbGVUcmVlSG9vazwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktMjIiPjxnPjxyZWN0IHg9IjAiIHk9IjMwIiB3aWR0aD0iMTQwIiBoZWlnaHQ9IjMwIiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PGc+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGZsZXgtc3RhcnQ7IHdpZHRoOiAxMzBweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA0NXB4OyBtYXJnaW4tbGVmdDogNnB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBsZWZ0OyBtYXgtaGVpZ2h0OiAyNnB4OyBvdmVyZmxvdzogaGlkZGVuOyBjb2xvcjogIzAwMDAwMDsgIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O0hlbHZldGljYSZxdW90OzsgY29sb3I6ICMwMDAwMDA7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IHdvcmQtd3JhcDogbm9ybWFsOyAiPjxzcGFuIHN0eWxlPSJ0ZXh0LXdyYXAtbW9kZTogbm93cmFwOyI+aWQ8L3NwYW4+PC9kaXY+PC9kaXY+PC9kaXY+PC9mb3JlaWduT2JqZWN0Pjx0ZXh0IHg9IjYiIHk9IjQ5IiBmaWxsPSJsaWdodC1kYXJrKCMwMDAwMDAsICNmZmZmZmYpIiBmb250LWZhbWlseT0iJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7IiBmb250LXNpemU9IjEycHgiPmlkPC90ZXh0Pjwvc3dpdGNoPjwvZz48L2c+PC9nPjxnIGRhdGEtY2VsbC1pZD0iQW13eW5ybTJDb3AxYWFXTXVVU1ktMjMiPjxnPjxyZWN0IHg9IjAiIHk9IjYwIiB3aWR0aD0iMTQwIiBoZWlnaHQ9IjMwIiBmaWxsPSJub25lIiBzdHJva2U9Im5vbmUiIHBvaW50ZXItZXZlbnRzPSJhbGwiLz48L2c+PGc+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTAuNSAtMC41KSI+PHN3aXRjaD48Zm9yZWlnbk9iamVjdCBzdHlsZT0ib3ZlcmZsb3c6IHZpc2libGU7IHRleHQtYWxpZ246IGxlZnQ7IiBwb2ludGVyLWV2ZW50cz0ibm9uZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgcmVxdWlyZWRGZWF0dXJlcz0iaHR0cDovL3d3dy53My5vcmcvVFIvU1ZHMTEvZmVhdHVyZSNFeHRlbnNpYmlsaXR5Ij48ZGl2IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIiBzdHlsZT0iZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IHVuc2FmZSBjZW50ZXI7IGp1c3RpZnktY29udGVudDogdW5zYWZlIGZsZXgtc3RhcnQ7IHdpZHRoOiAxMzBweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmctdG9wOiA3NXB4OyBtYXJnaW4tbGVmdDogNnB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBsZWZ0OyBtYXgtaGVpZ2h0OiAyNnB4OyBvdmVyZmxvdzogaGlkZGVuOyBjb2xvcjogIzAwMDAwMDsgIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O0hlbHZldGljYSZxdW90OzsgY29sb3I6ICMwMDAwMDA7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IHdvcmQtd3JhcDogbm9ybWFsOyAiPjxzcGFuIHN0eWxlPSJ0ZXh0LXdyYXAtbW9kZTogbm93cmFwOyI+PGZvbnQ+b3duZXI8L2ZvbnQ+PC9zcGFuPjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI2IiB5PSI3OSIgZmlsbD0ibGlnaHQtZGFyaygjMDAwMDAwLCAjZmZmZmZmKSIgZm9udC1mYW1pbHk9IiZxdW90O0hlbHZldGljYSZxdW90OyIgZm9udC1zaXplPSIxMnB4Ij5vd25lcjwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IkFtd3lucm0yQ29wMWFhV011VVNZLTI0Ij48Zz48cmVjdCB4PSIwIiB5PSI5MCIgd2lkdGg9IjE0MCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBmbGV4LXN0YXJ0OyB3aWR0aDogMTMwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTAwcHg7IG1hcmdpbi1sZWZ0OiA2cHg7Ij48ZGl2IHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDA7IHRleHQtYWxpZ246IGxlZnQ7IG1heC1oZWlnaHQ6IDE2cHg7IG92ZXJmbG93OiBoaWRkZW47IGNvbG9yOiAjMDAwMDAwOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7OyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+dHJlZTwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI2IiB5PSIxMDQiIGZpbGw9ImxpZ2h0LWRhcmsoIzAwMDAwMCwgI2ZmZmZmZikiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCI+dHJlZTwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9IkFtd3lucm0yQ29wMWFhV011VVNZLTI1Ij48Zz48cmVjdCB4PSIwIiB5PSIxMTAiIHdpZHRoPSIxNDAiIGhlaWdodD0iMjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0ibm9uZSIgcG9pbnRlci1ldmVudHM9ImFsbCIvPjwvZz48Zz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMC41IC0wLjUpIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHN0eWxlPSJvdmVyZmxvdzogdmlzaWJsZTsgdGV4dC1hbGlnbjogbGVmdDsiIHBvaW50ZXItZXZlbnRzPSJub25lIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiByZXF1aXJlZEZlYXR1cmVzPSJodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcxMS9mZWF0dXJlI0V4dGVuc2liaWxpdHkiPjxkaXYgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHN0eWxlPSJkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogdW5zYWZlIGNlbnRlcjsganVzdGlmeS1jb250ZW50OiB1bnNhZmUgZmxleC1zdGFydDsgd2lkdGg6IDEzMHB4OyBoZWlnaHQ6IDFweDsgcGFkZGluZy10b3A6IDEyMHB4OyBtYXJnaW4tbGVmdDogNnB4OyI+PGRpdiBzdHlsZT0iYm94LXNpemluZzogYm9yZGVyLWJveDsgZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBsZWZ0OyBtYXgtaGVpZ2h0OiAxNnB4OyBvdmVyZmxvdzogaGlkZGVuOyBjb2xvcjogIzAwMDAwMDsgIj48ZGl2IHN0eWxlPSJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IGZvbnQtc2l6ZTogMTJweDsgZm9udC1mYW1pbHk6ICZxdW90O0hlbHZldGljYSZxdW90OzsgY29sb3I6ICMwMDAwMDA7IGxpbmUtaGVpZ2h0OiAxLjI7IHBvaW50ZXItZXZlbnRzOiBhbGw7IHdoaXRlLXNwYWNlOiBub3JtYWw7IHdvcmQtd3JhcDogbm9ybWFsOyAiPjxmb250IHN0eWxlPSJmb250LXNpemU6IDEwcHg7Ij48c3BhbiBzdHlsZT0id2hpdGUtc3BhY2U6IHByZTsiPgk8L3NwYW4+YnJhbmNoPC9mb250PjwvZGl2PjwvZGl2PjwvZGl2PjwvZm9yZWlnbk9iamVjdD48dGV4dCB4PSI2IiB5PSIxMjQiIGZpbGw9ImxpZ2h0LWRhcmsoIzAwMDAwMCwgI2ZmZmZmZikiIGZvbnQtZmFtaWx5PSImcXVvdDtIZWx2ZXRpY2EmcXVvdDsiIGZvbnQtc2l6ZT0iMTJweCI+CWJyYW5jaDwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjwvZz48ZyBkYXRhLWNlbGwtaWQ9InRlMGtFNDgycTBGdWZ3S1RiX01vLTEiPjxnPjxyZWN0IHg9IjAiIHk9IjEzMCIgd2lkdGg9IjE0MCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJub25lIiBwb2ludGVyLWV2ZW50cz0iYWxsIi8+PC9nPjxnPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0wLjUgLTAuNSkiPjxzd2l0Y2g+PGZvcmVpZ25PYmplY3Qgc3R5bGU9Im92ZXJmbG93OiB2aXNpYmxlOyB0ZXh0LWFsaWduOiBsZWZ0OyIgcG9pbnRlci1ldmVudHM9Im5vbmUiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHJlcXVpcmVkRmVhdHVyZXM9Imh0dHA6Ly93d3cudzMub3JnL1RSL1NWRzExL2ZlYXR1cmUjRXh0ZW5zaWJpbGl0eSI+PGRpdiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgc3R5bGU9ImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiB1bnNhZmUgY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHVuc2FmZSBmbGV4LXN0YXJ0OyB3aWR0aDogMTMwcHg7IGhlaWdodDogMXB4OyBwYWRkaW5nLXRvcDogMTQwcHg7IG1hcmdpbi1sZWZ0OiA2cHg7Ij48ZGl2IHN0eWxlPSJib3gtc2l6aW5nOiBib3JkZXItYm94OyBmb250LXNpemU6IDA7IHRleHQtYWxpZ246IGxlZnQ7IG1heC1oZWlnaHQ6IDE2cHg7IG92ZXJmbG93OiBoaWRkZW47IGNvbG9yOiAjMDAwMDAwOyAiPjxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1zaXplOiAxMnB4OyBmb250LWZhbWlseTogJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7OyBjb2xvcjogIzAwMDAwMDsgbGluZS1oZWlnaHQ6IDEuMjsgcG9pbnRlci1ldmVudHM6IGFsbDsgd2hpdGUtc3BhY2U6IG5vcm1hbDsgd29yZC13cmFwOiBub3JtYWw7ICI+PGZvbnQgc3R5bGU9ImZvbnQtc2l6ZTogMTBweDsiPjxzcGFuIHN0eWxlPSJ3aGl0ZS1zcGFjZTogcHJlOyI+CTwvc3Bhbj5jb3VudDwvZm9udD48L2Rpdj48L2Rpdj48L2Rpdj48L2ZvcmVpZ25PYmplY3Q+PHRleHQgeD0iNiIgeT0iMTQ0IiBmaWxsPSJsaWdodC1kYXJrKCMwMDAwMDAsICNmZmZmZmYpIiBmb250LWZhbWlseT0iJnF1b3Q7SGVsdmV0aWNhJnF1b3Q7IiBmb250LXNpemU9IjEycHgiPgljb3VudDwvdGV4dD48L3N3aXRjaD48L2c+PC9nPjwvZz48L2c+PC9nPjwvZz48L2c+PC9zdmc+) **`MerkleTreeHook`** * Inserts dispatched messages into an on-chain Merkle tree * Required for `MessageIdMultisig` and `MerkleRootMultisig` ISMs * Important methods: * `postDispatch()` * `InsertedIntoTree()` *(event)* ### `x/warp` `warp` builds on-top of the core functionality by enabling token creation and cross-chain transfers between chains already connected via Hyperlane. These tokens leverage modular security through specific ISMs. * Currently, two token types are available: 1. **Collateral:** Locks tokens as collateral on the source chain for cross-chain transfers. 2. **Synthetic:** Mints new tokens on the destination chain to represent the original tokens. * Important methods: * `createToken()` * `remoteTransfer()` * `enrollRemoteRouter()` /img/cosmos-sdk-implementation/hyperlane-cosmos (5).svg ## HWR - Remote Transfer Lifecycle #### `Dispatch()` /img/cosmos-sdk-implementation/image.png #### `Process()` /img/cosmos-sdk-implementation/image_1.png ## EVM / Cosmos SDK Differences ### EVM ≠ Cosmos SDK 1. Instances instead of Contracts 2. IDs instead of Contract addresses 3. Tokens: Cosmos uses denoms (including native denoms and IBC denoms) instead of token contract addresses, so IGP config must specify a `denom`. There is no `NativeCollateralToken` contract abstraction. ### Tool Integration The Hyperlane CLI supports the Cosmos SDK module for deploying and managing core infrastructure and Warp Routes. The CLI handles Cosmos-specific details like bech32 address derivation, denom-based token references, and message-based deployment automatically. Step-by-step core deployment guide Bridge tokens between Cosmos chains For cross-chain routes, see the [EVM ↔ Cosmos HWR Guide](/docs/guides/warp-routes/evm-cosmos-warp-route-guide) or the [Cosmos ↔ SVM HWR Guide](/docs/guides/warp-routes/cosmos-svm-warp-route-guide). # Implementation Guide Source: https://docs.hyperlane.xyz/docs/alt-vm-implementations/implementation-guide A Hyperlane implementation for a new chain architecture is comprised of the following: 1. [Contracts](#1-contracts): expose the interface for application developers to send and receive messages with 2. [Agents](#2-agents): operate the protocol by adding security and relaying messages 3. [Applications](#3-applications): applications that use the protocol and demonstrate its capabilities Before getting started here, it is recommended to review the protocol documentation. If you would like to dive deeper, check out some of the Hyperlane implementations that are currently available: * [Solidity](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/solidity) * [CosmWasm](https://github.com/many-things/cw-hyperlane) * [Sealevel](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/rust/sealevel) * [Cairo](https://github.com/astraly-labs/hyperlane_starknet) * [Sway](https://github.com/hyperlane-xyz/fuel-contracts) * [Move](https://github.com/movementlabsxyz/hyperlane-monorepo/tree/v3-aptos) ## 1. Contracts Below describes the onchain contract spec for the Hyperlane protocol. It uses solidity types for familiarity but everything should be generalizable to other languages. * `address` should be interpreted as the local chain's address type. * `payable` describes a function that allows callers to pass native tokens. * Ensure events are properly emitted for all important state changes. * Clearly document any deviations from the reference implementation and their rationale. ### Considerations **Byte representation:** * Be aware that different chains may have different native types for representing bytes. For example, StarkNet uses felt252 for contract addresses, which may not fully accommodate 32-byte addresses used in other chains. * Implement proper conversion and validation mechanisms when dealing with cross-chain addresses. **Serialization:** * Pay close attention to how message fields are serialized, especially for variable-length data like the message body. * Ensure that the serialization method used (e.g., abi.encodePacked equivalent) behaves consistently across different chain implementations. ### Message The message is the core data structure used by the Hyperlane protocol. It is a packed data structure that contains all the information needed to route a message from one domain to another. * [Solidity](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/libs/Message.sol) * [Sway](https://github.com/hyperlane-xyz/fuel-contracts/blob/main/contracts/hyperlane-message/src/main.sw) * [CosmWasm](https://github.com/many-things/cw-hyperlane/blob/main/packages/interface/src/types/message.rs) * [Sealevel](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/main/hyperlane-core/src/types/message.rs) * [Cairo](https://github.com/astraly-labs/hyperlane_starknet/blob/main/cairo/crates/contracts/src/libs/message.cairo) ``` struct Message { // The version of the origin and destination Mailboxes uint8 version, // A nonce to uniquely identify the message on its origin Mailbox uint32 nonce, // Domain of origin chain uint32 origin, // Address of sender on origin chain bytes32 sender, // Domain of destination chain uint32 destination, // Address of recipient on destination chain bytes32 recipient, // Raw bytes of message body bytes body} ``` ### Mailbox The mailbox is the entrypoint for developers to send and receive messages from. Make sure that `localDomain` is immutable to prevent unauthorized changes that could compromise cross-chain security. * [Solidity Interface](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/interfaces/IMailbox.sol) Implementations: * [Solidity](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/Mailbox.sol) * [Sway](https://github.com/hyperlane-xyz/fuel-contracts/blob/main/contracts/hyperlane-mailbox/src/main.sw) * [CosmWasm](https://github.com/many-things/cw-hyperlane/blob/main/contracts/core/mailbox/src/execute.rs) * [Sealevel](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/sealevel/programs/mailbox/src/processor.rs) * [Cairo](https://github.com/astraly-labs/hyperlane_starknet/blob/main/cairo/crates/contracts/src/mailbox.cairo) In addition to default and custom hooks, Hyperlane introduces the concept of a **Required Hook** that is used for post processing of ALL dispatches. Make sure to call the required hook before the default or custom hook. #### dispatch Dispatches a message to the destination domain and recipient. ``` function dispatch( // Domain of destination chain uint32 destination, // Address of recipient on destination chain as bytes32 bytes32 recipient, // Raw bytes content of message body bytes body) returns ( // The message ID inserted into the Mailbox's merkle tree bytes32 messageId); ``` Dispatches a message to the destination domain and recipient, and provides metadata for the default hook. ``` function dispatch( // Domain of destination chain uint32 destination, // Address of recipient on destination chain as bytes32 bytes32 recipient, // Raw bytes content of message body bytes body, // Metadata used by the default post dispatch hook bytes defaultHookMetadata) returns ( // The message ID inserted into the Mailbox's merkle tree bytes32 messageId); ``` Dispatches a message to the destination domain and recipient, and provides metadata for a custom hook to use instead of the default. ``` function dispatch( // Domain of destination chain uint32 destination, // Address of recipient on destination chain as bytes32 bytes32 recipient, // Raw bytes content of message body bytes body, // Metadata used by the custom post dispatch hook bytes customHookMetadata, // Custom hook to use instead of the default IPostDispatchHook customHook) returns ( // The message ID inserted into the Mailbox's merkle tree bytes32 messageId); ``` #### process Attempts to deliver `message` to its recipient. Verifies `message` via the recipient's ISM using the provided `metadata`. ``` function process( // Metadata used by the ISM to verify message. bytes metadata, // Byte packed message bytes message); ``` #### latestDispatchedId Returns the latest dispatched message ID used for auth in post-dispatch hooks. ``` function latestDispatchedId() public view returns (bytes32); ``` ### Message Recipient A contract that wants to receive a message must expose the following handler. * [Solidity](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/interfaces/IMessageRecipient.sol) * [Sway](https://github.com/hyperlane-xyz/fuel-contracts/blob/main/contracts/hyperlane-interfaces/src/lib.sw) * [CosmWasm](https://github.com/many-things/cw-hyperlane/blob/main/packages/interface/src/core/mod.rs) * [Sealevel](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/sealevel/libraries/message-recipient-interface/src/lib.rs) * [Cairo](https://github.com/astraly-labs/hyperlane_starknet/blob/c0dbded927f340715bef8f6a8c6262f520ff3f1a/cairo/crates/contracts/src/interfaces.cairo#L131) ``` function handle( // Domain of origin chain uint32 origin, // Address of sender on origin chain bytes32 sender, // Raw bytes content of message body bytes body); ``` They may optionally specify a security module to verify messages before they are handled. ``` function IInterchainSecurityModule() returns (address); ``` After implementing these three contracts, you can reach your first milestone to test, mocking a message transfer, by calling a `Mailbox`'s `dispatch` function to send a message to a recipient and assert that the recipient received the message. See a [Foundry test case here.](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/59e89afc5cbdec5362da5e13327eab4cb640b6b5/solidity/test/Messaging.t.sol#L29) ### Interchain Security Module Interchain security modules are used to verify messages before they are processed. * [Solidity](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/interfaces/IIInterchainSecurityModule.sol) * [Sway](https://github.com/hyperlane-xyz/fuel-contracts/blob/main/contracts/hyperlane-interfaces/src/lib.sw) * [CosmWasm](https://github.com/many-things/cw-hyperlane/blob/main/packages/interface/src/ism/mod.rs) * [Sealevel](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/main/hyperlane-core/src/traits/interchain_security_module.rs) * [Cairo](https://github.com/astraly-labs/hyperlane_starknet/blob/c0dbded927f340715bef8f6a8c6262f520ff3f1a/cairo/crates/contracts/src/interfaces.cairo#L93) #### moduleType Returns an enum that represents the type of security model encoded by this ISM. ``` enum ModuleType { UNUSED, ROUTING, AGGREGATION, LEGACY_MULTISIG, MERKLE_ROOT_MULTISIG, MESSAGE_ID_MULTISIG, NULL, // used with relayer carrying no metadata CCIP_READ}function moduleType() returns (ModuleType); ``` *Relayers infer how to fetch and format metadata from this type.* #### verify Defines a security model responsible for verifying interchain messages based on the provided metadata. ``` function verify( // Off-chain metadata provided by a relayer, specific // to the security model encoded by the module // (e.g. validator signatures) bytes metadata, // Hyperlane encoded interchain message bytes message) returns ( // True if the message was verified bool success); ``` **Static module management** - Our Solidity implementation defines MultisigISMs as static and part of the bytecode which might not be possible in other chains. You may need to implement dynamic modules for the ISM instead. ### Validator Announce Validators announce their signature storage location so that the relayer can fetch and verify their signatures. * [Solidity](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/interfaces/IValidatorAnnounce.sol) * [Sway](https://github.com/hyperlane-xyz/fuel-contracts/blob/main/contracts/validator-announce/src/interface.sw) * [CosmWasm](https://github.com/many-things/cw-hyperlane/blob/main/packages/interface/src/core/va.rs) * [Sealevel](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/sealevel/programs/validator-announce/src/instruction.rs) * [Cairo](https://github.com/astraly-labs/hyperlane_starknet/blob/main/cairo/crates/contracts/src/isms/multisig/validator_announce.cairo) ### announce Announces a validator signature storage location ``` function announce( address validator, // The address of the validator string storageLocation, // Information encoding the location of signed checkpoints bytes signature // The signed validator announcement) external returns (bool); ``` ### getAnnouncedStorageLocations Returns a list of all announced storage locations ``` function getAnnouncedStorageLocations( address[] _validators // The list of validators to get storage locations for) external view returns ( string[][] // A list of registered storage metadata); ``` ### Multisig ISM Implements a security module that checks if the metadata provided to verify satisfies a quorum of signatures from a set of configured validators. * [Solidity](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/multisig/AbstractMultisigIsm.sol) * [Sway](https://github.com/hyperlane-xyz/fuel-contracts/blob/main/contracts/multisig-ism/src/main.sw) * [CosmWasm](https://github.com/many-things/cw-hyperlane/blob/main/packages/interface/src/ism/multisig.rs) * [Sealevel](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/rust/sealevel/programs/ism/multisig-ism-message-id) * Cairo [MerkleRoot](https://github.com/astraly-labs/hyperlane_starknet/blob/main/cairo/crates/contracts/src/isms/multisig/merkleroot_multisig_ism.cairo) and [MessageId](https://github.com/astraly-labs/hyperlane_starknet/blob/main/cairo/crates/contracts/src/isms/multisig/messageid_multisig_ism.cairo) It is a common error when implementing this ISM to allow a single validator's signature to be passed multiple times and errantly achieve quorum. Take care to ensure validators cannot be double counted and add a negative test case for this. See [solidity `test_verify_revertWhen_duplicateSignatures` for example](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/test/isms/MultisigIsm.t.sol#L194). #### Metadata To be used with the `MESSAGE_ID_MULTISIG` module type implementation in the relayer. * [Solidity](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/libs/MessageIdMultisigIsmMetadata.sol) * [Sway](https://github.com/hyperlane-xyz/fuel-contracts/blob/main/contracts/multisig-ism-metadata/src/main.sw) * [CosmWasm](https://github.com/many-things/cw-hyperlane/blob/main/packages/interface/src/types/metadata.rs) * [Sealevel](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/sealevel/programs/ism/multisig-ism-message-id/src/processor.rs) * [Cairo](https://github.com/astraly-labs/hyperlane_starknet/blob/main/cairo/crates/contracts/src/libs/multisig/message_id_ism_metadata.cairo) The metadata must be formatted as follows: ``` struct MultisigMetadata { // The address of the origin mailbox bytes32 originMailbox; // The signed checkpoint root bytes32 signedCheckpointRoot; // The concatenated signatures of the validators bytes signatures;} ``` #### validatorsAndThreshold[​](#validatorsandthreshold "Direct link to validatorsAndThreshold") Returns the set of validators responsible for verifying message and the number of signatures required. *Can change based on the content of \_message* ``` function validatorsAndThreshold( // Hyperlane formatted interchain message bytes message) returns ( // The array of validator addresses address[] validators, // The number of validator signatures needed uint8 threshold); ``` After implementing the MultisigISM, you reach the second milestone to test that your Mailbox only processes after a recipient's ISM returns true. You can test that with a `TestISM` that you can statically set to accept or reject any message. See a [Foundry test case here.](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/59e89afc5cbdec5362da5e13327eab4cb640b6b5/solidity/test/Mailbox.t.sol#L282) ### Interchain Gas Paymaster The gas paymaster is used to pay for the gas required in message processing on the destination chain. This is not strictly required if the relayer is willing to subsidize message processing. Implement robust checks for sufficient gas payment, considering chain-specific token handling. Our solidity implementation charges native message value but for other chains, you may need to charge a specific token and scale the gas overhead and `tokenExchangeRate` accordingly. * [Solidity](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/hooks/igp/InterchainGasPaymaster.sol) * [Sway](https://github.com/hyperlane-xyz/fuel-contracts/blob/main/contracts/igp/interchain-gas-paymaster/src/main.sw) * [CosmWasm](https://github.com/many-things/cw-hyperlane/blob/main/contracts/igps/core/src) * [Sealevel](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/sealevel/programs/hyperlane-sealevel-igp/src/processor.rs) #### payForGas Deposits msg.value as a payment for the relaying of a message to its destination chain. Although you can specify a `refundAddress`, overpayment **may not be refunded** to the message sender if you are composing hooks together. ``` function payForGas( // The ID of the message to pay for. bytes32 messageId, // The domain of the message's destination chain. uint32 destination, // The amount of destination gas to pay for. uint256 gasAmount, // The local address to refund any overpayment to. address refundAddress) payable; ``` #### GasPayment Emitted when a payment is made for a message's gas costs. ``` event GasPayment( bytes32 messageId, uint32 destinationDomain, uint256 gasAmount, uint256 payment); ``` #### DestinationGasConfigSet Emitted when the gas oracle for a remote domain is set. ``` event DestinationGasConfigSet( uint32 remoteDomain, // remote domain address gasOracle, // gas oracle uint96 gasOverhead // destination gas overhead); ``` ## 2. Agents Below describes the agent spec for a new chain implementation. The rust implementations hope to support all chains, but the spec is intended to be chain agnostic. #### Message Indexing All agents must index messages from the origin mailbox. In the solidity mailbox, we [emit an event for each message](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/59e89afc5cbdec5362da5e13327eab4cb640b6b5/solidity/contracts/Mailbox.sol#L221-L222) dispatched. Other chains may have different ways of surfacing this information, but the agent must be able to get message content reliably and with consistent ordering -- see the [message indexer](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/main/hyperlane-core/src/traits/indexer.rs) trait. * [ethereum](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/main/chains/hyperlane-ethereum/src/contracts/mailbox.rs) ### Validator In addition to indexing messages dispatched from the mailbox, validators produce attestations for the messages they observe to be used on the destination chain for security. #### Checkpoint Validators produce attestations called checkpoints from the Mailbox which commit via merkle root to all dispatched message IDs. ``` pub struct Checkpoint { /// The mailbox address pub mailbox_address: H256, /// The mailbox chain pub mailbox_domain: u32, /// The checkpointed root pub root: H256, /// The index of the checkpoint pub index: u32,} ``` Validators use the latest checkpoint method on the [mailbox trait](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/main/hyperlane-core/src/traits/mailbox.rs) to get the latest checkpoint from the mailbox and submit signatures to some highly available storage using the [checkpoint syncer trait](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/main/hyperlane-base/src/traits/checkpoint_syncer.rs). #### Checkpoint with Message ID Validators use indexed messages to join the checkpoint with the corresponding message ID emitted from the mailbox. ``` pub struct CheckpointWithMessageId { /// existing Hyperlane checkpoint struct #[deref] pub checkpoint: Checkpoint, /// hash of message emitted from mailbox checkpoint.index pub message_id: H256,} ``` They also publish these augmented checkpoints on their syncer. You can test your validator by configuring it with a chain with the above contracts and observe that it creates valid signatures. ### Relayer In addition to indexing messages dispatched from the mailbox, a relayer processes messages on the destination chain. This requires building metadata that satisfies the message recipient's ISM verification requirements, and signing transactions that process the message on the destination mailbox. #### Metadata Builders Each module type implies a different metadata format for message verification to succeed. A Relayer will need each module trait (eg [multisig](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/main/hyperlane-core/src/traits/multisig_ism.rs)) to be implemented. #### Message Processor The relayer will attempt to process messages on the destination mailbox (see [message processor](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/fa424826c0132c135511e5316a6e559b574b3a8f/rust/main/agents/relayer/src/msg/processor.rs#L28)). If * the message recipient ISM returns an unknown module type * module type is known but metadata fails to verify * metadata verifies but dry running (gas estimation) message processing fails then the message will be kicked to an exponential backoff retry queue. The relayer relies on implementations of the [mailbox](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/main/hyperlane-core/src/traits/mailbox.rs) and [ism](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/main/hyperlane-core/src/traits/interchain_security_module.rs) traits for these checks. #### Gas Payment Enforcement The Relayer may also require gas payment for a specific message ID on the origin chain before processing the message on the destination chain. To do this, they must have an IGP deployed with their address set as beneficiary and index gas payment events. See [gas payment enforcement trait](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/main/agents/relayer/src/msg/gas_payment/mod.rs). We recommend to start with no gas payment enforcement policy and then gradually support more restrictive ones. ### Testing Once you have implemented an MVP of the relayer, you should create an end-to-end test that: 1. Spins up local origin and destination chains. 2. Deploys your contracts onto both chains. 3. Run validators for the origin chain. 4. Run a relayer between both chains. 5. Observe that upon dispatch of a message of the origin chain, the validator observes the message, creates a signature and the relayer appropriately processes your message via the ISM that specifies the validator on the destination chain. See this [end-to-end test on the Rust codebase ](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/main/utils/run-locally/src/main.rs)for inspiration. After validating the agents with local end-to-end tests, it is recommended that you also run end-to-end tests with real testnets. ## 3. Applications ### Hyperlane Warp Routes Token router application that routes tokens between domains on demand. * [Solidity](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/solidity/contracts/token) * [CosmWasm](https://github.com/many-things/cw-hyperlane/tree/main/packages/interface/src/warp) * [Sealevel](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/sealevel/libraries/hyperlane-sealevel-token/src/instruction.rs) #### transferRemote Transfers `amountOrId` token to `recipient` on `destination` domain. ``` function transferRemote( // The Domain of the destination chain. uint32 destination, // The address of the recipient on the destination chain. bytes32 recipient, // The amount or identifier of tokens to be sent to the remote recipient. uint256 amountOrId) returns ( // The identifier of the dispatched message. bytes32 messageId); ``` #### Transfer Message To be interoperable with Hyperlane Warp Routes on other chains, the `body` of a transfer message must be a byte packed `TransferMessage` struct. ``` struct TransferMessage { // The recipient of the remote transfer bytes32 recipient; // An amount of tokens or a token identifier to be transferred uint256 amountOrId; // Optional metadata e.g. NFT URI information bytes metadata;} ``` # Alt-VM Implementations Source: https://docs.hyperlane.xyz/docs/alt-vm-implementations/overview While Hyperlane documentation was historically EVM-first, we now support additional ecosystems with varying levels of feature and tooling parity. Some workflows still differ by protocol (for example, certain CLI commands or testing flows), and we're continuing to close those gaps across platforms. If you're excited about building on top of these or bringing Hyperlane to other new ecosystems, reach out on [GitHub Discussions](https://github.com/hyperlane-xyz/hyperlane-monorepo/discussions)! ## Cosmos ### CosmosSDK The Hyperlane Cosmos SDK module enables direct integration with Cosmos SDK-based blockchains. The Hyperlane CLI supports deploying core infrastructure and Warp Routes on `cosmosnative` chains. See [Cosmos SDK Module](/docs/alt-vm-implementations/cosmos-sdk) for architecture details, or get started with the [Deploy to a Cosmos Chain](/docs/guides/chains/deploy-hyperlane-cosmos) guide. ### CosmWasm[​](#cosmwasm "Direct link to CosmWasm") See the CosmWasm implementation of Hyperlane [here,](https://github.com/many-things/cw-hyperlane) implemented and maintained by the [Mitosis team](https://mitosis.org/). Follow [this guide](https://github.com/many-things/cw-hyperlane/blob/main/DEPLOYMENT.md) on how to deploy to a Cosmos appchain here. We're live on Celestia, Stride and Neutron as of July 2024. ## Sealevel Hyperlane v3 for Solana Virtual Machine is live now on Solana and Eclipse, with more Solana rollups coming soon. You can find the Sealevel contract [implementation here](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/sealevel/programs). **Does Hyperlane use Anchor for Solana programs?** * No, Hyperlane’s core Solana programs do not use Anchor. **Can I use Anchor for building on Hyperlane’s Solana integration?** * Yes. Although Hyperlane itself doesn’t use Anchor, it’s possible to build with it. For example: [Everclear’s Solana spoke](https://github.com/everclearorg/monorepo/tree/dev/packages/contracts/solana-spoke/programs/everclear_spoke/src) - uses Anchor with Hyperlane’s SVM mailbox. **What testing frameworks can I use for Solana programs?** * Hyperlane uses the `solana-program-test` crate for unit and integration testing. This is a native Rust tool. If you're using Anchor, you might find Anchor's built-in testing utilities or general Rust test frameworks helpful. ## Cairo The Hyperlane protocol has been implemented in Cairo for Starkware by the [Pragma team](https://www.pragma.build/). You can find the in progress [implementation here](https://github.com/astraly-labs/hyperlane_starknet). ## Move Hyperlane has been implemented in MoveVM by [Movement Labs](https://movementlabs.xyz/). You can find the in progress [implementation here](https://github.com/movementlabsxyz/hyperlane-monorepo). These Move contracts are live on Movement's M1 testnet. ## Sway Find our in progress [Sway implementation here](https://github.com/hyperlane-xyz/fuel-contracts). # Example Usage Source: https://docs.hyperlane.xyz/docs/applications/interchain-account/example-usage ## Encoding When calling remote contracts using `callRemote`, the function parameters must be encoded into an array of `Call` structs. Each `Call` struct contains: * `to`: The target contract address (converted to bytes32). * `value`: The ETH or native token amount to send with the call. * `data`: The function call data, which can be encoded using abi.encodeCall. `Call.data` can be easily encoded with the `abi.encodeCall` function. ```solidity theme={null} struct Call { bytes32 to; // supporting non EVM targets uint256 value; bytes data; } interface IUniswapV3Pool { function swap( address recipient, bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96, bytes calldata data ) external returns (int256 amount0, int256 amount1); } IUniswapV3Pool pool = IUniswapV3Pool(...); Call swapCall = Call({ to: TypeCasts.addressToBytes32(address(pool)), data: abi.encodeCall(pool.swap, (...)); value: 0, }); uint32 ethereumDomain = 1; IInterchainAccountRouter(0xabc...).callRemote(ethereumDomain, [swapCall]); ``` ## Typescript Usage We also have Typescript tooling to easily deploy ICA accounts and call `callRemote` on the origin chain: ```typescript theme={null} const localChain = 'ethereum'; const signer = ; const localRouter: InterchainAccountRouter = InterchainAccountRouter__factory.connect(, signer); const recipientAddress = ; // use your own address here const recipientF = new TestRecipient__factory.connect(recipientAddress, signer); // use your own contract here const fooMessage = "Test"; const data = recipient.interface.encodeFunctionData("fooBar", [1, fooMessage]); const call = { to: recipientAddress, data, value: BigNumber.from("0"), }; const quote = await local["quoteGasPayment(uint32)"]( multiProvider.getDomainId(remoteChain) ); const config: AccountConfig = { origin: localChain, owner: signer.address, localRouter: localRouter.address, }; await localRouter.callRemote(localChain, remoteChain, [call], config); ``` ## Determine addresses In some cases, you may need to compute the ICA address on a remote chain before making a call. For example, if your ICA needs funding before executing transactions, you can retrieve its address and transfer assets to it in advance. See the [Transfer and Call Pattern](/docs/guides/warp-routes/evm/transfer-and-call-pattern) section for more information. The `getRemoteInterchainAccount` function can be used to get the address of an ICA given the destination chain and owner address. An example is included below of a contract precomputing its own Interchain Account address. ```solidity theme={null} address myInterchainAccount = IInterchainAccountRouter(...).getRemoteInterchainAccount( destination, address(this) ); ``` If you are using [#overrides](./overrides) to specify remote chains, pass those overrides when computing the remote ICA address. ```solidity theme={null} address myRemoteIca = IInterchainAccountRouter(...).getRemoteInterchainAccount( address(this), remoteRouterOverride, remoteIsmOverride ); ``` # Overrides Source: https://docs.hyperlane.xyz/docs/applications/interchain-account/overrides Interchain Accounts allow developers to override the default chains and security models configured in the `InterchainAccountRouter`. These are useful for: * Calling an ICA on chains not configured in `InterchainAccountRouter`. * Using different ISM than the defaults configured in the `InterchainAccountRouter` * Adjusting the gas limit for IGP payments or setting other parameters. ## Interface The `callRemoteWithOverrides` function looks similar to the `callRemote` function, but takes three additional arguments. First, developers can override `_router`, the address of the `InterchainAccountRouter` on the remote chain. This allows developers to control an ICA on remote chains that have not been configured on the local `InterchainAccountRouter`. Second, developers can override `_ism`, the address of the remote interchain security module (ISM) used to secure their ICA. This ISM will be used to verify the interchain messages passed between the local and remote `InterchainAccountRouters`. This allows developers to use a custom security model that best suits their needs. Third, developers can override `_hookMetadata`, the [StandardHookMetadata](/docs/reference/developer-tools/libraries/hookmetadata) metadata passed to the message hooks for each ICA call (for example, overriding the gas limit for the IGP payment). ```solidity theme={null} /** * @notice Dispatches a sequence of remote calls to be made by an owner's * interchain account on the destination domain * @dev Recommend using CallLib.build to format the interchain calls * @param _destination The remote domain of the chain to make calls on * @param _router The remote router address * @param _ism The remote ISM address * @param _calls The sequence of calls to make * @param _hookMetadata The hook metadata to override with for the hook set by the owner * @return The Hyperlane message ID */ function callRemoteWithOverrides( uint32 _destination, bytes32 _router, bytes32 _ism, CallLib.Call[] calldata _calls, bytes memory _hookMetadata ) public payable returns (bytes32) function getRemoteInterchainAccount( address _owner, address _router, address _ism ) public view returns (address) ``` # Overview Source: https://docs.hyperlane.xyz/docs/applications/interchain-account/overview Interchain Accounts (ICAs) enable a contract on the origin chain to make authenticated calls to contracts on a remote chain. Unlike general message passing, which requires the recipient to implement a specific interface, ICAs allow interaction with *any* contract on the destination chain. Developers can use ICAs for cross-chain execution, enabling contracts to trigger function calls on remote chains. Each ICA on a destination chain corresponds to a unique sender on the origin chain, and the account is deterministic based on `(origin, sender, router, ISM)`. This means that for every contract making interchain calls, there is a corresponding account on the destination chain that executes those calls. ICA is currently supported only on EVM chains. ## Architecture Overview ```mermaid theme={null} flowchart TB subgraph Origin chain direction TB Sender A_O[InterchainAccountRouter] M_O[(Mailbox)] end subgraph Destination chain direction TB M_D[(Mailbox)] A_D[InterchainAccountRouter] SenderAccount Recipient end Sender -- "callRemote(destination, recipient, call)" --> A_O A_O -- "dispatch(destination, router,
[sender, recipient, call])" --> M_O M_O -. "relay" .- M_D M_D -- "handle(origin, router,
[sender, recipient, call])" --> A_D A_D == "interchainAccount(origin, sender)" ==> SenderAccount SenderAccount -- "call" --> Recipient click A_O https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/middleware/InterchainAccountRouter.sol click A_D https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/middleware/InterchainAccountRouter.sol style Sender fill:#FF0099 style SenderAccount fill:#FF0099 style Recipient fill:#FF0099 ``` ## How Interchain Accounts Work Interchain Accounts allow you to make a remote call from **Chain A** to **Chain B** using the router (`InterchainAccountRouter`). We use [CREATE2](https://docs.openzeppelin.com/cli/2.8/deploying-with-create2) to compute the deterministic [OwnableMulticall](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/middleware/libs/OwnableMulticall.sol) contract address for you, which serves as a proxy for your cross-chain calls. You can explore this [here](./example-usage). Here's how it works: * You can encode your call which includes the to address, call data, and the `msg.value` for each call, batched together in an array. * You send the encoded call to the **Chain A** router which gets relayed to the **Chain B** router. * After decoding the calls, the **Chain B** router checks if the computed address is already deployed or not. If not, we deploy the *OwnableMulticall* contract. * The router then performs a multicall on the ICA address, which in turn makes the desired arbitrary call on **Chain B**. The Interchain Account interface assigns every `(uint32 origin, address owner, address remoteRouter, address remoteISM)` tuple a unique ICA address. The sender owns that ICA on the destination chain, and can direct it to make arbitrary function calls via the `InterchainAccountRouter.callRemote()` endpoint. For core chains supported by Hyperlane, you are able to use the defaults that are set by the owner of the router contract. See the [#overrides](./overrides) section to see how to make calls to *any* chain. ## Interface ```solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; import {CallLib} from "../contracts/libs/Call.sol"; interface IInterchainAccountRouter { function callRemote( uint32 _destinationDomain, CallLib.Call[] calldata calls ) external returns (bytes32); function getRemoteInterchainAccount(uint32 _destination, address _owner) external view returns (address); } ``` * Use `InterchainAccountRouter` out of the box - ICA routers have already been deployed to core chains. Please refer to [addresses](/docs/reference/addresses/deployments/interchainAccountRouter). Try using the `callRemote` method to do a call via your wallet's interchain account. # Superswaps: One-Click Cross-Chain Token Swaps Source: https://docs.hyperlane.xyz/docs/applications/use-cases/cross-chain-swaps This use case explains how [Superswaps](https://velodrome.finance/docs/superswaps) works under the hood using Hyperlane components including [**Interchain Accounts (ICAs)**](/docs/applications/interchain-account), [**Hyperlane Warp Routes (HWR)**](/docs/applications/warp-routes/overview), and the [**Offchain Lookup ISM**](/docs/protocol/ISM/standard-ISMs/offchain-lookup-ISM). ## Overview **[Superswaps](https://velodrome.finance/docs/superswaps)** is a cross-chain swapping mechanism developed by [Velodrome](https://velodrome.finance/) to enable one-click token swaps across the Superchain ecosystems. Warp Route diagram/doodle Instead of requiring users to manually bridge assets and perform separate swaps on different chains, Superswaps uses Hyperlane's interoperability stack to provide multiple cross-chain asynchronous composable transactions via a one-click and a MEV-resistant swapping experience. Before we get into how Superswaps works, let's discuss the challenges there are today. ## Problem As a user, cross-chain swaps traditionally require multiple steps. Let's say you have Token A on Chain A and want to end up with Token B on Chain B. This typically requires: 1. Swap tokens on Chain A (e.g., OP to USDC on Optimism) 2. Manually bridge tokens to Chain B (e.g., Base) 3. Switch to Chain B 4. Swap again into the desired asset (e.g., USDC to DAI) **Challenges:** * **Poor UX**: multiple transactions, wallet interactions, and chain switching * **Liquidity fragmentation**: different pools on each chain ## Solution: Superswaps with Hyperlane Superswaps simplifies this entire process, making it a single click for the user by leveraging Hyperlane's Open Interoperability Framework. ### Key Components * **[Interchain Accounts (ICAs)](/docs/applications/interchain-account)**: Allow a contract on Chain A to execute arbitrary logic on Chain B * **[Hyperlane Warp Routes (HWR)](/docs/applications/warp-routes/overview)**: Bridge assets between chains * **[oUSDT](https://docs.openusdt.xyz/)**: Interchain stablecoin used to transfer value between chains * **[Offchain Lookup ISM](/docs/protocol/ISM/standard-ISMs/offchain-lookup-ISM)**: Provides a way to verify Hyperlane messages using data that's stored off-chain which can be fetched and verified when needed ### Superswap Flow (Step-by-Step) Let's say a user wants to swap **OP on Optimism** → **USDC on Base**. #### Step 1: User initiates Superswap on Optimism (Origin Chain) * User signs **one transaction** via the Velodrome UI. * Behind the scenes, Velodrome: * Swaps user's `OP → oUSDT` (on Optimism) * Prepares an **Interchain Account (ICA)** call to execute a swap on Base #### Step 2: Hyperlane handles bridging and messaging Once the user has signed the single Superswap transaction, the cross-chain orchestration is handled by Hyperlane's interoperability framework. The [Relayer](/docs/protocol/agents/relayer) (a permissionless off-chain agent) is responsible for **carrying 3 distinct messages** across the chains. Each message plays a different role in ensuring tokens move, instructions are committed securely, and execution happens only when verified. **1. oUSDT is bridged via HWR** * [oUSDT](https://docs.openusdt.xyz/), the intermediary token that powers Superswaps, is bridged from origin chain (Optimism) to destination chain (Base) and delivered into the **user’s Interchain Account (ICA)** on Base. * This ensures that the ICA on Base holds the tokens required for the swap. **2. Commitment Message (hash of swap details)** * The second message is the **commitment**. Instead of sending the full swap details, this message only includes a **hash of the swap instruction** (for example, "swap `oUSDT → USDC`). * This message is sent through Hyperlane’s Interchain Account Router to be processed by the [Offchain Lookup ISM](/docs/protocol/ISM/standard-ISMs/offchain-lookup-ISM) (a security module that can fetch data from external sources when needed). The ISM stores the hash onchain as a public record of what was committed, while keeping the actual swap parameters hidden. * The full swap calldata is not placed onchain at this stage. Instead, it is stored offchain on a gateway service. Only the relayer that paid gas fees through Hyperlane's **Interchain Gas Payment (IGP)** system can retrieve it, and it must authenticate itself with an **ECDSA signature** before accessing the data. This protects the swap from MEV by keeping swap details hidden until final execution. MEV Protection with **Offchain Lookup ISM:** The Offchain Lookup ISM enforces the **commit–reveal scheme** before any ICA instruction is executed. * First, the swap details are **committed** onchain as a hash (without revealing the full data). * Later, when the reveal call arrives, the ISM: * Fetches the full calldata from the offchain gateway * Verifies that the hash of this data matches the earlier onchain commitment * Only if the commit and reveal match, the ICA continues to execution. * This process protects the user from MEV by **keeping swap details private** until the moment of execution. **3. Reveal & Execute Message (full swap details)** * The third message is the **reveal and execute** step. This message is passed into the **Destination ICA Router**, which in turn calls the **Offchain Lookup ISM**. * The Reveal message itself doesn't include the full calldata. Instead, it contains a pointer to the offchain gateway plus the relayer's signed proof, which authenticates it as the correct courier. * The **Offchain Lookup ISM** then triggers an offchain lookup. This step fetches the swap calldata from the gateway and returns it back. The ISM recomputes the hash of this calldata and checks it against the earlier commitment stored onchain. If the two match, the message is verified. * Finally, the **Sender ICA** on the destination chain calls the swap function. With the tokens already in place from the HWR, and the calldata now verified, the ICA executes the swap on the destination chain - converting the `oUSDT` into `USDC`. #### Putting it Together To recap: 1. Hyperlane Warp Route delivers tokens cross-chain. 2. Commitment Message locks in the swap hash onchain (but hides details). 3. Reveal Message fetches the real swap data offchain, verifies it against the hash, and then executes the swap. #### ICA Architecture Overview This diagram shows how ICAs work within Superswaps: the Origin Chain dispatches commitment and execution messages, the Offchain infrastructure (Velodrome Gateway and Relayer) coordinates data retrieval and message passing, and the Destination Chain executes swaps through the ICA. Warp Route diagram/doodle ### Result: One-Click Cross-Chain Token Swaps With Superswaps, users receive tokens on the destination chain with a single click * No need to manually bridge * No need to switch networks * No need to execute multiple transactions as the user * Swap is protected from MEV # TaoFi: Cross-Chain Swaps with User-controlled Recovery Source: https://docs.hyperlane.xyz/docs/applications/use-cases/cross-chain-swaps-with-recovery This use case explains how the [**TaoFi Bridge**](https://www.taofi.com/bridge) uses Hyperlane components — including [Interchain Accounts (ICAs)](/docs/applications/interchain-account/overview) and [**Hyperlane Warp Routes (HWR)**](/docs/applications/warp-routes/overview) — to enable cross-chain bridging with slippage protection and a user-controlled recovery. Taofi_Overview.png ## Overview Cross-chain swaps can fail on the destination chain due to slippage or front-running, leaving users with no way to roll back and no control over their funds. The **TaoFi Bridge** solves this by letting users bridge **USDC** across Ethereum, Base, Solana, and Bittensor EVM, while ensuring a **safe fallback** if execution fails. To achieve this, TaoFi relies on key design features: * **Slippage protection**: swaps include minimum-amount parameters that mitigate sandwich attacks. * **Salting**: gives each user a unique account on the destination chain, keeping funds segregated. * **Safe fallback**: if a swap fails, funds remain in the user’s account on the destination chain, where they can be withdrawn or retried. ## Problem Traditionally cross-chain swaps face critical challenges: 1. **Complex UX**: Users often need to bridge, switch chains, and manually swap. 2. **Same destination address for different users:** On the destination chain, all funds typically arrive at the same address. This makes it hard to partition by user, and if a swap fails, there’s no straightforward way to return tokens to the correct owner. 3. **Sandwiching**: On the destination chain, swaps can be front-run by MEV bots, leaving the user with worse execution or failed trades. 4. **Failure cases**: If the swap fails (for example, due to slippage or insufficient liquidity) after funds are bridged, the user can be left without any recovery option. ## Solution: TaoFi Bridge built with Hyperlane TaoFi overcomes these challenges by building on Hyperlane’s interoperability stack. With these components, users can bridge and swap USDC across Ethereum, Base, Solana, and Bittensor EVM in a single click — while keeping control of their funds even if execution fails. ## Key Components & Features TaoFi is built on Hyperlane’s core components, and makes use of higher-level features which they enable. * [**Interchain Accounts (ICAs)**](/docs/applications/interchain-account): Enable a contract on Chain A to execute arbitrary logic on Chain B * [**Hyperlane Warp Routes (HWR)**](/docs/applications/warp-routes/overview): Bridge assets between chains * **Salting**: The ICA router supports a `salt` parameter for account derivation. By passing the user’s address as the salt, each user gets a unique destination account. This ensures funds are partitioned by user and can be managed or refunded safely if a swap fails. * **Failure handling with [Transfer-and-Call](/docs/guides/warp-routes/evm/transfer-and-call-pattern) and Unique User Account Addresses**: By using the *Transfer and Call* pattern, applications can bridge tokens first and then execute the contract functions (e.g.: swap) only after the assets arrive. If that action fails (for example, due to slippage), the tokens remain safely in the user’s unique account on the destination chain. The user can then choose to retry with new parameters or withdraw their funds, ensuring they never lose control. * **Slippage checks (minimum amount parameter):** By including minimum-amount parameters in the remote call, applications prevent sandwiching from succeeding. If someone tries to sandwich the trade, the swap will no longer meet the min amount condition. Instead of executing at a worse price, the transaction fails safely and lets the user decide on what to do with the bridged funds. ## How it works (step-by-step) Let’s say a user wants to swap **USDC on Bittensor EVM** → **USDC on Base.** ### Step 1: User initiates swap on **Bittensor EVM** * The user signs a **single transaction** in the TaoFi UI. * Behind the scenes: * The contract derives a **salted Interchain Account** for the user on Base. * A Transfer and Call request is created, which includes the amount to bridge and the swap action to run on Base. ### Step 2: Hyperlane bridges tokens and message The cross-chain orchestration is handled by Hyperlane’s interoperability framework. The [**Relayer**](/docs/protocol/agents/relayer) (a permissionless off-chain agent) carries the 2 messages across the chains. * **Message 1**: Funds are bridged from Bittensor EVM to Base using HWR. They arrive in the user’s **unique ICA** on Base (generated using the `salt` parameter). * **Message 2**: The execution request tells the user’s ICA to perform the swap on Base. This message includes the **minimum amount parameter** that protects against sandwiching and slippage. ### Step 3: Execution on Base and failure handling * Once the funds arrive onto the remote chain, Hyperlane delivers the swap call to the ICA router. The user’s ICA executes the call on Base (converting into USDC on Base). * If the swap cannot meet the **minimum amount condition** (for example, due to slippage), the transaction will not be processed. * The funds remain in the user’s ICA, and the user can then: * Retry the swap with updated parameters, or * Withdraw the funds directly. ## Architecture Diagram TaoFi Architecture ## Putting It Together To recap: 1. HWR delivers funds cross-chain. 2. Salting creates a **unique address** for each user on the destination chain. 3. The ICA executes the swap on the remote chain, and slippage checks ensure it only goes through if the user’s minimum amount is met. If not, it fails safely. 4. The fallback mechanism ensures users stay in control even if the action fails. ## Result: Cross-Chain Swaps with a Safety Net With TaoFi, users can swap tokens across Ethereum, Base, Solana, and Bittensor EVM. * No need to manually bridge * Deterministic, isolated ICAs for every user * Users remain in control even when swaps don’t execute # HWR Example Usage Source: https://docs.hyperlane.xyz/docs/applications/warp-routes/example-usage Hyperlane Warp Routes (HWR) define how assets move between chains, whether as native tokens, synthetic representations, or collateral-backed assets. The choice of route depends on the asset type and the desired behavior on the destination chain. ## HWR Combinations ### 1. Native to Native This route allows for the transfer of native tokens between chains that both use their own native tokens. This type of route should only be used when both networks have native tokens of equivalent value, e.g. inEVM & Ethereum. #### Setup * **HypNative** contract deployed on both chains. #### Example Flow ``` Transaction Type: Native to Native Transfer From: Ethereum (ETH) To: inEVM (ETH) Amount: 1 ETH ``` #### Diagram ```mermaid theme={null} graph LR A[Alice on Ethereum] -->|1 ETH| B(Ethereum HypNative) B -->|Message| C(inEVM HypNative) C -->|ETH equivalent| D[Alice on inEVM] ``` #### Use Case * Alice wants to quickly move value from Ethereum to inEVM. ### 2. Native to Synthetic This route creates a synthetic representation of a native token on another chain. #### Setup * **HypNative** contract deployed on the origin chain where the native asset exists. * **HypERC20** contract deployed on the destination chain where the synthetic token is minted. #### Example Flow ``` Transaction Type: Minting Synthetic Token from Native Token From: Celo (CELO) To: Optimism (wCELO) Amount: 100 CELO ``` #### Diagram ```mermaid theme={null} graph LR A[Alice on Celo] -->|100 CELO| B(Celo HypNative) B -->|Message| C(Optimism HypERC20) C -->|Mint 100 wCELO| D[Alice on Optimism] ``` #### Use Case * A Celo-based project wants to make their native CELO token available for use on Optimism. ### 3. Collateral to Synthetic This route allows for the creation of synthetic tokens based on collateralized ERC20 tokens. #### Setup * **Collateral contract (HypERC20Collateral)** is deployed on the source chain where the original asset exists. * **Synthetic contract (HypERC20)** is deployed on the destination chain, where the asset is minted. #### Example Flow ``` Transaction Type: Minting Synthetic Token from Collateral Token From: Ethereum (USDC - Original Asset) - Collateral Source To: Arbitrum (wUSDC - Minted Synthetic Asset) - Synthetic Destination Amount: 1000 USDC ``` #### Diagram ```mermaid theme={null} graph LR A[Alice on Ethereum] -->|1000 USDC| B(Ethereum HypERC20Collateral) B -->|Message| C(Arbitrum HypERC20) C -->|Mint 1000 wUSDC| D[Alice on Arbitrum] ``` #### Use Case * Alice wants to use her USDC on Arbitrum without moving actual USDC to Arbitrum or relying on Arbitrum's bridged USDC. # HWR Interface Source: https://docs.hyperlane.xyz/docs/applications/warp-routes/interface Hyperlane Warp Routes (HWR) implement the `ITokenBridge` interface. ```solidity theme={null} interface ITokenBridge { /** * @notice Transfers tokens to the specified recipient on a remote chain * @param _destination The domain ID of the destination chain * @param _recipient The address of the recipient, encoded as bytes32 * @param _amount The amount of tokens the recipient should receive */ function transferRemote( uint32 _destination, bytes32 _recipient, uint256 _amount ) external payable; struct Quote { address token; // Token address (address(0) for native token) uint256 amount; // Fee amount in the specified token } /** * @notice Quotes the fees required for a remote transfer * @param _destination The domain ID of the destination chain * @param _recipient The address of the recipient, encoded as bytes32 * @param _amount The amount of tokens to transfer * @return quotes An array of Quote structs representing fees in different tokens */ function quoteTransferRemote( uint32 _destination, bytes32 _recipient, uint256 _amount ) external view returns (Quote[] memory quotes); } ``` ## Fee Quoting Interface New in version 10.0.0: The `quoteTransferRemote` function provides a standardized way to quote fees for warp route transfers. Only applicable to routes that return >= 10.0.0 from `PACKAGE_VERSION()`. ### Quote Structure The `quoteTransferRemote` function returns an array of `Quote` structs with the following convention: 1. **Index 0: Native Fees** * Token: `address(0)` (native token like ETH, MATIC, etc.) * Amount: Fees charged by the mailbox for dispatching the message * This must be sent as `msg.value` when calling `transferRemote` 2. **Index 1: Token Fees** * Token: The ERC20 token being bridged. * Amount: `_amount + internalFeeAmount` * This is the total amount of tokens that must be sent/approved, including any internal fees charged by the warp route ### Exact Amount Out Semantics Warp routes use "exact amount out" semantics, meaning: * The `_amount` parameter in `transferRemote` specifies the **exact amount the recipient receives** * Fees are charged **on top** of this amount from the sender * Total tokens required = `_amount + internalFeeAmount + externalFeeAmount` **Example:** ```solidity theme={null} // Get fee quote Quote[] memory quotes = warpRoute.quoteTransferRemote( destinationDomain, recipientAddress, 1000e18 // Recipient will receive exactly 1000 tokens ); // quotes[0]: Native fee (e.g., 0.00001 ETH) uint256 nativeFee = quotes[0].amount; // quotes[1]: Token amount (e.g., 1001e18 = 1000 + 1 fee) uint256 tokenFee = quotes[1].amount; // Approve warp route for token transfer IERC20(quotes[1].token).approve( address(warpRoute), tokenFee // 1001e18 total ); // Transfer with native fee warpRoute.transferRemote{value: nativeFee}( destinationDomain, recipientAddress, 1000e18 // Recipient receives exactly 1000 tokens ); ``` **Important:** Always query fees immediately before the transfer with the consistent parameters, as fees may change based on destination, recipient, amount, gas prices, exchange rates, or warp route configuration. ## Deploy your HWR Ready to deploy your HWR? It's easy, follow the [step-by-step guide](/docs/guides/quickstart/deploy-warp-route). # HWR 2.0 Source: https://docs.hyperlane.xyz/docs/applications/warp-routes/multi-collateral-warp-routes Hyperlane Warp Routes 2.0 are a type of Hyperlane Warp Route (HWR) that allows liquidity to be sourced from multiple collateral chains with native rebalancing for supported configurations. ## Overview In a single-collateral HWR, tokens are locked on one source chain. Example: * Lock 100 USDC on Ethereum * Mint 100 USDC on NewChain Hyperlane Warp Routes 2.0, on the other hand, allows users to bridge from multiple collateral chains. Example: * Lock 50 USDC on Base * Lock 50 USDC on Arbitrum * Mint 100 USDC on NewChain This setup allows a destination chain to receive assets from multiple sources, making it easier for users to onboard liquidity without depending on a single origin. ## Rebalancing If more funds flow in one direction, one of the chains in the route can run out of collateral, creating imbalanced flow that prevents withdrawals. To maintain a smooth user experience, collateral must be balanced across chains. HWR 2.0 supports three rebalancing options depending on the token and chain: | Method | Tokens | How | | -------------------------------------------------------------------------------------------------------------------- | --------- | -------------------------------------------------------------------------- | | [USDC Rebalancing](/docs/guides/warp-routes/evm/multi-collateral-warp-routes-rebalancing#usdc-rebalancing) | USDC | Automatic, via CCTP on supported chains | | [Inventory Rebalancing](/docs/guides/warp-routes/evm/multi-collateral-warp-routes-rebalancing#inventory-rebalancing) | USDT, ETH | Automatic, via a cross-chain liquidity aggregator on EVM-compatible chains | | [Manual Rebalancing](/docs/guides/warp-routes/evm/multi-collateral-warp-routes-rebalancing#manual-rebalancing) | Any | LPs manually move collateral using the CLI or UI | ## Supported Tokens and Protocols | Token | Method | Chains | | ----- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | USDC | USDC Rebalancing | Arbitrum, Avalanche, Base, Ethereum, HyperEVM, Ink, Linea, OP Mainnet, Plume, Polygon PoS, Sei, Sonic, Unichain, World Chain. Additional chains supported by [Circle CCTP](https://developers.circle.com/cctp) v1/v2 will roll out incrementally. | | USDT | Inventory Rebalancing | EVM-compatible chains. Additional chains planned. | | ETH | Inventory Rebalancing | EVM-compatible chains. Additional chains planned. | ## Guides * To deploy Hyperlane Warp Routes 2.0 head over to [Deploy a Hyperlane Warp Route 2.0](/docs/guides/warp-routes/evm/deploy-multi-collateral-warp-routes) # HWRs Overview Source: https://docs.hyperlane.xyz/docs/applications/warp-routes/overview Hyperlane Warp Routes (HWR) are modular cross-chain asset bridges that enable the transfer of tokens between chains using Hyperlane. Developers can use Hyperlane to permissionlessly deploy HWRs to move assets between chains. They support various asset types, including: * ERC20 & ERC721 tokens (for EVM-compatible chains) * SVM-based assets (for SVM-compatible chains) * Native tokens (such as ETH, or other gas tokens) You can combine HWR with a Hyperlane deployment to create economic routes between any chain and others already connected through Hyperlane. ## Modular Security Like all applications built on top of Hyperlane, HWRs have customizable security via [Interchain Security Modules](../../protocol/ISM/modular-security). The deployer of a HWR can specify the ISMs that are used to verify interchain transfer messages. This means that each HWR may have a unique security configuration. Users transferring interchain tokens should understand the trust assumptions of a Route before using it. Similarly, Warp frontends should manually curate their HWR to avoid supporting insecure ones. See the [Warp UI deployment docs](/docs/guides/warp-routes/bridge-ui-guide) details. ## HWR Architecture HWR let deployers choose how tokens are transferred between chains. Depending on the type of HWR, contracts will lock tokens, mint wrapped tokens, burn wrapped tokens, or release original tokens. For example: 1. **Collateral → Synthetic**: Tokens are locked on the origin (collateral) chain, a message is sent, and wrapped tokens are minted on the destination (synthetic) chain. 2. **Native → Synthetic**: Native gas tokens (e.g., ETH) are locked on the origin chain, a message is sent, and synthetic tokens are minted on the destination chain. 3. **Native → Collateral**: Native tokens are locked on the origin chain, a message is sent, and collateral tokens are released on the destination chain. Each HWR requires a contract deployed on every chain its on that acts as an entry/exists point. These contracts use the [Mailbox](/docs/protocol/core/mailbox) to send interchain messages to one another. ### HWR Types This table gives a high-level overview of HWR types. For detailed explanations, see: [HWR Types.](./types) | **HWR Type** | **Description** | | ------------------------- | ------------------------------------------------------------------------------------------------ | | Native Token HWRs | Enables direct transfers of native gas tokens (e.g., ETH) across chains without wrapping. | | Collateral-Backed ERC20 | Locks ERC20 tokens as collateral on the source chain for cross-chain transfers. | | Synthetic ERC20 | Mints new ERC20 tokens on the destination chain to represent the original tokens. | | Hyperlane Warp Routes 2.0 | Allows liquidity to be sourced from multiple collateral tokens. | | Specialized HWR | Adds advanced features or integrates with specific use cases (e.g., vaults, fiat-backed tokens.) | ### Example Architecture Let’s walk through a **Collateral** to **Synthetic** HWR using the lock-and-mint model to transfer ERC20 tokens between two chains: 1. The user locks their tokens on the collateral chain (e.g., Ethereum) in the HWR contract. 2. A message is sent through Hyperlane’s Mailbox and relayed to the synthetic chain (e.g., Base). 3. On the destination chain, the HWR contract mints wrapped tokens to the user. In the diagram below, the ISM is a [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM), which uses a set of validators to approve messages. (Note: Not all ISMs require validators, this depends on the chosen security model.) Here’s a simplified view of the flow: Warp Route diagram/doodle ## Deploy a HWR HWR can be deployed between any set of chains that have Hyperlane deployments. To deploy a HWR, head over to the following guides: * [EVM-based HWR](/docs/guides/quickstart/deploy-warp-route) * [SVM-based HWR](/docs/guides/warp-routes/svm/svm-warp-route-guide) * [EVM-SVM HWR](/docs/guides/warp-routes/evm-svm-warp-route-guide) If you would like to create a HWR that includes a chain that Hyperlane is not currently deployed on, feel free to [deploy Hyperlane](/docs/guides/chains/deploy-hyperlane) yourself! # HWR Types Source: https://docs.hyperlane.xyz/docs/applications/warp-routes/types Hyperlane Warp Routes (HWR) are Hyperlane's implementation of token bridging, allowing for permissionless transfer of native, ERC20, and synthetic (newly deployed ERC20) assets across any chain via Hyperlane. This document provides details on all HWR types. | **HWR Types** | **Description** | | ------------------------- | ------------------------------------------------------------------------------------------------ | | Native Token HWR | Enables direct transfers of native gas tokens (e.g., ETH) across chains without wrapping. | | Collateral-Backed ERC20 | Locks ERC20 tokens as collateral on the source chain for cross-chain transfers. | | Synthetic ERC20 | Mints new ERC20 tokens on the destination chain to represent the original tokens. | | Hyperlane Warp Routes 2.0 | Allows liquidity to be sourced from multiple collateral tokens. | | Specialized HWR | Adds advanced features or integrates with specific use cases (e.g., vaults, fiat-backed tokens.) | *Please note that this document does not include ERC721 HWR.* ## Core HWR Types ### Native Token HWR Implemented in `HypNative.sol`, native HWRs handle the transfer of native gas tokens (e.g. ETH on Ethereum or Arbitrum, MNT on Mantle) across different chains. #### Features * Directly transfers native tokens without wrapping. * Uses `msg.value` for transfer amount. * Handles excess `msg.value` as hook payment. * Supports donations through a `receive()` function. See [the implementation](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/HypNative.sol) for more details. ### Collateral-Backed ERC20 HWR Implemented in `HypERC20Collateral.sol`, collateral HWRs enable ERC20 tokens to be locked as collateral on the source chain and then used to mint a synthetic representation on the destination chain. #### Features * Wraps existing ERC20 tokens as collateral for transfers. * Locks tokens in the contract on the source chain. * Releases equivalent tokens on the destination chain. * Uses SafeERC20 for secure token transfers. See [the implementation](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/HypERC20Collateral.sol) for more details. ### Synthetic ERC20 HWRs Implemented in `HypERC20.sol`, synthetic HWRs mint new tokens on the destination chain that represent the original tokens from the source chain. The original tokens are not transferred but remain locked. #### Features * Maintains consistent total supply across all chains. * Supports custom token attributes (name, symbol, decimals). * Mints new tokens on the destination chain. * Burns tokens on the source chain when transferred back. See [the implementation](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/HypERC20.sol) for more details. ## Advanced Features ### TokenRouter Functionality All HWR extend the `TokenRouter` contract, which provides the core functionality for HWR token transfers. #### Features 1. **Message Structure**: Uses [TokenMessage](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/libs/TokenMessage.sol) library for encoding and decoding token transfer messages. 2. **Transfer Initiation**: `transferRemote` function initiates cross-chain transfers. 3. **Message Handling**: `_handle` function processes incoming transfer messages. 4. **Abstract Methods**: * `_transferFromSender`: Implemented by all HWRs to handle token collection. * `_transferTo`: Implemented by all HWRs to handle token distribution. #### TokenMessage Format ```solidity theme={null} [32 bytes for recipient][32 bytes for amount][remaining bytes for metadata] ``` This standardized format ensures consistent handling across different HWR implementations while allowing for extensibility through metadata. See [the implementation](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/libs/TokenRouter.sol) for more details. ### FastTokenRouter Transfers Implemented in `FastTokenRouter.sol`, this router extends TokenRouter and provides faster token transfers through a liquidity provider mechanism. #### Features * Allows liquidity providers to fulfill transfer requests before message processing. * Includes a `fastFee` to incentivize liquidity providers. * Introduces `fastTransferId` for unique transfer identification. See [the implementation](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/libs/FastTokenRouter.sol) for more details. ## Specialized HWR Extensions ### 1. Fast Collateral Transfers (FastHypERC20Collateral) * Combines fast transfer capabilities with collateral-backed ERC20 functionality. * See [the implementation](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/extensions/FastHypERC20Collateral.sol) for more details. ### 2. Vault Integration (HypERC4626OwnerCollateral, HypERC4626Collateral) * Allows for yield generation on collateral by integrating with ERC-4626 vaults. * See [the implementation](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/extensions/HypERC4626OwnerCollateral.sol) & [rebasing variant](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/extensions/HypERC4626Collateral.sol) and for more details. ### 3. Fiat-Backed Tokens (HypFiatToken) * Designed for stablecoins and other fiat-backed tokens, implementing specific mint and burn operations. * See [the implementation](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/extensions/HypFiatToken.sol) for more details. ### 4. Scaled Native Tokens (HypNativeScaled) * Scales native token values for consistency across chains with different decimals. * See [the implementation](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/extensions/HypNativeScaled.sol) for more details. ### 5. xERC20 Integration (HypXERC20 & HypXERC20Lockbox) * Enables cross-chain transfers of xERC20 tokens, integrating with lockbox mechanisms for conversions. * See the [HypXERC20 implementation](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/extensions/HypXERC20.sol) and the [HypXERC20Lockbox implementation](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/token/extensions/HypXERC20Lockbox.sol) for more details. ## References For setup examples & use cases, check out [HWRs: Example Usage](./example-usage). # Ecosystem Source: https://docs.hyperlane.xyz/docs/ecosystem Projects building on Hyperlane across DeFi, stablecoins, privacy, and custom VMs Hyperlane Ecosystem Hyperlane provides the base layer for interoperability. This page shows what's possible with Hyperlane's primitives and how teams are using them in production. *** ## DeFi & Cross-Chain Swaps Cross-chain swapping mechanism enabling one-click token swaps across the Superchain ecosystem. Cross-chain USDC swaps with built-in failure recovery using Hyperlane Warp Routes and salted ICAs. High-performance perpetuals DEX on Starknet using Hyperlane Warp Routes for cross-chain transfers. Liquid restaking protocol using Hyperlane Warp Routes to extend ezETH across multiple chains. Private transaction infrastructure for cross-chain transfers via API. *** ## Custom VM Implementations Hyperlane supports chains with non-EVM execution environments through bespoke VM implementations. These integrations include the full Hyperlane stack: [Mailbox](/docs/protocol/core/mailbox), [Hyperlane Warp Routes](/docs/protocol/warp-routes/warp-routes-overview), [ISMs](/docs/protocol/ISM/modular-security), and [agent infrastructure](/docs/protocol/agents/overview). *** ## Build with Us Connect with the ecosystem team to start building on Hyperlane. # Get Started Building with Hyperlane Source: https://docs.hyperlane.xyz/docs/get-started-building Build cross-chain applications in three steps. Whether you're creating token bridges, cross-chain NFTs, or interchain messaging, this guide will get you started. ## Step 1: Identify Your Virtual Machine Choose the blockchain environments where you want to enable interchain functionality. Hyperlane supports multiple VM types including EVM chains (Ethereum, Polygon, Arbitrum), Cosmos and Solana. **What you need to decide:** * Source chain (where messages originate) * Destination chain(s) (where messages are delivered) * Gas token requirements for each chain *** ## Step 2: Deploy Hyperlane Core Infrastructure Deploy core Hyperlane contracts, this includes core Mailbox and ISM contracts. **Before deploying, check if Hyperlane is already available on your chain:** Check the [Hyperlane registry](https://github.com/hyperlane-xyz/hyperlane-registry) to learn which chains have a Hyperlane deployment. If the chain you are looking to connect already has Hyperlane core contracts deployed, skip to Step 3! **If you need to deploy:** * Use the Hyperlane CLI for automated deployment * Configure your security settings * Deploy the Hyperlane core contracts [Deploy Hyperlane infrastructure →](/docs/guides/chains/deploy-hyperlane) *** ## Step 3: Create Your Hyperlane Warp Route (HWR) Bridge your tokens using Hyperlane's messaging infrastructure. Hyperlane Warp Routes are modular cross-chain asset bridges using Hyperlane's messaging infrastructure. Learn more about how they work. **Common HWR types:** * **ERC-20 HWR**: Bridge any ERC-20 token * **Native HWR**: Move native tokens (ETH, SOL, etc.) * **Collateral HWR**: Lock tokens on origin, mint on destination * **Synthetic HWR**: Create wrapped versions on destination chains **Choose your deployment guide:** Deploy on Ethereum, Polygon, Arbitrum, and other EVM chains Deploy on Solana and other Sealevel VM chains Deploy on Cosmos SDK-based chains **Advanced HWRs**: Check out our [HWR resources](/docs/applications/warp-routes/types) and [HWR guides](/docs/guides/warp-routes) for more complex use cases. *** ## Next Steps Create a user interface for your HWR Deploy Hyperlane with local Validators and Relayers Configure custom security for your interchain messages ## Need Help? Join [GitHub Discussions](https://github.com/hyperlane-xyz/hyperlane-monorepo/discussions) for support! # Deploy to a New Chain Source: https://docs.hyperlane.xyz/docs/guides/chains/deploy-hyperlane Step-by-step guide on how to connect your chain with Hyperlane * This guide is for **EVM-compatible** chains only. * For Cosmos SDK chains, use [Deploy to a Cosmos Chain](/docs/guides/chains/deploy-hyperlane-cosmos). * It will walk you through deploying Hyperlane to your new chain as quickly as possible for testing, not production. This includes the core Mailbox and ISM contracts as well as Hyperlane Warp Route contracts for asset bridging. * To see which chains are already supported, visit the [Registry](https://github.com/hyperlane-xyz/hyperlane-registry/tree/main/chains). * If you need any help, reach out on [GitHub Discussions](https://github.com/hyperlane-xyz/hyperlane-monorepo/discussions) or [get in touch](https://forms.gle/KyRTaWvo4XNmNvrq6). ## Prerequisites Anyone can begin this quickstart guide once they have the following artifacts & assets available: * A new, custom, or pre-existing network of your choice, including the following metadata: * A chain name, e.g. `ethereum` * A chain ID, e.g. `1` * A RPC URL, e.g. `https://eth.llamarpc.com` * A deployer wallet/EOA private key or seed phrase * This EOA should be funded on your custom chain and any chain you will be passing messages to & from * [Hyperlane CLI](/docs/reference/developer-tools/cli) ## 1. Registry Let’s create a custom chain config, run: ```bash theme={null} hyperlane registry init ``` Follow the prompts to set up your chain metadata. Setting up block or gas properties is optional. Now, under `$HOME/.hyperlane/chains` you will find a new folder named with your custom chain’s name, and a file named `metadata.yaml` within that folder.
Example content of this config at `$HOME/.hyperlane/chains/yourchain/metadata.yaml` ```yaml theme={null} # yaml-language-server: $schema=../schema.json # Metadata for your custom chain blockExplorers: - apiUrl: https://explorer.yourchain.com/api apiKey: XXXX # helpful to avoid rate limiting on the contract verification API family: etherscan #explorer you're using, also supporting routescan or blockscout name: Chainscan url: https://explorer.yourchain.com blocks: confirmations: 1 estimateBlockTime: 1 reorgPeriod: 0 chainId: 171717 displayName: Chain Name domainId: 171717 isTestnet: true # optional name: yourchain nativeToken: name: Ether symbol: ETH decimals: 18 protocol: ethereum rpcUrls: - http: https://hyper-lane-docs.rpc.caldera.xyz/http ```
## 2. Core Next, let’s configure, deploy and test your custom chain’s core contracts. ### Initialize configuration 1. From your local environment, set the private key or seed phrase of your funded deployer address to `HYP_KEY`. For example: `export HYP_KEY=''` 2. From the same terminal instance, run: ```bash theme={null} hyperlane core init ```
The deployment config will be written to `./configs/core-config.yaml` ```yaml theme={null} # The address that owns and manages the deployed contracts. This account has admin privileges. owner: "0x16F4898F47c085C41d7Cc6b1dc72B91EA617dcBb" # The default Interchain Security Module (ISM) configuration. defaultIsm: #`type`: Specifies the type of ISM. Here, it uses a trusted relayer ism. type: trustedRelayerIsm #`relayer`: The address of the relayer responsible for processing interchain messages. relayer: "0x16F4898F47c085C41d7Cc6b1dc72B91EA617dcBb" defaultHook: # A hook configuration that specifies the use of a Merkle Tree. type: merkleTreeHook requiredHook: # The owner address responsible for managing the hook configuration. owner: "0x16F4898F47c085C41d7Cc6b1dc72B91EA617dcBb" # The type of hook. This one applies a protocol fee mechanism. type: protocolFee # The address that receives the protocol fees. beneficiary: "0x16F4898F47c085C41d7Cc6b1dc72B91EA617dcBb" # The maximum fee allowed by the protocol, in wei. maxProtocolFee: "100000000000000000" # The current fee charged by the protocol, set to 0 for testing purposes. protocolFee: "0" ```
### Deploy contracts To deploy contracts, run: ```bash theme={null} hyperlane core deploy ``` Use the arrows and enter to select your custom chain from the bottom of the mainnet list. It will take a few minutes for all contracts to deploy.
Under `$HOME/.hyperlane/chains` you will find a new folder named with your custom chain’s name, and a file named `addresses.yaml` within that folder ```yaml theme={null} staticMerkleRootMultisigIsmFactory: "0x6906cb4741d3E2322E9f9aA645DfC8AB6F122c47" staticMessageIdMultisigIsmFactory: "0x3CE97a32d9C8294691cBd2baC09B078EDa75c429" staticAggregationIsmFactory: "0x81f969fDBF48278Ce09685Ce48e03388B6785aF4" staticAggregationHookFactory: "0x3d864A3c25F61E3c3A7d02e980453A6E1f0a92A6" domainRoutingIsmFactory: "0xC4c01f7B03f0fFa77A0265C600dEF7Ad28BCa5A2" proxyAdmin: "0xABb7175d5F123172E7B7Fa467CC9fE4C2FEdb942" mailbox: "0x5F58d75A9caDE4e2b191313223978dF049f93b81" interchainAccountRouter: "0x43c0745b0dE9Cb780816a24ddE63d79Ca99B5dE8" interchainAccountIsm: "0x9C96dC8f4257413225d6B5C47d1afbafc39B269F" validatorAnnounce: "0xE3bd39BF92DB385dE6313D6070b035bD934378CB" testRecipient: "0xa58462b1943Be1469Ed58db690C78583BA34Fd2E" ```
* `eth_getStorageAt()` Compatibility: Some chains may not utilize the [`eth_getStorageAt()`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getstorageat) API. If your deployment encounters related issues, refer to the [Troubleshooting Guide](/docs/guides/deploy-hyperlane-troubleshooting#eth-getstorageat-compatibility). ### Send test message To send a test message, run: ```bash theme={null} hyperlane send message --relay ``` The `--relay` flag is optional and will deliver the message to the destination chain. You can also run a relayer in the background with ```bash theme={null} hyperlane relayer --chains yourchain,sepolia ``` **🎉 Congrats! You have successfully sent a message to your custom chain** ## 3. Hyperlane Warp Route Now that you have a Hyperlane Mailbox and core contracts on your chain, it’s time to set up token bridging between your chain and any other Hyperlane chain. Continue on to the [Deploy a Hyperlane Warp Route](/docs/guides/quickstart/deploy-warp-route) docs for more details. ## 4. Submit to Registry If you want other chains to connect with you as well as to take this to production, make a registry PR. ### Ensure complete info Make sure your metadata is complete: * add a `logo.svg` file inside the folder * include `Deployer` information identifying the team deploying * indicate `isTestnet` `true` if the chain is testnet * add the api url `gnosisSafeTransactionServiceUrl` if you have a gnosis safe service * lint the yaml files and order alphabetically ### Commit to GitHub First, navigate to your local instance of the registry and commit changes ```bash theme={null} cd ~/.hyperlane && git init && git add . && git commit ``` Then, sync local registry with canonical registry ```bash theme={null} git remote add canonical git@github.com:hyperlane-xyz/hyperlane-registry.git git pull canonical main --rebase ``` Finally, push local registry to github fork and submit a PR. Please include a [changeset](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md) in your PR. **Congrats! You have successfully deployed Hyperlane to your chain and added your work to the Hyperlane registry** Thank you for contributing to the future of permissionless interop 🫡 # Deploy to a Cosmos Chain Source: https://docs.hyperlane.xyz/docs/guides/chains/deploy-hyperlane-cosmos Step-by-step guide on how to connect your Cosmos SDK chain with Hyperlane * This guide is for **Cosmos SDK** chains with the Hyperlane module integrated. For CosmWasm-based chains, see the [CosmWasm implementation](https://github.com/many-things/cw-hyperlane). * It will walk you through deploying Hyperlane to your new chain as quickly as possible for testing, not production. This includes the core Mailbox and ISM components as well as Hyperlane Warp Route components for asset bridging. * To see which chains are already supported, visit the [Registry](https://github.com/hyperlane-xyz/hyperlane-registry/tree/main/chains). * If you need any help, reach out on [GitHub Discussions](https://github.com/hyperlane-xyz/hyperlane-monorepo/discussions) or [get in touch](https://forms.gle/KyRTaWvo4XNmNvrq6). ## Prerequisites Anyone can begin this quickstart guide once they have the following artifacts & assets available: * A Cosmos SDK chain with the Hyperlane module integrated (including the `x/core` and `x/warp` modules) * A new, custom, or pre-existing Cosmos SDK network of your choice, including the following metadata: * The chain name, e.g. `hyp1` * The chain ID, e.g. `hyperlane-local-1` * The bech32 prefix, e.g. `hyp` * RPC, REST, and gRPC URLs * Native token denomination and gas price * A deployer wallet hex private key (64 hex characters, with or without `0x` prefix) * This wallet should be funded on your custom chain and any chain you will be passing messages to & from * If you use a mnemonic wallet, export/derive the raw hex private key before running CLI commands * [Hyperlane CLI](/docs/reference/developer-tools/cli) ## 1. Registry The `hyperlane registry init` command is currently designed for EVM chains and does not support Cosmos SDK chains. Instead, create your chain metadata file manually. Create the directory and file: ```bash theme={null} mkdir -p $HOME/.hyperlane/chains/yourchain ``` Then create `$HOME/.hyperlane/chains/yourchain/metadata.yaml` with the following content, replacing values with your chain's details: ```yaml theme={null} # yaml-language-server: $schema=../schema.json # Metadata for your custom Cosmos chain bech32Prefix: hyp chainId: hyperlane-local-1 displayName: My Cosmos Chain domainId: 758986691 # Must be globally unique; generate with: python3 -c 'print(int("NAME".encode().hex(), 16) % 4_294_967_295)' name: yourchain protocol: cosmosnative slip44: 118 nativeToken: decimals: 6 denom: uhyp name: TEST symbol: TEST gasPrice: amount: '0.2' denom: uhyp rpcUrls: - http: http://127.0.0.1:26657 restUrls: - http: http://127.0.0.1:1317 grpcUrls: - http: http://127.0.0.1:9090 blockExplorers: - name: My Chain Explorer url: https://mychain.com/explorer apiUrl: https://mychain.com/explorer/api ``` Key Cosmos-specific fields: * **`protocol: cosmosnative`** — Must be exactly `cosmosnative` (not `cosmos` or `ethereum`) * **`bech32Prefix`** — Your chain's address prefix (e.g. `cosmos`, `osmo`, `hyp`) * **`slip44`** — [SLIP-44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md) coin type (use `118` for standard Cosmos chains) * **`grpcUrls`** — Required for Cosmos SDK chains * **`gasPrice`** — Must include both `amount` and `denom` * **`nativeToken.denom`** — The on-chain denomination (e.g. `uatom`, `uosmo`) * **`domainId`** — Must be unique across the Hyperlane network (do not reuse another chain's domain) ## 2. Core Next, let’s configure, deploy and test your custom chain’s core components. ### Create Configuration 1. Set the hex private key of your funded deployer address for Cosmos-native operations: * `export HYP_KEY_COSMOSNATIVE=''` (64 hex characters, with or without `0x` prefix) * Or pass `--key.cosmosnative` directly to deploy commands 2. Create `./configs/core-config.yaml` using the template below. `HYP_KEY` is treated as the legacy Ethereum shared key in the current CLI. For Cosmos SDK chains, use `HYP_KEY_COSMOSNATIVE` (or `--key.cosmosnative`) to avoid key prompts.
Use this template for `./configs/core-config.yaml` ```yaml theme={null} # The address that owns and manages the deployed components. This account has admin privileges. owner: "hyp1jq304cthpx0lwhpqzrdjrcza559ukyy3sc4dw5" # The default Interchain Security Module (ISM) configuration. defaultIsm: # Specifies the type of ISM. Here, it uses a multisig ISM. type: merkleRootMultisigIsm threshold: 1 validators: # Validators use hex addresses (0x...) even on Cosmos chains. - '0x0c60e7eCd06429052223C78452F791AAb5C5CAc6' defaultHook: # A hook configuration that specifies the use of an Interchain Gas Paymaster. type: interchainGasPaymaster owner: "hyp1jq304cthpx0lwhpqzrdjrcza559ukyy3sc4dw5" beneficiary: "hyp1jq304cthpx0lwhpqzrdjrcza559ukyy3sc4dw5" # Address authorized to set gas oracle prices. On Cosmos, typically the same as owner. oracleKey: "hyp1jq304cthpx0lwhpqzrdjrcza559ukyy3sc4dw5" overhead: hyp: 200000 oracleConfig: hyp: gasPrice: '1' tokenDecimals: 6 tokenExchangeRate: '10000000000' requiredHook: # The type of hook. This one applies a Merkle Tree for message dispatch. type: merkleTreeHook ```
### Deploy To deploy, run: ```bash theme={null} hyperlane core deploy ``` Use the arrows and enter to select your custom chain from the bottom of the list. It will take a few minutes for all components to deploy.
Under `$HOME/.hyperlane/chains` you will find a new folder named with your custom chain’s name, and a file named `addresses.yaml` within that folder ```yaml theme={null} # Example — your actual Hex32 IDs will differ mailbox: "0x68797065726c616e650000000000000000000000000000000000000000000000" validatorAnnounce: "0x68797065726c616e650000000000000000000000000000000000000000000000" staticMerkleRootMultisigIsmFactory: "0x68797065726c616e650000000000000000000000000000000000000000000000" # Populated based on your ISM type # Other factory fields may appear as empty strings ```
[Aggregation ISMs](/docs/protocol/ISM/standard-ISMs/aggregation-ISM) are currently not supported on Cosmos SDK chains due to AltVM limitations. Use `messageIdMultisigIsm` or `merkleRootMultisigIsm` instead. ### Verify Deployment After deployment, verify your core components are configured correctly: ```bash theme={null} hyperlane core read --chain yourchain ``` `hyperlane send message` does not currently support Cosmos SDK chains. To test message delivery, deploy a [Warp Route](/docs/guides/warp-routes/cosmos/cosmos-warp-route-guide) and use a [relayer](/docs/operate/relayer/run-relayer) to process transfers. ### Update Core Configuration (Day 2) Use `core read` output as your editable config for updates such as validator rotation, default ISM changes, or gas oracle updates: ```bash theme={null} hyperlane core read --chain yourchain --config ./yourchain-core.yaml # Edit ./yourchain-core.yaml hyperlane core apply --chain yourchain --config ./yourchain-core.yaml ``` Once ownership has been transferred away from the deployer, `core apply` will no longer work with the deployer key alone. Use the `--strategy` flag with a file submitter to submit transactions through the new owner (e.g. a multisig). For production hardening, see: * [Update Mailbox Default ISM](/docs/guides/production/core-deployment/update-mailbox-default-ism) * [Transfer Mailbox Ownership](/docs/guides/production/core-deployment/transfer-mailbox-ownership) **🎉 Congrats! You have successfully deployed Hyperlane core to your custom Cosmos chain** ## 3. Hyperlane Warp Route Now that you have a Hyperlane Mailbox and core components on your chain, it’s time to set up token bridging between your chain and any other Hyperlane chain. Continue with one of the following guides: * [Deploy a Cosmos Warp Route](/docs/guides/warp-routes/cosmos/cosmos-warp-route-guide) * [Deploy an EVM ↔ Cosmos HWR](/docs/guides/warp-routes/evm-cosmos-warp-route-guide) * [Deploy a Cosmos ↔ SVM HWR](/docs/guides/warp-routes/cosmos-svm-warp-route-guide) ## 4. Submit to Registry If you want other chains to connect with you as well as to take this to production, make a registry PR. ### Ensure complete info Make sure your metadata is complete: * add a `logo.svg` file inside the folder * include `Deployer` information identifying the team deploying * indicate `isTestnet` `true` if the chain is testnet * lint the YAML files and order alphabetically ### Commit to GitHub First, navigate to your local instance of the registry and commit changes ```bash theme={null} cd ~/.hyperlane && git init && git add . && git commit ``` Then, sync local registry with canonical registry ```bash theme={null} git remote add canonical git@github.com:hyperlane-xyz/hyperlane-registry.git git pull canonical main --rebase ``` Finally, push local registry to GitHub fork and submit a PR. Please include a [changeset](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md) in your PR. **🎉 Congrats! You have successfully deployed Hyperlane to your Cosmos chain and added your work to the Hyperlane registry** # Deploy Hyperlane with Local Agents Source: https://docs.hyperlane.xyz/docs/guides/chains/deploy-hyperlane-with-local-agents Advanced guide for deploying Hyperlane with local validators and relayers This guide is for advanced users who may eventually intend to run Hyperlane agents in a production-like environment. It will cover the basics of how to manually configure and run agents but **it is not a production setup guide**. ## Overview There are six steps in this guide: 1. **Set up keys** that you will use to deploy contracts and run validators and relayers 2. **Deploy contracts** to the local chain and to every remote chain with which the local chain will be able to send and receive messages 3. **Run a validator** to provide the signatures needed for the Interchain Security Modules you deployed 4. **Run a relayer** to send and receive messages between the chains you deployed contracts to 5. **Send a test message** to confirm that your relayer is able to deliver messages to and from each pair of chains 6. **Deploy a Hyperlane Warp Route (HWR)** to send token value, not just messages, across chains ## Getting Started ## 1. Set up keys Set up your keys for deploying contracts and running agents. ## 2. Deploy contracts Deploy Hyperlane contracts to your chains. ## 3. Run a validator Validators provide the security for messages sent *from* your chain to remote chains. They're only required when using a [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM). Learn more about what validators do [here](/docs/protocol/agents/validators). ### Setup directories First, generate an agent config file using the Hyperlane CLI. If you have a local registry with custom chain configurations, pass the registry path to the command: ```bash theme={null} hyperlane registry agent-config --chains --registry /path/to/your/registry ``` This will create an agent config at `./configs/agent-config.json`. Then, set the `CONFIG_FILES` environment variable to the path of the generated agent config: ```bash theme={null} export CONFIG_FILES=/full/path/to/configs/agent-config.json ``` Next, create a local directory for your validator to write its signatures to. Remember the path, as you will need this when configuring your validator. The validator signatures path will be written on-chain as part of the [validator announcement transaction](/docs/alt-vm-implementations/implementation-guide#validator-announce). **Be careful not to reveal any security-sensitive or personal information!** ```bash theme={null} # Pick an informative name specific to the chain you're validating export VALIDATOR_SIGNATURES_DIR=/tmp/hyperlane-validator-signatures- # Create the directory mkdir -p $VALIDATOR_SIGNATURES_DIR ``` You will not be able to mount anything in `/tmp` when running the agent via Docker on Mac. To counter this, create a local `tmp` directory to mount instead. ```bash theme={null} # Create a local tmp directory that can be accessed by docker mkdir tmp # Pick an informative name specific to the chain you're validating export VALIDATOR_SIGNATURES_DIR=tmp/hyperlane-validator-signatures- # Create the directory mkdir -p $VALIDATOR_SIGNATURES_DIR ``` ### Configure There are numerous parameters that validators can be configured with. For this guide, we are concerned with just a handful: | Parameter | Description | | ------------------------- | ------------------------------------------------------------------------------------------------------------- | | `--db` | Path for writing persistent data to disk. | | `--originChainName` | Name of the chain being validated (e.g. `ethereum`). | | `--checkpointSyncer.type` | Set to `localStorage` for this guide. | | `--checkpointSyncer.path` | Path to local directory where validator signatures will be written. Same path as `$VALIDATOR_SIGNATURES_DIR`. | | `--validator.key` | Your validator's hexadecimal private key. | Make sure the validator key corresponds to the address provided when setting up your MultisigIsmConfig. Otherwise, the Multisig ISM you deployed in the previous step will not be able to verify messages sent from your chain. To learn more about all the parameters you can change, read the [agent configuration reference](/docs/operate/config/config-reference). **Update agent config** Unless you are running Docker on Linux, you will also need to update the agent configuration for your network. This is because Docker does not support the [`host` network mode](https://docs.docker.com/network/drivers/host/) on Mac, Windows or Windows Server. To do this, navigate to the agent-configuration at `$CONFIG_FILES` and replace all instances of "localhost" or "127.0.0.1" in to `host.docker.internal`. For example: ```json theme={null} ... "localnet1": { ... "rpcUrls": [ { // "http": "http://localhost:8545" // "http": "http://127.0.0.1:8545" "http": "http://host.docker.internal:8545" } ], ... }, ... ``` **Mounting directories** Running with Docker adds an extra layer of complexity because config files need to be accessible from within the Docker container, and validator signatures need to be accessible from outside of the container for the relayer to read. This is so the relayer can construct the metadata required for the message to be successfully validated by the Multisig ISM. To solve this issue, you can mount directories on your file system into the container. In the arguments below, we: 1. Set the `$CONFIG_FILES` environment variable to a fixed path within the container. 2. Mount the agent config file to this fixed path and making it readonly. 3. Mount the persistent data directory at a fixed path within the container. 4. Mount the validator signatures directory to a fixed path within the container. ```bash theme={null} ... -e CONFIG_FILES=/config/agent-config.json \ --mount type=bind,source=$CONFIG_FILES,target=/config/agent-config.json,readonly \ --mount type=bind,source="$(pwd)"/hyperlane_db_validator_,target=/hyperlane_db \ --mount type=bind,source="$(pwd)"/$VALIDATOR_SIGNATURES_DIR,target=/tmp/validator-signatures \ ... ``` Hardcoding these paths deduplicates the configuration between docker instances running validators for different origin chains. This makes it easier to pass the right arguments when running the container. See the example below, where the only items to be configured differently for different chains are the chain name and validator key. ```bash theme={null} ... ./validator \ --db /hyperlane_db \ --originChainName \ --checkpointSyncer.type localStorage \ --checkpointSyncer.path /tmp/validator-signatures \ --validator.key ... ``` **Clone and setup** First, clone the Hyperlane monorepo: ```bash theme={null} git clone git@github.com:hyperlane-xyz/hyperlane-monorepo.git ``` Then follow the [setup instructions](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/README.md) in the `rust` directory. This should setup `rustup` as well as Rosetta 2 if you are on Apple Silicon. ```bash theme={null} # install rustup curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # (apple silicon only) install rosetta 2 softwareupdate --install-rosetta --agree-to-license ``` ### Run Now that you understand more about configuring validator arguments, pull the latest docker image: ```bash theme={null} docker pull --platform linux/amd64 ghcr.io/hyperlane-xyz/hyperlane-agent:agents-v2.2.0 ``` Before running, ensure that all directories you need to mount are present. This may involve creating `hyperlane_db_validator_` if it does not exist yet. ```bash theme={null} mkdir -p hyperlane_db_validator_ ``` Finally, run the validator: ```bash theme={null} docker run \ -it \ -e CONFIG_FILES=/config/agent-config.json \ --mount type=bind,source=$CONFIG_FILES,target=/config/agent-config.json,readonly \ --mount type=bind,source="$(pwd)"/hyperlane_db_validator_,target=/hyperlane_db \ --mount type=bind,source="$(pwd)"/$VALIDATOR_SIGNATURES_DIR,target=/tmp/validator-signatures \ ghcr.io/hyperlane-xyz/hyperlane-agent:agents-v2.2.0 \ ./validator \ --db /hyperlane_db \ --originChainName \ --checkpointSyncer.type localStorage \ --checkpointSyncer.path /tmp/validator-signatures \ --validator.key ``` After following the setup instructions, you should now be able to use `cargo` to run the Validator: ```bash theme={null} cargo run --release --bin validator -- \ --db ./hyperlane_db_validator_ \ --originChainName \ --checkpointSyncer.type localStorage \ --checkpointSyncer.path $VALIDATOR_SIGNATURES_DIR \ --validator.key ``` **Optional: Run the binary directly** You can alternatively build out the agent: ```bash theme={null} cargo build --release --bin validator ``` And run the binary directly: ```bash theme={null} ./target/release/validator \ --db ./hyperlane_db_validator_ \ --originChainName \ --checkpointSyncer.type localStorage \ --checkpointSyncer.path $VALIDATOR_SIGNATURES_DIR \ --validator.key ``` For further information, check out the [Validators guide](/docs/operate/validators/run-validators). To learn about running multiple validators, see [this section](/docs/operate/validators/run-validators#running-multiple-validators). ## 4. Run a relayer * **Single Relayer Recommendation**: A single relayer is generally sufficient and can handle message delivery across 100+ chains efficiently. You don't need to run separate relayers for each network - this approach actually increases operational complexity without providing performance benefits. * **Trusted Relayer ISM Key Management**: If you're using a trusted relayer ISM (which is not recommended for production), avoid using the same relayer key across multiple relayer instances as this can cause nonce conflicts and transaction failures. Either run a single relayer or use different keys for each relayer. * For production deployments, use a multisig ISM instead of trusted relayer ISM. Relayers deliver interchain messages sent between the local and remote chains. Learn more about what relayers do [here](/docs/protocol/agents/relayer). You should already have set the `CONFIG_FILES` environment variable to the path of the agent config generated in the [agent configs](#agent-configs) step. If not, do so now. ```bash theme={null} export CONFIG_FILES=/full/path/to/configs/agent-config.json ``` ### Configure There are numerous parameters that relayers can be configured with. For this guide, we are concerned with just a handful: | Parameter | Description | | ------------------------------- | ---------------------------------------------------------------------------------------- | | `--db` | Path for writing persistent data to disk. | | `--relayChains` | Comma separated names of the chains to relay between. E.g. `ethereum,polygon,avalanche`. | | `--allowLocalCheckpointSyncers` | Allows the relayer to look for validator signatures on the local filesystem. | | `--defaultSigner.key` | A hexadecimal private key used to sign transactions for all chains. | | `--metrics-port` | Optional. The port to expose prometheus metrics on, defaults to `9090`. | Your set of relay chains should include both the origin chain and the destination chain. To learn more about all the parameters you can change, read the [agent configuration reference](/docs/operate/config/config-reference). **Mounting directories** For the relayer, we provide almost the same arguments to Docker as the validator: 1. Set the `$CONFIG_FILES` environment variable to a fixed path within the container. 2. Mount the agent config file to this fixed path and making it **readonly**. 3. Mount the persistent data directory at a fixed path within the container. 4. Mount the validator signatures directory to a fixed path within the container and making it **readonly**. ```bash theme={null} ... -e CONFIG_FILES=/config/agent-config.json \ --mount type=bind,source=$CONFIG_FILES,target=/config/agent-config.json,readonly \ --mount type=bind,source="$(pwd)"/hyperlane_db_relayer,target=/hyperlane_db \ --mount type=bind,source="$(pwd)"/$VALIDATOR_SIGNATURES_DIR,target=/tmp/validator-signatures,readonly \ ... ``` Hardcoding these paths deduplicates the configuration between docker instances running relayers for different sets of chains. This makes it easier to pass the right arguments when running the container. See the example below, where the only items to be configured differently for different chains are the list of chains to relay between and the relayer key. **Clone and setup** If you haven't already done so, clone the Hyperlane monorepo and follow the [setup instructions](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/README.md) in the `rust` directory. ```bash theme={null} # clone hyperlane monorepo git clone git@github.com:hyperlane-xyz/hyperlane-monorepo.git # install rustup curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # (apple silicon only) install rosetta 2 softwareupdate --install-rosetta --agree-to-license ``` ### Run If you haven't already pulled the Docker image, do this now by running: ```bash theme={null} docker pull --platform linux/amd64 ghcr.io/hyperlane-xyz/hyperlane-agent:agents-v2.2.0 ``` Before running, ensure that all directories you need to mount are present. This may involve creating `hyperlane_db_relayer` if it does not exist yet. ```bash theme={null} mkdir -p hyperlane_db_relayer ``` Finally, run the relayer: ```bash theme={null} docker run \ -it \ -e CONFIG_FILES=/config/agent-config.json \ --mount type=bind,source=$CONFIG_FILES,target=/config/agent-config.json,readonly \ --mount type=bind,source="$(pwd)"/hyperlane_db_relayer,target=/hyperlane_db \ --mount type=bind,source="$(pwd)"/$VALIDATOR_SIGNATURES_DIR,target=/tmp/validator-signatures,readonly \ ghcr.io/hyperlane-xyz/hyperlane-agent:agents-v2.2.0 \ ./relayer \ --db /hyperlane_db \ --relayChains , \ --allowLocalCheckpointSyncers true \ --defaultSigner.key \ ``` After following the setup instructions, you should now be able to use `cargo` to run the Relayer: ```bash theme={null} cargo run --release --bin relayer -- \ --db ./hyperlane_db_relayer \ --relayChains , \ --allowLocalCheckpointSyncers true \ --defaultSigner.key \ --metrics-port 9091 ``` The metrics port is overridden to avoid clashing with the validator. **Optional: Run the binary directly** You can alternatively build out the agent: ```bash theme={null} cargo build --release --bin relayer ``` And run the binary directly: ```bash theme={null} ./target/release/relayer \ --db ./hyperlane_db_relayer \ --relayChains , \ --allowLocalCheckpointSyncers true \ --defaultSigner.key \ --metrics-port 9091 ``` For further information, check out the [Relayer guide](/docs/operate/relayer/run-relayer). ## 5. Send test messages Send test messages to verify your setup is working correctly. ## 6. (Optional) Deploy a Hyperlane Warp Route To connect tokens using your new Hyperlane deployment, see the [Hyperlane Warp Route deployment guide](/docs/guides/quickstart/deploy-warp-route). # Create your own Hook & ISM Source: https://docs.hyperlane.xyz/docs/guides/create-custom-hook-and-ism Hooks and ISMs have a complementary relationship: you can customize your behavior from origin and they use a pairwise ISM contract on the destination to verify your custom hook behavior. You can implement and utilize your own hook and ISM pattern as per your requirements. You can use an external bridge provider like Wormhole or Chainlink's CCIP by implementing the `IPostDispatchHook` interface on the source chain and `IInterchainSecurityModule` on the destination chain. ```solidity theme={null} interface IPostDispatchHook { enum Types { UNUSED, ROUTING, AGGREGATION, MERKLE_TREE, INTERCHAIN_GAS_PAYMASTER, FALLBACK_ROUTING, ID_AUTH_ISM, PAUSABLE, PROTOCOL_FEE, LAYER_ZERO_V1, RATE_LIMITED, ARB_L2_TO_L1, OP_L2_TO_L1, MAILBOX_DEFAULT_HOOK, AMOUNT_ROUTING } /** * @notice Returns an enum that represents the type of hook */ function hookType() external view returns (uint8); /** * @notice Returns whether the hook supports metadata * @param metadata metadata * @return Whether the hook supports metadata */ function supportsMetadata( bytes calldata metadata ) external view returns (bool); /** * @notice Post action after a message is dispatched via the Mailbox * @param metadata The metadata required for the hook * @param message The message passed from the Mailbox.dispatch() call */ function postDispatch( bytes calldata metadata, bytes calldata message ) external payable; /** * @notice Compute the payment required by the postDispatch call * @param metadata The metadata required for the hook * @param message The message passed from the Mailbox.dispatch() call * @return Quoted payment for the postDispatch call */ function quoteDispatch( bytes calldata metadata, bytes calldata message ) external view returns (uint256); } ``` ```solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; interface IInterchainSecurityModule { enum Types { UNUSED, ROUTING, AGGREGATION, LEGACY_MULTISIG, MERKLE_ROOT_MULTISIG, MESSAGE_ID_MULTISIG, NULL, // used with relayer carrying no metadata CCIP_READ, ARB_L2_TO_L1, WEIGHTED_MERKLE_ROOT_MULTISIG, WEIGHTED_MESSAGE_ID_MULTISIG, OP_L2_TO_L1 } /** * @notice Returns an enum that represents the type of security model * encoded by this ISM. * @dev Relayers infer how to fetch and format metadata. */ function moduleType() external view returns (uint8); /** * @notice Defines a security model responsible for verifying interchain * messages based on the provided metadata. * @param _metadata Off-chain metadata provided by a relayer, specific to * the security model encoded by the module (e.g. validator signatures) * @param _message Hyperlane encoded interchain message * @return True if the message was verified */ function verify( bytes calldata _metadata, bytes calldata _message ) external returns (bool); } interface ISpecifiesInterchainSecurityModule { function interchainSecurityModule() external view returns (IInterchainSecurityModule); } ``` Hooks currently expect metadata to be formatted with the [`StandardHookMetadata` library](/docs/reference/developer-tools/libraries/hookmetadata). You can also inherit from our `AbstractMessageIdAuthorizedIsm` which allows for access control for an intermediate `verifyMessageId` function call which sets in storage the messageId to true if received from the authorized `AbstractMessageIdAuthHook` hook. This pattern is used currently in the [`OpStackHook`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/ef2ece300e71a30e8f4f59e5b26e21eea012d43b/solidity/contracts/hooks/OPStackHook.sol#L33C8-L33C8) \<> [`OpStackIsm`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/ef2ece300e71a30e8f4f59e5b26e21eea012d43b/solidity/contracts/isms/hook/OPStackIsm.sol#L31) pattern. ## Workflow ```mermaid theme={null} flowchart TB subgraph Origin Chain Sender M_O[(Mailbox)] E_B_O[(ExternalBridgeOrigin)] C_H[AbstractMessageIdAuthorizedIsm] Sender -- "dispatch(..., metadata){value}" --> M_O M_O -. "postDispatch(metadata, ...)
{value - fee}" ..-> C_H C_H -- "externalCall(metadata, message)" --> E_B_O end E_B_O -. "crosschainCall(metadata,message)" ..-> E_B_D M_O -. "relay" ..-> M_D subgraph Destination Chain Recipient M_D[(Mailbox)] E_B_D[(ExternalBridgeDestination)] ISM{AbstractMessageIdAuthorizedIsm} M_D -- "handle(origin,sender,message)" --> Recipient M_D -- "verify(metadata, message)" --> ISM ISM -. "interchainSecurityModule()" .- Recipient E_B_D -- "verifiedMessageId(message)" --> ISM end style E_B_O fill: #FF0099 style E_B_D fill: #FF0099 ``` ## Interface After implementing the above interfaces, you can override default hook along the hook metadata by using the overloaded `dispatch` call in our mailbox. **On the source chain:** * `mailbox.dispatch()` calls your custom hook via `AbstractMessageIdAuthHook.postDispatch()`. * `_postDispatch` checks whether `latestDispatchedId` is the id being dispatched from the hook to make the mailbox is the contract calling the hook (since calling `postDispatch` isn't access controlled) * `_sendMessageId` calls your custom external bridge logic like calling the CCIP router contract. **On the destination chain:** * The external bridge will call `verifyMessageId` function (which is access-controlled) and sets the `messageId` in the `verifiedMessages` mapping to true. * On receiving the message for the relayer, the mailbox will call your ISM contract (specified in your recipient address) which checks if the messageId in the `verifiedMessages` mapping is true and returns true to the mailbox and vice versa. `AbstractMessageIdAuthorizedIsm` can send `msg.value` through `postDispatch` calls and we utilize the `verifiedMessages`' little endian 255 bits for storing the `msg.value` and the top bit for the actual receipt of the messageId delivery. Therefore, you can send up to 2^255 amount of value of the native token from origin and the destination ISM can only receive 2^255 amount of value of native token on the destination chain. ## Access Control If `postDispatch` must only be called with a `message` that was *just* dispatched, the `latestDispatchedId` function on the Mailbox can be used to verify the message was *actually* dispatched. This is used instead of some `require(mailbox == msg.sender)` to support **composition** where a hook may pass a `message` along to another hook. The following utility is provided in the [`MailboxClient` library](/docs/reference/developer-tools/libraries/mailbox-client) for convenience. # Troubleshooting Guide Source: https://docs.hyperlane.xyz/docs/guides/deploy-hyperlane-troubleshooting ## General Troubleshooting Logging levels and formats can be configured for Hyperlane tooling using the following two environment variables: * `LOG_LEVEL`: The log level to filter to. Defaults to `info`. Choices: `debug | info | warn | error | off` * `LOG_FORMAT`: The format of the log output. Defaults to `pretty`. Choices: `pretty | json` The [Hyperlane CLI](/docs/reference/developer-tools/cli) also allows configuring logging via the `--log` and `--verbosity` flags. Within your working directory, you may find a `chains/` yaml files organized by chain name. These `metadata.yaml` files describe the information needed to use the chain in Hyperlane deployments and apps. You can define a full configuration for any new chain in this file. The metadata that can be configured is defined in this [example configuration](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/typescript/cli/examples/chain-config.yaml). You can also find the chain metadata schema at [chainMetadataTypes.ts](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/typescript/sdk/src/metadata/chainMetadataTypes.ts). Here's an example configuration for two local anvil chains: ```yaml theme={null} anvil1: chainId: 31337 domainId: 31337 name: anvil1 protocol: ethereum rpcUrls: - http: http://localhost:8545 nativeToken: name: Ether symbol: ETH decimals: 18 anvil2: chainId: 31338 domainId: 31338 name: anvil2 protocol: ethereum rpcUrls: - http: http://localhost:8555 ``` You can also extend a core chain config by providing the fields to be overridden: ```yaml theme={null} sepolia: blocks: confirmations: 2 ``` You can override the RPC urls by extending the core chain config. Example: Define RPC URLs array and adjust retry settings ```yaml theme={null} demochain: name: demochain chainId: 123456 domainId: 123456 protocol: ethereum rpcUrls: - http: https://rpc-testnet.demochain.gg sepolia: rpcUrls: - http: https://rpc2.sepolia.org - http: https://some-other-sepolia-rpc.gg retry: maxRequests: 10 ``` Transaction overrides are any properties to include when forming transaction requests. For example: * `gasPrice`: number | string * `maxFeePerGas`: number | string * `maxPriorityFeePerGas`: number | string * `nonce`: number | string * `type`: number * `ccipReadEnabled`: boolean In the example below we're using a gas price of 7 gwei, hardcoding the nonce, and setting a maximum value for the base and priority fees. ```yaml theme={null} sepolia: transactionOverrides: gasPrice: 7000000000 # 7 gwei maxFeePerGas: 150000000000 # 150 gwei maxPriorityFeePerGas: 40000000000 # 40 gwei nonce: 1337 ``` If you are overriding the nonce in the chain configuration, ensure you are updating the value on successful transactions. Delays or timeouts in message delivery often result from RPC issues, such as overloaded endpoints, or from chains that produce blocks only on demand. To identify the issue, check for logs indicating RPC-related problems such as: `Deprioritizing an inner provider in FallbackProvider` To address these delays: * **Check RPC Health:** Ensure RPC endpoints are responsive. * **Configure Chains with On-Demand Blocks:** For these chains, set the reorgPeriod to 0. This ensures that agents always look at the tip of the chain, avoiding delays caused by block finalization processes. ## Agent Troubleshooting * **Reason**: This occurs when the relayer cannot retrieve validator signatures required to process a message. * **Solution**: * Ensure the validators have announced their storage locations. Check validator logs for a message such as: `Validator has announced signature storage location, locations: ["file:///tmp/hyperlane-validator-signatures-local"]` * Verify that each validator has a unique signature storage path (`--checkpointSyncer.path`) to prevent overwriting. * Confirm that the relayer has read access to the storage paths. * **Reason**: This occurs when the Interchain Security Module (ISM) does not recognize the origin chain. * **Solution**: * Ensure the ISM configuration includes the Validators for the origin chain. * If it doesn't, add validators for the origin chain to your ISM. * Restart the relayer after updating the ISM configuration. If messages are stuck in the relayer queue or not being processed, use the `list_operations` endpoint to inspect the relayer's queue: ```shell theme={null} curl http://0.0.0.0:9090/list_operations?destination_domain= ``` This endpoint provides the status of messages in the queue and can help identify why they are not being delivered. For detailed insights, enable debug logging and monitor the relayer's activity: `HYP_LOG_LEVEL=debug`. Once logs are captured, you can use them to locate issues with specific message IDs. After reviewing the logs, you can trigger an immediate retry of all pending messages using the `message_retry` endpoint: ```shell theme={null} curl --location 'http://127.0.0.1:9090/message_retry' \ --header 'Content-Type: application/json' \ --data '[{"messageid": "*", "origindomain": "*", "senderaddress": "*", "destinationdomain": "*", "recipientaddress": "*"}]' ``` Make sure that you use the most recent version of the relayer and capture all logs for debugging. Ensure the Interchain Security Module (ISM) on your chain is configured correctly. An incorrect ISM can result in messages not being processed. Verify the ISM address in your configuration and ensure it matches your deployment setup. ## Advanced Troubleshooting Some chains do not natively support the [`eth_getStorageAt()`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getstorageat) API. If you're deploying on one of these chains and encounter issues, review the changes made to the Hyperlane codebase in this [commit](https://github.com/hyperlane-xyz/hyperlane-monorepo/commit/871df7a4dce203ff5cf23ae654d03743dc00ea61). To deploy Hyperlane on these chains follow the steps: 1. Clone the [repo](https://github.com/hyperlane-xyz/hyperlane-monorepo) 2. Apply the changes in the [commit](https://github.com/hyperlane-xyz/hyperlane-monorepo/commit/871df7a4dce203ff5cf23ae654d03743dc00ea61). 3. Build the project from the root directory: `yarn build` 4. Run the Hyperlane CLI from the root directory: `yarn workspace @hyperlane-xyz/cli hyperlane` # Transfer Mailbox Ownership Source: https://docs.hyperlane.xyz/docs/guides/production/core-deployment/transfer-mailbox-ownership Learn how to change the owner of your Hyperlane Mailbox using the Hyperlane CLI This guide explains how to change the owner of your Hyperlane Mailbox using the Hyperlane CLI. Transferring ownership is necessary when you want to give control to a different address, such as for security reasons or when making changes to who manages the Mailbox. As the new owner, you will have full control over the Mailbox settings, including managing hooks, ISM configurations, and permissions for message handling. We'll guide you through updating the owner address, applying the change, and confirming everything is set correctly. ## Using the Hyperlane CLI One of the quickest way to transfer a mailbox ownership is by using the [Hyperlane CLI](https://docs.hyperlane.xyz/docs/reference/developer-tools/cli). ## Prerequisites * The core config generated by `hyperlane core init`. * This config is used to deploy core contracts, including the mailbox. By default, it takes the filepath of `CURRENT_DIR/configs/core-config.yaml`. * The chain that the mailbox was deployed to. * Access to the private key that currently owns the mailbox. If you followed the [How to Connect Your Chain with Hyperlane](/docs/guides/chains/deploy-hyperlane) guide, you may have deployed a mailbox with the owner set to the single private key. In production, it is advisable to use a multisig. To confirm using the Hyperlane CLI, execute the following with `--chain` set to the name of your chain that the mailbox is deployed on: ```bash theme={null} hyperlane core read --chain ``` After running `core read`, you should see a similar config with `owner` set to private key's address: ```yaml {8} theme={null} defaultHook: address: "0xC2E88eC0aB5FDB9756CD3EFEE40D24120fFa6E57" type: "merkleTreeHook" defaultIsm: address: "0xF37395A79f56268FD0040E1f5711e9Af974a545A" relayer: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" type: "trustedRelayerIsm" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" requiredHook: address: "0x390d29a822C21F57B163F1173cD43382bd643401" beneficiary: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" maxProtocolFee: "100000000000000000" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" protocolFee: "0" type: "protocolFee" ``` The output is saved to `CURRENT_DIR/configs/core-config.yaml`. Follow these steps using the CLI to transfer the existing ownership to another address. ## Step 1: Update Config Update `owner` address in the `core-config.yaml` ```diff core-config.yaml theme={null} defaultHook: address: "0xE71AC7A1ccB822423576EfFdb0B74564C49BEcBA" type: merkleTreeHook defaultIsm: address: "0x89842f40928f81FC4415b39bfBFC3205eB6161cB" relayer: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" type: trustedRelayerIsm - owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + owner: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" requiredHook: address: "0x390d29a822C21F57B163F1173cD43382bd643401" beneficiary: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" maxProtocolFee: "100000000000000000" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" protocolFee: "0" type: protocolFee ``` ## Step 2: Apply Using the CLI, execute: ```bash theme={null} hyperlane core apply --chain ``` You should see a batch of transactions executed on chain, and a final message indicating that the mailbox has been updated. ## Step 3: Confirm To confirm using the Hyperlane CLI, execute the following: ```bash theme={null} hyperlane core read --chain ``` After running `core read`, you should see a similar config with the now updated `owner`: ```yaml {8} theme={null} defaultHook: address: "0x67F8c06Fd2915728E9D21451E33FbDFbCcd63c44" type: "merkleTreeHook" defaultIsm: address: "0xac7D6df90fa937ADEfE7aD2d4905f0AEa170c467" relayer: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" type: "trustedRelayerIsm" owner: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" requiredHook: address: "0x1Cd94b4D9B5f0e3474a6bDB8b9503Ca84F53e548" beneficiary: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" maxProtocolFee: "100000000000000000" owner: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" protocolFee: "0" type: "protocolFee" ``` By completing these steps, you have successfully transferred and verified ownership of your mailbox to a new address. # Update Mailbox Default ISM Source: https://docs.hyperlane.xyz/docs/guides/production/core-deployment/update-mailbox-default-ism Learn how to update your mailbox default ISM using the Hyperlane CLI for production deployments ## Using the Hyperlane CLI When first deploying with the CLI, a new mailbox uses a Trusted Relayer ISM out of the box so you don't need to run a relayer or validator. In order to go to production, you'll need to remove this ISM with the Hyperlane CLI. ## Prerequisites * The core config generated by `hyperlane core init`. * This config is used to deploy core contracts, including the mailbox. By default, it takes the filepath of `CURRENT_DIR/configs/core-config.yaml`. * The chain that the mailbox was deployed to. * Access to the private key that currently owns the mailbox. If you followed the [How to Connect Your Chain with Hyperlane](/docs/guides/chains/deploy-hyperlane) guide, you may have deployed a mailbox with the owner set to the single private key. In production, it is advisable to use a multisig. To confirm using the Hyperlane CLI, execute the following with `--chain` set to the name of your chain that the mailbox is deployed on: ```bash theme={null} hyperlane core read --chain ``` After running `core read`, you should see a similar config with `owner` set to private key's address: ```yaml {4-7} theme={null} defaultHook: address: "0xC2E88eC0aB5FDB9756CD3EFEE40D24120fFa6E57" type: "merkleTreeHook" defaultIsm: address: "0xF37395A79f56268FD0040E1f5711e9Af974a545A" relayer: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" type: "trustedRelayerIsm" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" requiredHook: address: "0x390d29a822C21F57B163F1173cD43382bd643401" beneficiary: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" maxProtocolFee: "100000000000000000" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" protocolFee: "0" type: "protocolFee" ``` The output is saved to `CURRENT_DIR/configs/core-config.yaml`. This particular config has a `trustedRelayerIsm`. This means contracts (e.g., Hyperlane Warp Route) that fallback to the mailbox's `defaultIsm` will give permission to `relayer` address to execute arbitrary messages. This may be undesirable in cases outside of the self-relaying feature. Follow these steps using the CLI to update the existing default Ism to a different configuration. ## Step 1: Update Configuration Alternatively, you can update the `relayer` address to something else (e.g., "burn" it by setting it to an inaccessible address). ```diff core-config.yaml theme={null} defaultHook: address: "0xC2E88eC0aB5FDB9756CD3EFEE40D24120fFa6E57" type: merkleTreeHook defaultIsm: address: "0xF37395A79f56268FD0040E1f5711e9Af974a545A" - relayer: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" + relayer: "0x0000000000000000000000000000000000000001" type: trustedRelayerIsm owner: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" requiredHook: address: "0x4f54055C94DCbC2b502146D46909A2cC7461c5D8" beneficiary: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" maxProtocolFee: "100000000000000000" owner: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" protocolFee: "0" type: protocolFee ``` Alternatively, you can update the `defaultIsm` config to a different ISM config. As shown, it is updated to a `messageIdMultisigIsm`. Configuring ISMs is an advanced feature that require knowledge of different ISM types and how they work together topologically. ```diff core-config.yaml theme={null} defaultHook: address: "0xC2E88eC0aB5FDB9756CD3EFEE40D24120fFa6E57" type: merkleTreeHook defaultIsm: - address: "0xF37395A79f56268FD0040E1f5711e9Af974a545A" - relayer: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" - type: trustedRelayerIsm + threshold: 1 + type: messageIdMultisigIsm + validators: + - "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" owner: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" requiredHook: address: "0x4f54055C94DCbC2b502146D46909A2cC7461c5D8" beneficiary: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" maxProtocolFee: "100000000000000000" owner: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" protocolFee: "0" type: protocolFee ``` ## Step 2: Apply Using the CLI, execute: ```bash theme={null} hyperlane core apply --chain ``` You should see a batch of transactions executed on chain, and a final message indicating that the mailbox has been updated. ## Step 3: Confirm To confirm using the Hyperlane CLI, execute the following: ```bash theme={null} hyperlane core read --chain ``` After running `core read`, you should see a similar config with the now updated default ISM: ```yaml {6} theme={null} defaultHook: address: "0x67F8c06Fd2915728E9D21451E33FbDFbCcd63c44" type: "merkleTreeHook" defaultIsm: address: "0xac7D6df90fa937ADEfE7aD2d4905f0AEa170c467" relayer: "0x0000000000000000000000000000000000000001" type: "trustedRelayerIsm" owner: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" requiredHook: address: "0x1Cd94b4D9B5f0e3474a6bDB8b9503Ca84F53e548" beneficiary: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" maxProtocolFee: "100000000000000000" owner: "0xa5558cA30cd9952Ab0e2349C274a3736698bD60e" protocolFee: "0" type: "protocolFee" ``` By completing these steps, you've successfully updated the mailbox default ISM and enhanced the security of your mailbox. Your mailbox is now ready for production use. # Overview Source: https://docs.hyperlane.xyz/docs/guides/production/prod-overview To launch your Hyperlane deployment into a production environment, follow these steps to set up your chain’s core deployment and configure Hyperlane Warp Route (HWR) deployments. ### 1. Core Deployment To begin you'll need to set up and productionize the core components of your Hyperlane deployment. Update the Interchain Security Module (ISM) associated with the Mailbox contract. The ISM acts as a critical security layer, verifying messages between chains. Ensure that the default ISM settings align with your security requirements. Transfer ownership of the Mailbox contract to a production-ready owner account. This step secures the Mailbox by ensuring only trusted parties have control over its configuration. ### 2. HWR Deployment Remove any test or development relayers that may have been configured initially. In production, ensure that only trusted, secure relayers are used to prevent unauthorized message relaying. Transfer ownership of the HWR to the designated production owner. This step ensures that only trusted parties have control over critical HWR settings, such as ISM configurations, Validator options, and relayer settings. # Alt SVMs: Using Squads Source: https://docs.hyperlane.xyz/docs/guides/production/using-squads/alt-svm-using-sqauds Step-by-step guide to executing and signing a transaction in the Squads App on Alt SVMs ## UI Setup The main Squads UI doesn’t support alt SVMs. Instead use: [Squads Backup App](https://backup.app.squads.so/) ### 1. Configure for the Alt-SVM **You MUST configure it to work with the alt-SVM!** Go to **Settings** and use the following settings depending on the chain: * **RPC URL:** `https://mainnetbeta-rpc.eclipse.xyz` * **Program ID:** `eSQDSMLf3qxwHVHeTr9amVAGmZbRLY2rFdSURandt6f` * **RPC URL:** `https://rpc.mainnet.soo.network/rpc` * **Program ID:** `Hz8Zg8JYFshThnKHXSZV9XJFbyYUUKBb5NJUrxDvF8PB` * **RPC URL:** `https://api.mainnet-alpha.sonic.game/` * **Program ID:** `sqdsFBUUwbsuoLUhoWdw343Je6mvn7dGVVRYCa4wtqJ` * **RPC URL:** `https://api.mainnet-beta.solana.com` *(might need to be a private RPC URL for better performance)* * **Program ID:** `SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf` Note that these configs are saved in your browser’s storage, and while they may go away in the UI after refreshing, they do persist. svm
  squads ### 2. Import the Multisig Address For this step, the **Multisig account** is required. You can either import it directly or search for it using the **Vault address** (token owner address). svm squads ## Submit Transaction 1. You’ll receive a base58 **message** from the Abacus Works team that is required for executing step 3. 2. Go to the **Transactions** tab, and click **Import Transaction**. altvm squads 3. Copy the base58 message into the UI and click **Import**. 4. Refresh the page. You should now see the transaction. altvm squads 5. Make sure to **keep track of the index/public key of the proposed transactions** and what they do. This way, signers know exactly what they’re signing. altvm squads # Using Squads with Solana Source: https://docs.hyperlane.xyz/docs/guides/production/using-squads/using-squads-solana Step-by-step guide to executing and signing a transaction in the Squads App on Solana For Solana, the main UI that can be used: [Squads App](https://app.squads.so/) ## Steps 1. You’ll receive a base58 transaction from the Abacus Works team that is required for executing step 3. 2. Navigate to **Developers → TX Builder** in Squads, and click **Import base58 encoded tx**. svm squads 3. Copy the base58 transaction received from the Abacus Works team into the textbox. 4. Click Next, then **Add Instruction**. svm squads 5. Give it a clear name, and click **Run Simulation**. svm squads Simulation should be successful! 6. Click **Initiate Transaction** when you’re ready to submit it to the Vault. 7. You’ll be prompted for your Ledger to sign about 5 transactions via Phantom. 8. You’ll be brought to the **Transactions** view, which you may need to refresh. Now share the transaction with the other signers for them to confirm or reject. 9. You can simulate the transaction and click **See Details** to view the logs of the simulated transaction. 🎉 You should see logs indicating ownership was successfully transferred! svm squads # Remove Trusted Relayer Source: https://docs.hyperlane.xyz/docs/guides/production/warp-route-deployment/remove-trusted-relayer This guide explains how to remove the default Trusted Relayer ISM from your Hyperlane Warp Route (HWR) using the Hyperlane CLI. Removing the Trusted Relayer ISM is a crucial step when preparing your HWR for production. ## Using the Hyperlane CLI When first deploying with the CLI, new HWR use a Trusted Relayer ISM out of the box so you don't need to run a relayer or validator. In order to go to production, you'll need to remove this ISM with the [Hyperlane CLI](/docs/reference/developer-tools/cli). ## Prerequisites * The warp route ID. * After deployment, the warp route ID is saved to the registry at `$HOME/.hyperlane/deployments/warp_routes/`. * The format is `SYMBOL/id` (e.g., `ETH/yourid`). * To list existing warp route IDs: `ls $HOME/.hyperlane/deployments/warp_routes/` * Access to the private key that currently owns the HWR. If you followed the [Deploy a Warp Route](/docs/guides/quickstart/deploy-warp-route) guide, you most likely have deployed a HWR with a trusted relayer set to a signer address. To confirm using the Hyperlane CLI, identify your warp route ID: ```bash theme={null} hyperlane warp read -w ``` You can then choose the HWR for which you're removing the trusted relayer. After running `warp read`, you should see a similar config under `interchainSecurityModule` containing a `trustedRelayerIsm`: ```yaml {7-9} theme={null} yourchain: ... interchainSecurityModule: address: "0xd54d32cD6a62482497252D59E6cCC1445fF0b92d" type: "staticAggregationIsm" modules: - address: "0x50b6dA835D9b8b20523891410a2E042855B465C8" relayer: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" type: "trustedRelayerIsm" - owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" address: "0xcE512189fF1BD41186E9eDda02BF321Fb1FC6eAc" type: "defaultFallbackRoutingIsm" domains: {} threshold: 1 ``` This particular config has a `trustedRelayerIsm` as part of the `staticAggregationIsm`. This means that the `relayer` address will be allowed to call the HWR's `handle()` function. In other words, the `relayer` can execute arbitrary messages on the HWR. This may be undesirable in cases outside of the self-relaying feature. Warp route configs are stored in your local registry at `$HOME/.hyperlane/deployments/warp_routes//`. The `warp read` command outputs the current on-chain config for reference. Follow these steps using the CLI to remove the trusted relayer. ## Step 1: Configuration Update the warp route deployment config in your local registry by **removing** the `trustedRelayerIsm` block from `modules`. Alternatively, you can configure the entire `modules` block as desired. ```diff title="warp-route-deployment.yaml" theme={null} yourchain: mailbox: '0x979Ca5202784112f4738403dBec5D0F3B9daabB9' owner: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' interchainSecurityModule: address: '0xd54d32cD6a62482497252D59E6cCC1445fF0b92d' type: 'staticAggregationIsm' modules: - - address: '0x50b6dA835D9b8b20523891410a2E042855B465C8' - relayer: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' - type: trustedRelayerIsm - owner: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' address: '0xcE512189fF1BD41186E9eDda02BF321Fb1FC6eAc' type: 'defaultFallbackRoutingIsm' domains: {} threshold: 1 name: Ether symbol: ETH decimals: 18 totalSupply: 0 type: native ``` ## Step 2: Apply Using the CLI, execute: ```bash theme={null} hyperlane warp apply -w ``` You should see a batch of transactions executed on chain, and a final message indicating that the warp config has been updated. ## Step 3: Confirm To confirm that the trusted relayer was successfully removed using the Hyperlane CLI, run the following command with your token symbol and the chain it is deployed on: ```bash theme={null} hyperlane warp read -w ``` After running `warp read`, confirm that the trusted relayer ISM has been removed from your HWR (In this example, it should only contain the remaining `defaultFallbackRoutingIsm`). You should see a similar config under `interchainSecurityModule`: ```yaml {8-11} theme={null} yourchain: mailbox: "0x979Ca5202784112f4738403dBec5D0F3B9daabB9" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" interchainSecurityModule: address: "0x8af9445d8A3FbFBd1D5dF185B8a4533Ab060Cf36" type: "staticAggregationIsm" modules: - owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" address: "0xBe0232d5d45f9aD8322C2C4F84c39e64302Cd996" type: "defaultFallbackRoutingIsm" domains: {} threshold: 1 name: "Ether" symbol: "ETH" decimals: 18 totalSupply: 0 type: "native" ``` By completing these steps, you've successfully removed the trusted relayer ISM from your HWR and enhanced the security of your HWR setup. Your HWR is now ready for production use. # Transfer Ownership Source: https://docs.hyperlane.xyz/docs/guides/production/warp-route-deployment/transfer-warp-route-ownership This guide provides a step-by-step guide to transferring ownership of your Hyperlane Warp Route (HWR). It also explains the responsibilities, security considerations, and configuration options that come with owning a HWR. ## HWR Ownership Overview Before transferring ownership of your HWR, it's important to understand what this ownership entails. Ownership grants control over configuration settings, such as the Interchain Security Module (ISM), Validator options, and other parameters critical to security. Once a mailbox is set up on the chain, anyone can deploy a HWR. HWRs are commonly deployed by a few different groups - the Abacus Works team, the asset issuer, the chain team, or the application team. ### Overview of Ownership * **Responsibilities:** As the owner, you take on responsibilities that include managing security configurations, like the ISM and Validator settings, to meet your specific security and operational goals. * **Security & Autonomy**: Ownership choices often come down to security and control preferences. We strongly recommend using a multisig like a Gnosis Safe for any production setups. Teams can choose **full ownership** for complete autonomy, or **joint ownership** on the multisig to share security management. Joint ownership enables collaborative decision-making on critical updates, which can increase trust for users and developers. ### ISM, Validator, and Relayer Options When configuring or transferring a HWR, owners have flexibility in managing ISM, Validator, and Relayer settings: * **ISM Customization**: Each HWR may require a tailored ISM configuration depending on security needs. Owners can set up a custom ISM or use Hyperlane's default setup. * **Validator Options**: Ownership allows you to choose or manage your Validator set. Hyperlane can handle Validator responsibilities by default, making it optional to run your own. * **Relayer Support**: Hyperlane provides Relayer services by default, but teams can operate their own Relayers for more control over security, reliability, and costs. This customization enables teams to tailor message handling to fit specific performance, compliance, or operational requirements. ## HWR Ownership Transfer Guide ### Using the Hyperlane CLI One of the quickest way to transfer a HWR ownership is by using the [Hyperlane CLI](https://docs.hyperlane.xyz/docs/reference/developer-tools/cli). ## Prerequisites * The warp route ID. * After deployment, the warp route ID is saved to the registry at `$HOME/.hyperlane/deployments/warp_routes/`. * The format is `SYMBOL/id` (e.g., `ETH/yourid`). * To list existing warp route IDs: `ls $HOME/.hyperlane/deployments/warp_routes/` * Access to the private key that currently owns the HWR. If you followed the [Deploy a Warp Route](/docs/guides/quickstart/deploy-warp-route) guide, you may have deployed a HWR with the owner set to the single private key. In production, it is advisable to use a multisig. To confirm using the Hyperlane CLI, locate your token symbol and the chain it is deployed on: ```bash theme={null} hyperlane warp read -w ``` You should be able to select the HWR that you wish to update the ownership for. After running `warp read`, you should see a similar config with `owner` set to private key's address: ```yaml {3} theme={null} yourchain: mailbox: "0x979Ca5202784112f4738403dBec5D0F3B9daabB9" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" ... ``` Warp route configs are stored in your local registry at `$HOME/.hyperlane/deployments/warp_routes//`. The `warp read` command outputs the current on-chain config for reference. Follow these steps using the CLI to transfer the existing ownership to another address. ## Step 1: Configuration Update the `owner` address in the warp route deployment config in your local registry. ```diff title="warp-route-deployment.yaml" theme={null} yourchain: mailbox: '0x979Ca5202784112f4738403dBec5D0F3B9daabB9' - owner: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' + owner: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' IInterchainSecurityModule: address: '0xd54d32cD6a62482497252D59E6cCC1445fF0b92d' type: staticAggregationIsm modules: - owner: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' address: '0xcE512189fF1BD41186E9eDda02BF321Fb1FC6eAc' type: defaultFallbackRoutingIsm domains: {} threshold: 1 name: Ether symbol: ETH decimals: 18 totalSupply: 0 type: native ``` ## Step 2: Apply Using the CLI, execute by providing the warp route ID: ```bash theme={null} hyperlane warp apply -w ``` You should see a batch of transactions executed on chain, and a final message indicating that the warp config has been updated. ## Step 3: Confirm To confirm that the owner was successfully updated using the Hyperlane CLI, run the following command with your token symbol and the chain it is deployed on: ```bash theme={null} hyperlane warp read -w ``` After running `warp read`, you should see a similar config with the now updated `owner`: ```yaml {3} theme={null} yourchain: mailbox: "0x979Ca5202784112f4738403dBec5D0F3B9daabB9" owner: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" IInterchainSecurityModule: address: "0x8af9445d8A3FbFBd1D5dF185B8a4533Ab060Cf36" type: staticAggregationIsm modules: - owner: "0xe738d6e51aad88F6F4ce6aB8827279cffFb94876" address: "0xBe0232d5d45f9aD8322C2C4F84c39e64302Cd996" type: defaultFallbackRoutingIsm domains: {} threshold: 1 name: Ether symbol: ETH decimals: 18 totalSupply: 0 type: native ``` By completing these steps, you have successfully transferred and verified ownership of your HWR to a new address. # Bridge a Token Source: https://docs.hyperlane.xyz/docs/guides/quickstart/deploy-warp-route **This guide is for EVM-based chains.** For other environments, check out: * [SVM Hyperlane Warp Route Guide](/docs/guides/warp-routes/svm/svm-warp-route-guide) * [EVM ↔ SVM Hyperlane Warp Route Guide](/docs/guides/warp-routes/evm-svm-warp-route-guide) * [Cosmos Hyperlane Warp Route Guide](/docs/guides/warp-routes/cosmos/cosmos-warp-route-guide) * [EVM ↔ Cosmos Hyperlane Warp Route Guide](/docs/guides/warp-routes/evm-cosmos-warp-route-guide) * [Cosmos ↔ SVM Hyperlane Warp Route Guide](/docs/guides/warp-routes/cosmos-svm-warp-route-guide) This section provides a step-by-step walkthrough for creating an interchain token bridge by deploying Hyperlane Warp Route (HWR) contracts. ## Prerequisites * [Hyperlane CLI](/docs/reference/developer-tools/cli) * A private key for contract transaction signing ## 1. Configuration ### HWR deployment config To deploy the route, you will need a HWR deployment config file. A valid config will specify: * Which token, on which chain, is this HWR being created for? * *Optional:* Hyperlane connection details, such as contract addresses for the [Mailbox](/docs/reference/addresses/deployments/mailbox), [Interchain Gas](/docs/reference/hooks/interchain-gas), and [Interchain Security Modules](/docs/protocol/ISM/modular-security#core-concepts). * *Optional:* Token standard, including ERC20 (fungible tokens), ERC721 (NFTs), and ERC4626 (yield-bearing tokens). Note ERC721 support is experimental and some Hyperlane tooling won't work for NFTs yet. The easiest way to create a HWR deployment config file is with the CLI's config command: ``` hyperlane warp init ``` This command provides a walkthrough, prompting you for configuration choices directly in the terminal. You will be asked to select specific options for each part of the configuration, such as the network type, chains to connect, token type, and whether to use trusted ISMs. * If your config looks correct, you can now skip to [Step 2: Deployment](#2-deployment). Or see below for details on how to define your config manually. * If you need any help setting up a token bridge, reach out on [GitHub Discussions](https://github.com/hyperlane-xyz/hyperlane-monorepo/discussions) or [get in touch](https://forms.gle/KyRTaWvo4XNmNvrq6). #### Deployment config schema Your config consists of a map of chain names to deployment configs. Each config sets details about the token for which you are creating a HWR. * **type**: * Set this to `collateral` to create a basic HWR for an ERC20/ERC721 token * Set this to `collateralVault` to create a yield-bearing HWR for an ERC20 token that deposits into an existing ERC4626 vault * Set this to `native` to create a HWR for a native token (e.g. ether) * **address:** * If using `collateral`, the address of the ERC20/ERC721 contract for which to create a route * If using `collateralVault`, the address of the existing ERC4626 vault to deposit collateral into * **isNft:** If using `collateral` for an ERC721 contract, set to `true`. #### Optional fields[​](#optional-fields "Direct link to Optional fields") You may specify the following optional values in your config entries. If no values are provided, the deployer will attempt to pull these values from elsewhere. In the case of metadata (symbol, name decimals), it will query the contract. For addresses (mailbox, ISM) it will check the registry, either yours (if provided) or the [default](/docs/reference/registries#default-registry). * **symbol:** The token symbol * **name:** The token name * **decimals:** The number of decimal places for the token * **mailbox:** The address of the [mailbox](/docs/reference/addresses/deployments/mailbox) contract to use to send and receive messages * **interchainSecurityModule:** The address of an [interchain security modules](/docs/protocol/ISM/modular-security#core-concepts) to verify interchain messages #### Example[​](#example "Direct link to Example") For a minimal Warp deployment config example using local anvil chains, see [`warp-route-deployment.yaml`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/typescript/cli/examples/warp-route-deployment.yaml). * Learn more about HWR types and the different configurations in the following sections: * [HWR Types](/docs/protocol/warp-routes/warp-routes-types) * [HWR Example Usage](/docs/protocol/warp-routes/warp-routes-example-usage) ### Chain Configurations The deployment will require basic information about any chains it will be interacting with. If the target chains are not already in the [Hyperlane Registry](https://github.com/hyperlane-xyz/hyperlane-registry), you must specify chain metadata for them. See the [CLI reference](/docs/reference/developer-tools/cli) for details. To see what chains are in the currently known, run the following command: ``` hyperlane registry list ``` To create a chain metadata config for any other chains, run the following command: ``` hyperlane registry init ``` Or you can define the config manually. See the [ChainMetadata type](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/typescript/sdk/src/metadata/chainMetadataTypes.ts#L62) for its schema. See [chain-config.yaml](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/typescript/cli/examples/chain-config.yaml) for an example. Where possible, be sure to **reuse any existing chains** from the registry/CLI in your HWR config instead of setting up a new mailbox. ## 2. Deploy the HWR Once your configuration is ready, initiate the HWR deployment with: ``` hyperlane warp deploy ``` During deployment, the CLI requires access to your private key to sign transactions. You can set this up in one of two ways: 1. **Environment Variable**: Set your private key as HYP\_KEY to avoid entering it each time: ``` export HYP_KEY= ``` 2. **Manual Entry**: Alternatively, you can enter the private key directly when prompted during deployment. The `hyperlane warp deploy` command will create deployment artifacts in your local registry at `$HOME/.hyperlane/deployments/warp_routes//`. The warp route ID follows the format `SYMBOL/id` (e.g., `ETH/yourid`). This ID is used with CLI commands like `warp read`, `warp send`, and `warp apply`. Warp route configs are stored in the registry. To modify a warp route config, edit the files in `$HOME/.hyperlane/deployments/warp_routes//` and then run `hyperlane warp apply`. ### Testing You can initiate a test transfer of a single wei with the following command: ``` hyperlane warp send --relay -w TOKEN/chain1-chain2 ``` The `--relay` flag is optional and will relay the message to the destination chain. `--relay` only works when both origin and destination are EVM chains. For non-EVM routes, see the [CLI Warp Send reference](/docs/reference/developer-tools/cli#warp-send). You can also run a relayer that delivers only for your HWR in the background with: ``` hyperlane relayer -w TOKEN/chain1-chain2 ``` You can test in either direction between where you have the HWR set. However, if you deployed `native` or `collateral` HWR, you must select the origin where the route corresponding to where that `native` or `collateral` type is deployed. By default, the amount sent is `1` of the smallest unit of the token. You can also use just the symbol (e.g., `-w ETH`) and the CLI will auto-select if there's only one matching route, or prompt you to choose if multiple exist. **Next Steps** * If you were following the [Deploy Hyperlane to a new chain](/docs/guides/chains/deploy-hyperlane#3-hyperlane-warp-route) guide and want to connect other chains or move to production with Abacus Works, continue with the [Submit to Registry](/docs/guides/chains/deploy-hyperlane#4-submit-to-registry) guide. * For interacting with HWRs via a UI, continue to the [Warp UI docs](/docs/guides/warp-routes/bridge-ui-guide). ## Learn More * Check out the [HWR](docs/applications/warp-routes/overview) reference page for more information on the interface and security implications of a HWR. The [interface](docs/applications/warp-routes/overview#interface) section covers calling `transferRemote` to transfer tokens to a specified recipient on a destination chain. Note that you'll have to prompt for a token approval prior to calling `transferRemote`. * A HWR is a type of [router](/docs/reference/developer-tools/libraries/router) application, a pattern enabling you to link multiple contracts across chains together. # Local Setup: Sending Messages between Anvil Nodes Source: https://docs.hyperlane.xyz/docs/guides/quickstart/local-testnet-setup This guide walks you through sending interchain messages between two local Anvil nodes using the Hyperlane CLI. ## Prerequisites[​](#prerequisites "Direct link to Prerequisites") * **[Hyperlane CLI](https://docs.hyperlane.xyz/docs/reference/developer-tools/cli):** Make sure you have the latest version of the Hyperlane CLI installed. ``` npm install -g @hyperlane-xyz/cli ``` * **[Anvil (foundry)](https://book.getfoundry.sh/getting-started/installation):** Installed to run local chains. Install it via ``` curl -L https://foundry.paradigm.xyz | bash ``` * **Node.js** (v18 or later) * **Deployer Wallet Private Key**: You need a funded wallet for deploying contracts. This will be used as the HYP\_KEY. ``` export HYP_KEY= ``` ## Step-by-Step Guide[​](#step-by-step-guide "Direct link to Step-by-Step Guide") ### 1. Environment Setup Create a working directory for the Hyperlane configuration:[​](#1-environment-setup-create-a-working-directory-for-the-hyperlane-configuration "Direct link to 1. Environment Setup: Create a working directory for the Hyperlane configuration:") ``` mkdir hyperlane-local-test && cd hyperlane-local-test ``` ### 2. Start Two Distinct Anvil Nodes[​](#2-start-two-distinct-anvil-nodes "Direct link to 2. Start Two Distinct Anvil Nodes") We will run two Anvil nodes with unique chain IDs. * On a first terminal, start the first Anvil node: ``` anvil --port 8545 --chain-id 31337 --block-time 1 ``` * Runs on `http://localhost:8545`. * Chain ID: `31337`. * In a new terminal, start the second Anvil node: ``` anvil --port 8546 --chain-id 31338 --block-time 1 ``` * Runs on `http://localhost:8546`. * Chain ID: `31338`. ### 3. Initialize the Hyperlane Registry[​](#3-initialize-the-hyperlane-registry "Direct link to 3. Initialize the Hyperlane Registry") On a new terminal, use the Hyperlane CLI to create configurations for both Anvil nodes: ``` hyperlane registry init ``` Follow the prompts to set up `anvilnode1`. The CLI will ask you for the details of your chains including chainId and RPC URLs. Repeat the process for `anvilnode2`. This process will create `metadata.yaml` files under `$HOME/.hyperlane/chains/anvilnode1` and `$HOME/.hyperlane/chains/anvilnode2`. Example metadata: * **anvilnode1** ``` chainId: 31337displayName: Anvilnode1domainId: 31337isTestnet: truename: anvilnode1nativeToken: decimals: 18 name: ETH symbol: ETHprotocol: ethereumrpcUrls: - http: http://localhost:8545 ``` * **anvilnode2** ``` chainId: 31338displayName: Anvilnode2domainId: 31338isTestnet: truename: anvilnode2nativeToken: decimals: 18 name: ETH symbol: ETHprotocol: ethereumrpcUrls: - http: http://localhost:8546 ``` ### 4. Deploy Core Contracts[​](#4-deploy-core-contracts "Direct link to 4. Deploy Core Contracts") We'll configure and deploy Hyperlane core contracts. You'll need the deployer wallet private key to deploy the core contracts. You can use `export HYP_KEY=''` to set the private key as an environment variable. ``` hyperlane core init ``` The deployment configuration will be saved to `./configs/core-config.yaml`. Next, deploy the core contracts: ``` hyperlane core deploy ``` Follow the prompts to select `anvilnode1`. The CLI will deploy Mailbox, Interchain Security Modules (ISMs), and other required contracts. Repeat the process for `anvilnode2`. Once complete, you’ll find `addresses.yaml` in `$HOME/.hyperlane/chains/anvilnode1` and `$HOME/.hyperlane/chains/anvilnode2`, with the deployed contract addresses. You should be able to see the messages of the contract deployments on your terminals running the local nodes. ### 5. Send a Test Message[​](#5-send-a-test-message "Direct link to 5. Send a Test Message") Use the Hyperlane CLI to send a message from `anvilnode1` to `anvilnode2`. ``` hyperlane send message --relay ``` The CLI will prompt you to provide the origin chain (`anvilnode1`) and the destination chain (`anvilnode2`). For local testing, the `--relay` flag automatically relays the message to the destination chain. After sending the message, check the following: * Validator Logs: Look for entries indicating that signatures were generated and stored. * Relayer Logs: Look for successful metadata retrieval and message processing. * Anvil Logs: Ensure blocks were mined to process the transactions. 🎉 You've sent a message between two local Anvil nodes using Hyperlane! ## Troubleshooting[​](#troubleshooting "Direct link to Troubleshooting") 1. “Could not fetch metadata” warning: * **Reason:** This occurs when the relayer cannot retrieve validator signatures required to process a message. Common causes: * The validator key lacks testnet funds. * The validator has not announced its storage locations. * **Solution:** * Ensure the validators have announced their storage locations. Check validator logs for a message such as: `Validator has announced signature storage location, locations: ["file:///tmp/hyperlane-validator-signatures-local"].` * Verify that each validator has a unique signature storage path (`--checkpointSyncer.path`) to prevent overwriting. * Confirm that the relayer has read access to the storage paths. 2. Messages time out: * **Reason:** Anvil doesn't auto-mine blocks by default, causing validators or relayers to wait indefinitely for new blocks. * **Solution:** Make sure to use the `--block-time 1 flag` when starting Anvil to auto-mine blocks every second. 3. Validator mismatch or misconfiguration: * **Reason:** The ISM configuration on the destination chain does not match the validator key(s) used by the origin chain. * **Solution:** Check that the ISM configuration includes the correct validator addresses. Validator logs can help identify the announced addresses. # Deploying a Bridge UI for your HWR Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/bridge-ui-guide After you've successfully [deployed a Hyperlane Warp Route (HWR)](/docs/guides/quickstart/deploy-warp-route), you have three out-of-the-box options for setting up a frontend UI to support interchain token transfers: 1. **[Fork, customize, and deploy the Hyperlane Warp UI template](#fork--customize-the-ui)** 2. **[Use a managed Superbridge instance](#superbridge)** 3. **[Embed the bridge widget in your existing site](/docs/guides/warp-routes/embed-widget)** — drop a React component or iframe into your app ## 1. Hyperlane Warp UI Template The [Hyperlane Warp UI template](https://github.com/hyperlane-xyz/hyperlane-warp-ui-template) is a prebuilt Next.JS app you can easily customize and deploy. * **Configuration**: Follow the [configuration instructions](https://github.com/hyperlane-xyz/hyperlane-warp-ui-template/blob/main/README.md) for details on how to configure the Warp UI Web application and run it locally. * **Customization**: Follow the [customization instructions](https://github.com/hyperlane-xyz/hyperlane-warp-ui-template/blob/main/CUSTOMIZE.md) for details on how to configure the UI's tokens and change the default branding assets/theme. ### Registry By default, the app will use the canonical Hyperlane registry published on NPM. To use a different registry, you can set a URL using the `NEXT_PUBLIC_REGISTRY_URL` environment variable. ### HWR Config Example Here's an example config for a HWR that connects USDC on Sepolia to Alfajores. You can use Typescript or YAML for your route configs. ```typescript theme={null} { tokens: [ { // The ChainName of the token chainName: "sepolia", // See https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/typescript/sdk/src/token/TokenStandard.ts standard: TokenStandard.EvmHypCollateral, // The token metadata (decimals, symbol, name) decimals: 6, symbol: "USDC", name: "USD Coin", // The router address addressOrDenom: "YOUR_ROUTER_ADDRESS_1", // The address of the underlying collateral token collateralAddress: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", // A path to a token logo image logoURI: "/logos/usdc.png", // The list of tokens this one is connected to connections: [{ token: "ethereum|alfajores|YOUR_ROUTER_ADDRESS_2" }], }, { chainName: "alfajores", standard: TokenStandard.EvmHypSynthetic, decimals: 6, symbol: "USDC", name: "USD Coin", addressOrDenom: "YOUR_ROUTER_ADDRESS_2", logoURI: "/logos/usdc.png", connections: [{ token: "ethereum|alfajores|YOUR_ROUTER_ADDRESS_2" }], }, ]; } ``` #### Chain Config Example Chain metadata can also be configured as needed. These are the same configs as those used with the CLI for any of its deploy or send command (for example, those from the [deploy guide](/docs/guides/chains/deploy-hyperlane)). ```typescript theme={null} { anvil1: { chainId: 31337, name: 'anvil1', displayName: 'Anvil 1 Local', nativeToken: { name: 'Ether', symbol: 'ETH', decimals: 18 }, publicRpcUrls: [{ http: 'http://127.0.0.1:8545' }], blocks: { confirmations: 1, reorgPeriod: 0, estimateBlockTime: 10, }, logoURI: '/logo.svg' } } ``` ### Deploy the UI Since the UI is a Next.js app, you can use your favorite hosting service to host it. We recommend [Vercel](https://vercel.com), which works well with Next. [AWS Amplify](https://aws.amazon.com/amplify) is another popular option. 1. Sign up for [Vercel](https://vercel.com/) 2. Create a new project and connect it to your GitHub repo 3. Hit Deploy! And that's it! Now you and your users can use the UI to send tokens from the collateral chain to remote chains, from one remote chain to another, and from any remote chain back to the collateral chain. If there is no production relayer running for these chains, you can run a lightweight CLI relayer that delivers only for your HWR in the background with: ```bash theme={null} hyperlane relayer -w TOKEN/chain1-chain2 ``` This will allow you to test the warp UI locally or for a quick demo without needing to run a full production relayer in the cloud. ### Return gas A common problem with token bridges like HWRs is that a user may transfer a token like USDC to a new chain, but only afterwards realize that they do not have the native gas token to move those tokens anywhere including back. To improve the user experience, you could provide some native gas tokens via a faucet, in addition to UI warnings. To create a faucet, modify the HWR contracts to hold a balance of the native token to share with recipients. For developers looking to further customize the Warp UI for their own projects or build their own interchain applications, we encourage you to explore the Typescript SDK. The SDK contains a growing set of an utilities and abstractions for interacting with Hyperlane across different protocols (EVM, Cosmos, Solana). ## 2. Superbridge [Superbridge](https://superbridge.app) is a custom bridge provider, they manage bridge frontends for hundreds of rollups, various tokens and different ecosystems. Getting a managed Superbridge for your HWR is a hassle-free approach to operating your bridge. A few of their most popular Hyperlane powered bridges are [Renzo's ezETH bridge](https://renzo.superbridge.app) and [Elixir's deUSD bridge](https://elixir.superbridge.app). With a managed bridge instance, Superbridge will handle hosting, theming, upgrades & user support requests for your HWR. They've also built a handy feature that allows for self-service testing of recently deployed HWRs. ### Testing your HWR 1. Navigate to the [Superbridge Hyperlane Playground](https://hyperlane.superbridge.app) 2. Click the settings cog and then click Customize 3. Paste in the YAML file you generated when deploying your HWRs 4. The specified tokens and networks will now be available for bridging. If any tokens or networks are missing after you've pasted in the YAML file, it's possible Superbridge doesn't support Hyperlane on this network just yet. [Reach out](mailto:support@superbridge.app) to Superbridge to see what the timeline is for adding support. ### Bridging Widget In addition to the hosted UI, Superbridge offers a bridging widget, so you can embed your bridge in your own site. Checkout their [Widget Demos](https://widget-demos.superbridge.app/) site for an overview of all the configuration options available. ### Go to Production To bring your HWR to production with Superbridge, [reach out to the Superbridge team](mailto:alex@superbridge.app). They can typically get a frontend up and running in about a day. # Deploy a Cosmos ↔ SVM HWR Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/cosmos-svm-warp-route-guide Deploy a Hyperlane Warp Route between a Cosmos SDK chain and an SVM chain This guide walks you through deploying a Hyperlane Warp Route (HWR) between a Cosmos SDK chain and an SVM chain (Solana, Eclipse). It combines the Hyperlane TypeScript CLI for the Cosmos side with the Sealevel Rust CLI for the SVM side, linked via the `foreignDeployment` field. ## Prerequisites * [Hyperlane CLI](/docs/reference/developer-tools/cli) (TypeScript CLI for Cosmos deployment) * Rust (latest stable version) and [Solana CLI tools](https://docs.solanalabs.com/cli/install) (`3.0.14` for deployment) * A funded wallet on the SVM chain (Solana keypair) * A funded wallet on the Cosmos chain (hex private key) * If your Cosmos wallet uses a mnemonic, derive/export the raw hex private key first (64 hex chars, optional `0x` prefix). * Hyperlane core deployed on both chains: * For SVM, see the prerequisites in [Deploy an SVM HWR](/docs/guides/warp-routes/svm/svm-warp-route-guide) * For Cosmos, see [Deploy to a Cosmos Chain](/docs/guides/chains/deploy-hyperlane-cosmos) ## Overview Since the SVM and Cosmos chains use different deployment tooling, the workflow is: 1. **Deploy the Cosmos side** using the Hyperlane TypeScript CLI (`hyperlane warp deploy`) 2. **Deploy the SVM side** using the Sealevel Rust CLI, referencing the Cosmos deployment via `foreignDeployment` 3. **Update the Cosmos side** using `hyperlane warp apply` so the Cosmos router enrolls the SVM router ## Walkthrough ### Step 1: Deploy on the Cosmos Side Create a Warp Route config for the Cosmos chain. Since we are deploying the Cosmos side first, only the Cosmos chain entry is required. ```yaml theme={null} # cosmos-warp-config.yaml yourcosmoschain: type: collateral token: uatom # Native denom on the Cosmos chain owner: "cosmos1..." # Bech32 owner address mailbox: "0x..." # Hex32 Mailbox address from core deployment name: "Cosmos Hub" symbol: "ATOM" decimals: 6 ``` Set your Cosmos private key and (optionally) preselect a Warp Route ID for deterministic artifact filenames: ```bash theme={null} export HYP_KEY_COSMOSNATIVE='' export WARP_ROUTE_ID='ATOM/yourcosmoschain' hyperlane warp deploy --warpRouteId "$WARP_ROUTE_ID" --config ./cosmos-warp-config.yaml ``` The CLI will output deployment artifacts to `~/.hyperlane/deployments/warp_routes/`. If you omit `--warpRouteId`, use the ID shown in deploy output (usually `SYMBOL/label`, e.g. `ATOM/yourcosmoschain`) for later steps. ```bash theme={null} # Verify the deployment hyperlane warp read --warpRouteId "$WARP_ROUTE_ID" ``` ### Step 2: Deploy on the SVM Side Follow the [SVM HWR guide](/docs/guides/warp-routes/svm/svm-warp-route-guide) for building programs and preparing your environment. Create a `token-config.json` for the SVM side, referencing the Cosmos deployment via `foreignDeployment`: ```json theme={null} { "solanamainnet": { "type": "synthetic", "decimals": 6, "name": "Cosmos Hub", "symbol": "ATOM", "uri": "", "interchainGasPaymaster": "" }, "yourcosmoschain": { "type": "collateral", "decimals": 6, "token": "uatom", "foreignDeployment": "" } } ``` The `interchainGasPaymaster` value is the overhead IGP address from your SVM chain's [core deployment artifacts](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/rust/sealevel/environments/mainnet3) at `/core/program-ids.json`. Deploy from the Sealevel client directory: ```bash theme={null} # From rust/sealevel/client cargo run -- -k ./warp-route-deployer-key.json warp-route deploy \ --warp-route-name atom \ --environment mainnet3 \ --environments-dir ../environments \ --built-so-dir ../target/deploy \ --token-config-file ../environments/mainnet3/warp-routes/atom/token-config.json \ --registry ~/path/to/your/local/hyperlane-registry \ --ata-payer-funding-amount 50000000 ``` The SVM deployment writes program IDs under `rust/sealevel/environments/mainnet3/warp-routes/atom/program-ids.json`. You will need the SVM warp route program ID for the next step. ### Step 3: Update Cosmos-Side Router Enrollment Create an apply config that includes the SVM chain as a `foreignDeployment`: ```yaml theme={null} # cosmos-warp-apply.yaml yourcosmoschain: type: collateral token: uatom owner: "cosmos1..." mailbox: "0x..." # Hex32 Mailbox address name: "Cosmos Hub" symbol: "ATOM" decimals: 6 solanamainnet: type: synthetic owner: "" foreignDeployment: "" ``` Because `--config` is a local deploy-config file, also pass the matching warp core config via `--warp`: ```bash theme={null} cp ~/.hyperlane/deployments/warp_routes/"$WARP_ROUTE_ID"-config.yaml ./cosmos-warp-core.yaml hyperlane warp apply \ --warpRouteId "$WARP_ROUTE_ID" \ --config ./cosmos-warp-apply.yaml \ --warp ./cosmos-warp-core.yaml ``` ### Step 4: Verify Both Sides **SVM side:** ```bash theme={null} # From rust/sealevel/client cargo run -- -k ./warp-route-deployer-key.json \ -u token query \ --program-id synthetic ``` **Cosmos side:** ```bash theme={null} hyperlane warp read --warpRouteId "$WARP_ROUTE_ID" ``` ### Step 5: Test a Transfer `hyperlane warp send` does not currently support Cosmos SDK or SVM chains. To test your cross-chain warp route, run a [relayer](/docs/operate/relayer/run-relayer) between your chains and initiate a transfer from the SVM side using the Sealevel CLI, or from the Cosmos side using native transaction tooling. For Cosmos-initiated transfers, submit `/hyperlane.warp.v1.MsgRemoteTransfer` using your chain's native `tx` tooling, and quote fees beforehand with `QueryQuoteRemoteTransfer` (`hyperlane.warp.v1.Query/QuoteRemoteTransfer`). To transfer from SVM to Cosmos: ```bash theme={null} # From rust/sealevel/client cargo run -- -u \ -k ./warp-route-deployer-key.json \ token transfer-remote ./warp-route-deployer-key.json \ \ synthetic --program-id ``` The recipient address must be a `0x`-prefixed 32-byte hex value (64 hex chars), not bech32. When converting from bech32, use a converter that outputs the Hyperlane recipient format (left-padded `bytes32`). The relayer handles conversion back to a bech32 account on the destination chain. ## Important Considerations ### Decimals Cosmos tokens typically use 6 decimals, which is compatible with SVM's standard precision. If bridging a token with different decimals on each side, use the `remoteDecimals` field in the SVM config (see the [EVM ↔ SVM guide](/docs/guides/warp-routes/evm-svm-warp-route-guide) for an example). ### Address Formats * **SVM**: Base58-encoded public keys (e.g., `D6k6T3G74ij6atCtBiWBs5TbFa1hFVcrFUSGZHuV7q3Z`) * **Cosmos**: Bech32 addresses (e.g., `cosmos1...`) The `foreignDeployment` field in the SVM `token-config.json` should use the Cosmos warp route address in Hex32 format (`0x`-prefixed 32-byte value), not bech32. ### Router Enrollment This route is fully bidirectional only after both sides enroll each other: * The SVM deploy step enrolls the Cosmos router on the SVM side. * The `warp apply` step enrolls the SVM router on the Cosmos side. ### Key Management * **SVM side**: Uses a Solana keypair file (JSON format) * **Cosmos side**: Uses a hex private key via `HYP_KEY_COSMOSNATIVE` or `--key.cosmosnative` For production deployments, transfer ownership to a multisig setup — [Squads](https://squads.so/) for SVM or a Cosmos-native multisig for the Cosmos side. ## Related Guides * [Deploy an SVM HWR](/docs/guides/warp-routes/svm/svm-warp-route-guide) * [Deploy a Cosmos HWR](/docs/guides/warp-routes/cosmos/cosmos-warp-route-guide) * [Deploy to a Cosmos Chain](/docs/guides/chains/deploy-hyperlane-cosmos) * [Deploy an EVM ↔ SVM HWR](/docs/guides/warp-routes/evm-svm-warp-route-guide) * [Deploy an EVM ↔ Cosmos HWR](/docs/guides/warp-routes/evm-cosmos-warp-route-guide) # Deploy a Cosmos HWR Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/cosmos/cosmos-warp-route-guide Deploy a Hyperlane Warp Route between Cosmos SDK chains with the Hyperlane CLI ## Outcomes You will be deploying a Hyperlane Warp Route (HWR) for an asset of your choice between Cosmos SDK chains, provided there is an existing Hyperlane core deployment. **Looking for cross-VM guides?** This guide focuses on Cosmos-native deployments. For cross-chain setups, see: * [EVM ↔ Cosmos Warp Route Guide](/docs/guides/warp-routes/evm-cosmos-warp-route-guide) * [Cosmos ↔ SVM Warp Route Guide](/docs/guides/warp-routes/cosmos-svm-warp-route-guide) ## HWR Types The type of token used determines the HWR type. In Cosmos, tokens are identified by their **denominations (denoms)** rather than contract addresses. * [Collateral](/docs/protocol/warp-routes/warp-routes-types#collateral-backed-erc20-hwr): Handles the transfer of existing tokens by locking them on the source chain. This can be a native denom (e.g., `uatom`, `uhyp`) or an IBC denom (e.g., `ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2`). * [Synthetic](/docs/protocol/warp-routes/warp-routes-types#synthetic-erc20-hwr): Handles synthetic tokens that are minted and burned as transfers occur. The Hyperlane CLI deploys a new token representation on the destination chain. ### Common Setup: Collateral to Synthetic The most common pattern is **Collateral to Synthetic**. You lock an existing token (Collateral) on its origin chain to mint a new representation (Synthetic) on the destination chain. When transferring back, the Synthetic token is burned and the Collateral is unlocked. ## Before You Start * **Hyperlane Core**: Ensure Hyperlane core components are deployed on your target chains. If not, follow the [Deploy Hyperlane to Cosmos](/docs/guides/chains/deploy-hyperlane-cosmos) guide. * **Deployer Wallet**: You need a private key for a wallet funded with native tokens on all participating chains to pay for deployment and transaction fees. * If your wallet is mnemonic-based, derive/export the raw hex private key first (64 hex chars, optional `0x` prefix). * **Hyperlane CLI**: Install the [Hyperlane CLI](/docs/reference/developer-tools/cli). ## Walkthrough: Deploy a Cosmos HWR ### Step 1: Create Warp Deployment Config Create a YAML file (e.g., `warp-route-deployment.yaml`) to define your Warp Route. This config maps chain names to their respective token settings. ```yaml theme={null} # Replace chain names, addresses, and token details with your own values. # Each chain uses its own bech32 prefix for addresses. hyp1: type: collateral token: uhyp owner: "hyp1jq304cthpx0lwhpqzrdjrcza559ukyy3sc4dw5" mailbox: "0x..." # Your chain's Mailbox address (Hex32 format) name: Hyperlane Token symbol: HYP decimals: 6 hyp2: type: synthetic owner: "hyp2..." # Owner address on the destination chain mailbox: "0x..." # Destination chain's Mailbox address (Hex32 format) name: Hyperlane Token symbol: HYP decimals: 6 ``` #### Config Schema | Field | Description | | :------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | | `type` | `collateral` (lock existing) or `synthetic` (mint new). | | `token` | The token denomination (e.g., `uhyp`, `uatom`, or an `ibc/` path). Required for `collateral`. | | `owner` | The Bech32 address that will own the Warp Route components. | | `mailbox` | The address of the Mailbox. | | `name` | The display name of the token. | | `symbol` | The token symbol. | | `decimals` | The number of decimal places (usually `6` for Cosmos SDK tokens). | | `interchainSecurityModule` | (Optional) Address of a custom ISM. Omit to use the default ISM configured in the destination Mailbox. | | `gas` | (Optional) Compute unit ceiling for message delivery on the destination chain. Start conservative (e.g., `300000`) and increase if messages run out of gas. | ### Step 2: Deploy the Warp Route Run the deployment command using the Hyperlane CLI. The CLI will prompt you for the private key for each chain if it's not provided via environment variables. ```bash theme={null} hyperlane warp deploy --config ./warp-route-deployment.yaml ``` You can also set your private key as an environment variable to skip prompts: `export HYP_KEY_COSMOSNATIVE=` For mixed EVM ↔ Cosmos routes, also set `HYP_KEY` for the EVM side. Upon success, the CLI will output the deployment artifacts to `~/.hyperlane/deployments/warp_routes/`. ### Step 3: Verify the Deployment You can verify the state of your deployed Warp Route by reading its configuration from the chains. ```bash theme={null} export WARP_ROUTE_ID='' hyperlane warp read --warpRouteId "$WARP_ROUTE_ID" ``` Use the Warp Route ID shown in deploy output. For a config with exactly one synthetic chain, the default ID is usually `SYMBOL/` (for the example above, `HYP/hyp2`). ### Step 4: Transfer Ownership for Production (Recommended) Many teams deploy first with a hot deployer key, then transfer ownership to a multisig after verification. 1. Update `owner` fields in your `warp-route-deployment.yaml` to your production owner addresses. 2. Use the generated core config and re-apply: ```bash theme={null} cp ~/.hyperlane/deployments/warp_routes/"$WARP_ROUTE_ID"-config.yaml ./warp-route-core.yaml hyperlane warp apply \ --warpRouteId "$WARP_ROUTE_ID" \ --config ./warp-route-deployment.yaml \ --warp ./warp-route-core.yaml ``` When `--config` points to a local deploy config file, you must also pass the matching core config with `--warp`. ### Step 5: Test a Transfer `hyperlane warp send` does not currently support Cosmos SDK chains. To test your route: * Run a [relayer](/docs/operate/relayer/run-relayer) between your chains. * From Cosmos, submit a warp module transfer transaction using `/hyperlane.warp.v1.MsgRemoteTransfer` (via your chain's native `tx` tooling). * Before sending, quote the required gas payment using `QueryQuoteRemoteTransfer` (`hyperlane.warp.v1.Query/QuoteRemoteTransfer`). * Or run a local bridge UI using the [Hyperlane Warp UI template](https://github.com/hyperlane-xyz/hyperlane-warp-ui-template) (see [Bridge UI Guide](/docs/guides/warp-routes/bridge-ui-guide)). You can verify the warp route is correctly registered on both chains: ```bash theme={null} hyperlane warp read --warpRouteId "$WARP_ROUTE_ID" ``` ## Production Handoff If you want your route to be discoverable by others: * Open a PR to [hyperlane-registry](https://github.com/hyperlane-xyz/hyperlane-registry) with your deploy/config artifacts. * Add `logoURI` on all route tokens and `coinGeckoId` on collateral/native entries when applicable. * If you want listing in Hyperlane-hosted bridge surfaces (such as Nexus), contact the Hyperlane team after your registry PR is merged. # Embedding the Bridge Widget Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/embed-widget Embed Hyperlane's bridge widget in your app using the @hyperlane-xyz/warp-widget SDK or a plain iframe You can add Hyperlane bridging directly into your site so users never have to leave your app. The [`@hyperlane-xyz/warp-widget`](https://www.npmjs.com/package/@hyperlane-xyz/warp-widget) SDK handles iframe creation, theming, and event listening. ## Install ```bash theme={null} pnpm add @hyperlane-xyz/warp-widget # or npm install @hyperlane-xyz/warp-widget # or yarn add @hyperlane-xyz/warp-widget ``` ## React ```tsx theme={null} import { HyperlaneWarpWidget } from '@hyperlane-xyz/warp-widget/react'; function BridgePage() { return ( console.log('Widget event:', event)} width="420px" height="600px" /> ); } ``` | Prop | Type | Default | Description | | ----------- | ------------------ | ----------- | --------------------------- | | `config` | `WarpWidgetConfig` | `undefined` | Theme, defaults, and routes | | `onEvent` | `(event) => void` | `undefined` | Event callback | | `width` | `string` | `'100%'` | Iframe width | | `height` | `string` | `'600px'` | Iframe height | | `className` | `string` | `undefined` | CSS class for the container | | `style` | `CSSProperties` | `undefined` | Inline styles | ## Vanilla JS Works with Vue, Angular, Svelte, or plain HTML — anything that can give you a DOM element. ```ts theme={null} import { createWarpWidget } from '@hyperlane-xyz/warp-widget'; const container = document.getElementById('widget-root'); if (!container) throw new Error('Missing #widget-root element'); const widget = createWarpWidget({ container, config: { theme: { accent: '3b82f6', mode: 'dark' }, defaults: { origin: 'ethereum', destination: 'base' }, }, }); widget.on('ready', (payload) => { console.log('Widget ready at', payload?.timestamp); }); // When you're done: widget.destroy(); ``` | Option | Type | Default | Description | | ----------- | ------------------ | ----------- | --------------------------- | | `container` | `HTMLElement` | required | DOM element to mount into | | `config` | `WarpWidgetConfig` | `undefined` | Theme, defaults, and routes | | `width` | `string` | `'100%'` | Iframe width | | `height` | `string` | `'600px'` | Iframe height | Returns `{ iframe, destroy, on }` — `iframe` is the raw `HTMLIFrameElement`, `destroy()` removes it and cleans up listeners, `on(event, callback)` subscribes to events and returns an unsubscribe function. ## Theme Colors Control the widget's look by passing a `theme` object. All color values are hex strings **without the `#` prefix**. ```ts theme={null} config: { theme: { accent: '3b82f6', bg: '0f172a', card: '1e293b', text: 'e2e8f0', buttonText: 'ffffff', border: '334155', error: 'ef4444', mode: 'dark', }, } ``` | Property | Description | Default | | ------------ | --------------------------------------------- | ----------- | | `accent` | Primary color for buttons, headers, and links | `9a0dff` | | `bg` | Page background | transparent | | `card` | Card and surface backgrounds | `ffffff` | | `text` | Main text color | `010101` | | `buttonText` | Text color inside buttons | `ffffff` | | `border` | Border color | `bfbfbf40` | | `error` | Error state color | `dc2626` | | `mode` | `'dark'` or `'light'` — sets preset defaults | `light` | Setting `mode: 'dark'` applies a full dark color scheme. You can still override individual colors on top — for example, `mode: 'dark'` with `accent: '22c55e'` gives a dark widget with green accents. ## Transfer Defaults Pre-fill the transfer form so users land on a ready-to-go state instead of picking chains and tokens themselves. ```ts theme={null} config: { defaults: { origin: 'ethereum', destination: 'arbitrum', originToken: 'USDC', destinationToken: 'USDC', }, } ``` | Property | Description | | ------------------ | ------------------------------------------ | | `origin` | Origin chain name (e.g. `'ethereum'`) | | `destination` | Destination chain name (e.g. `'arbitrum'`) | | `originToken` | Origin token symbol (e.g. `'USDC'`) | | `destinationToken` | Destination token symbol | ## Route Filtering By default the widget shows all routes from the Hyperlane registry. To limit which routes your users see, pass their IDs: ```ts theme={null} config: { routes: ['ETH/viction', 'USDC/eclipsemainnet'], } ``` Route IDs are derived from the [Hyperlane Registry deployments](https://github.com/hyperlane-xyz/hyperlane-registry/tree/main/deployments/warp_routes) — the folder name is the symbol and the config file name is the route identifier. For example, `deployments/warp_routes/USDC/eclipsemainnet-config.yaml` becomes `USDC/eclipsemainnet`. Only specified routes will appear in the token selector. ## Events The widget sends events to your app. Use `onEvent` in React or `widget.on()` in vanilla JS. | Event | Payload | Description | | ------- | --------------- | -------------------------------- | | `ready` | `{ timestamp }` | Fires when the widget has loaded | ## Self-Hosting The widget points to the Hyperlane-hosted Warp UI by default. If you [fork and deploy the Warp UI template](https://github.com/hyperlane-xyz/hyperlane-warp-ui-template) yourself, the `/embed` route is included automatically. To restrict which sites can embed your instance, set the `NEXT_PUBLIC_EMBED_ALLOWED_ORIGINS` environment variable: ```text theme={null} NEXT_PUBLIC_EMBED_ALLOWED_ORIGINS=https://app-a.com https://app-b.com ``` If not set, any site can embed the widget (default: `*`). Set this in production to prevent unauthorized sites from embedding your instance. ## Alternative: No-Code Embed If you can't install npm packages (e.g. WordPress, Shopify, Webflow), you can embed the widget with a plain iframe: ```html theme={null} ``` All [theme properties](#theme-colors) work as URL params, plus `origin`, `destination`, `originToken`, `destinationToken`, and `routes` (comma-separated). ## Troubleshooting ### Widget doesn't load Your site's Content Security Policy might be blocking the iframe. Add the Warp UI origin to your CSP `frame-src`: ```text theme={null} Content-Security-Policy: frame-src https://nexus.hyperlane.xyz; ``` ### Wallet popups don't open The iframe needs `allow-popups` in its sandbox for wallet extensions like MetaMask. The SDK sets this automatically — if using a raw iframe, make sure your `sandbox` attribute includes it. ## Examples Working examples in the [hyperlane-monorepo](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/typescript/warp-widget/examples): * **`vanilla/`** — Single HTML file, no build tools. Open in a browser. * **`react-app/`** — Vite + React app showing both the React component and imperative API. ```bash theme={null} cd typescript/warp-widget/examples/react-app pnpm install pnpm dev ``` # Deploy an EVM ↔ Cosmos HWR Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/evm-cosmos-warp-route-guide Deploy a Hyperlane Warp Route between an EVM chain and a Cosmos SDK chain This guide walks you through deploying a Hyperlane Warp Route (HWR) between an EVM-based chain and a Cosmos SDK chain using the Hyperlane CLI. ## Prerequisites Before you begin, ensure you have: * [Hyperlane CLI](/docs/reference/developer-tools/cli) installed. * Funded wallets on both the EVM and Cosmos chains. * Cosmos signer keys must be raw hex private keys (64 hex chars, optional `0x`). If you use mnemonics, derive/export the hex key first. * Hyperlane core components (Mailbox, etc.) already deployed on both chains. * For Cosmos, see [Deploy to a Cosmos Chain](/docs/guides/chains/deploy-hyperlane-cosmos). * For EVM, see [Deploy Hyperlane](/docs/guides/chains/deploy-hyperlane). ## Walkthrough ### Step 1: Create the Warp Route Config Create a YAML file (e.g., `warp-route-config.yaml`) that defines the token and connection details for both chains. ```yaml theme={null} ethereum: type: collateral token: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" # USDC on Ethereum mailbox: "0xc005dc82818d67AF737725bD4bf75435d065D239" owner: "0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba" interchainSecurityModule: "0x0000000000000000000000000000000000000000" # Zero address = use the default ISM configured in the destination Mailbox gas: 300000 # Set a ceiling for expected Cosmos-side compute units yourcosmoschain: type: synthetic mailbox: "0x..." # Hex32 Mailbox address owner: "hyp1owneraddress..." # Bech32 address name: "USD Coin" symbol: "USDC" decimals: 6 # foreignDeployment: "hyp1..." # Use if the Cosmos HWR is already deployed ``` #### Key Fields * **`type`**: Use `collateral` for the chain where the original token exists, and `synthetic` for the chain where the new token will be minted. * **`token`**: On EVM, this is the ERC20 contract address. On Cosmos, if using `collateral`, this would be the native denom (e.g., `uatom`). * **`foreignDeployment`**: This field is used to link to an existing Warp Route deployment on the remote chain. If you have already deployed the Cosmos side, provide its address here to enroll it in the EVM deployment. * **`interchainSecurityModule`**: Set to `0x0000000000000000000000000000000000000000` to use the default ISM configured in the destination Mailbox. * **`gas`**: In the EVM config, `gas` sets the Cosmos-side compute unit ceiling for message delivery. Start conservative and increase if messages run out of gas. ### Step 2: Deploy the Warp Route Run the deployment command using the Hyperlane CLI: ```bash theme={null} hyperlane warp deploy --config ./warp-route-config.yaml ``` The CLI will prompt you for the private keys for each chain. **Private key format:** Both EVM and Cosmos keys should be provided in **hex format** (64 characters, with or without `0x` prefix). The CLI handles bech32 derivation for Cosmos automatically. To avoid prompts, set both env vars before running deploy: ```bash theme={null} export HYP_KEY= export HYP_KEY_COSMOSNATIVE= ``` You can also pass protocol-specific flags directly (`--key` for EVM and `--key.cosmosnative` for Cosmos). ### Step 3: Verify the Deployment After the deployment completes, you can verify the state of your Warp Route on both sides: ```bash theme={null} export WARP_ROUTE_ID='' hyperlane warp read --warpRouteId "$WARP_ROUTE_ID" ``` Use the Warp Route ID shown in deploy output. For a config with exactly one synthetic chain, the default ID is usually `SYMBOL/` (for this example, typically `USDC/yourcosmoschain`). This will output the current configuration and addresses for the route. ### Step 4: Transfer Ownership for Production (Recommended) If you deployed with hot deployer keys, update the route owners and re-apply before production: 1. Update `owner` fields in `warp-route-config.yaml` to your production owner addresses. 2. Re-apply with the generated core config: ```bash theme={null} cp ~/.hyperlane/deployments/warp_routes/"$WARP_ROUTE_ID"-config.yaml ./warp-route-core.yaml hyperlane warp apply \ --warpRouteId "$WARP_ROUTE_ID" \ --config ./warp-route-config.yaml \ --warp ./warp-route-core.yaml ``` When `--config` points to a local deploy config file, you must also pass the matching core config with `--warp`. ### Step 5: Test a Transfer `hyperlane warp send` does not currently support Cosmos SDK chains. To test your route: * Run a [relayer](/docs/operate/relayer/run-relayer) between both chains. * Initiate transfers from EVM using the deployed HypERC20 contract. * From Cosmos, submit `/hyperlane.warp.v1.MsgRemoteTransfer` with your chain's native `tx` tooling. * Before Cosmos-side transfer submission, quote required gas payment via `QueryQuoteRemoteTransfer` (`hyperlane.warp.v1.Query/QuoteRemoteTransfer`). * Optionally use the [Hyperlane Warp UI template](https://github.com/hyperlane-xyz/hyperlane-warp-ui-template) for manual end-to-end testing (see [Bridge UI Guide](/docs/guides/warp-routes/bridge-ui-guide)). Verify the warp route is correctly registered on both sides: ```bash theme={null} hyperlane warp read --warpRouteId "$WARP_ROUTE_ID" ``` ## Production Handoff For ecosystem discoverability: * Open a PR to [hyperlane-registry](https://github.com/hyperlane-xyz/hyperlane-registry) with your route artifacts. * Add `logoURI` on route tokens and `coinGeckoId` where applicable. * If you want listing in Hyperlane-hosted bridge surfaces (such as Nexus), contact the Hyperlane team after your registry PR is merged. ## Important Considerations ### Address Formats EVM chains use hex addresses (starting with `0x`), while Cosmos chains use bech32 addresses (e.g., `cosmos1...`). The Hyperlane CLI handles the conversion between these formats automatically when interacting with the different protocols. ### Gas and Fees When sending a message from EVM to Cosmos, you must specify a sufficient `gas` limit in your config. This represents the compute units on the Cosmos side. Set this as a ceiling based on expected execution and raise it if delivery fails due to out-of-gas. Ensure your EVM wallet has enough native tokens to pay for the interchain gas fees. ## Related Guides * [Deploy to a New Chain (EVM)](/docs/guides/chains/deploy-hyperlane) * [Deploy to a Cosmos Chain](/docs/guides/chains/deploy-hyperlane-cosmos) * [Deploy a Cosmos HWR](/docs/guides/warp-routes/cosmos/cosmos-warp-route-guide) * [Deploy a Cosmos ↔ SVM HWR](/docs/guides/warp-routes/cosmos-svm-warp-route-guide) * [Bridge a Token (EVM)](/docs/guides/quickstart/deploy-warp-route) # Deploy an EVM ↔ SVM HWR Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/evm-svm-warp-route-guide ## Prerequisites Ensure you have the following installed and configured: * [Hyperlane CLI](/docs/reference/developer-tools/cli) * Rust (latest stable version) * Yarn and Node.js (latest stable version) * Solana CLI tools (`3.0.14`) ## Walkthrough ### Step 1: Create the HWR Directory 1. In `./rust/sealevel/environments/${environment}`, create a directory called `warp-routes` 2. Inside `warp-routes`, create a new directory for your HWR deployment, e.g. `environments/mainnet3/warp-routes/pzeth` 3. **Optional:** If you want to, open a PR to the `hyperlane-registry` with metadata to associate with the synthetic token in the HWR. Example [here](https://github.com/hyperlane-xyz/hyperlane-registry/pull/142). * **Tip:** Although not critical, for the `image` field try to pick a source that is unlikely to break the URL ### Step 2: Deploy on the SVM Side 4. From here on, to deploy on the SVM side you can also follow our official guide for tips: [Deploy SVM HWR](/docs/guides/warp-routes/svm/svm-warp-route-guide) 5. Create `token-config.json` for the SVM configuration, e.g. ```bash theme={null} { "solana": { "type": "synthetic", "decimals": 9, "name": "Renzo Restaked LST", "symbol": "pzETH", "uri": "", "interchainGasPaymaster": "5FG1TUuhXGKdMbbH8uHEnUghazD4aVfEPAgKLNGNx3SL", "remoteDecimals": 18 } } ``` * Often EVM tokens have 18 decimals, which are too large for the SVM. The pattern is to bridge them into SOL as 9 decimals. This can be done using `remoteDecimals: 18`. 6. Run the deployment command: ```bash theme={null} cargo run -- -k ~/solana-mainnet-deployer-keypair.json warp-route deploy \ --warp-route-name pzeth \ --environment mainnet3 \ --environments-dir ../environments \ --built-so-dir ../target/deploy \ --token-config-file ../environments/mainnet3/warp-routes/pzeth/token-config.json \ --registry ~/path/to/your/local/hyperlane-registry \ --ata-payer-funding-amount 50000000 ``` ### Step 3: Deploy on the Ethereum Side 7. Deploy the Ethereum HWR contract, which will also enroll the SVM router based on the yaml token config. 1. Ensure you have latest version of the [Hyperlane CLI](/docs/reference/developer-tools/cli). 2. Create a HWR deployment config file with the CLI's config command: `hyperlane warp init ` The command provides a walkthrough, prompting you for configuration choices directly in the terminal. Use the following steps for your HWR configuration. You can input during the walkthrough or directly in the generated YAML config file. * Manually set `foreignDeployment: ` for the SVM chain, as shown in the config example below. * Set `interchainSecurityModule: "0x0000000000000000000000000000000000000000"` to use the default ISM set in the destination chain Mailbox * Set the `gas` to a ceiling of the compute units you expect the SVM message delivery transaction to take. For instance, HWRs have gas set to `300`. It's important for this to be an upper limit - the relayer will not deliver HWR transfer messages otherwise, because senders would pay an insufficient amount to have them delivered. ```json theme={null} ethereum: interchainSecurityModule: "0x0000000000000000000000000000000000000000" isNft: false mailbox: "0xc005dc82818d67AF737725bD4bf75435d065D239" owner: "0xa7ECcdb9Be08178f896c26b7BbD8C3D4E844d9Ba" token: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" type: collateral gas: 300000 eclipsemainnet: foreignDeployment: "D6k6T3G74ij6atCtBiWBs5TbFa1hFVcrFUSGZHuV7q3Z" mailbox: "EitxJuv2iBjsg2d7jVy2LDC1e2zBrx4GB5Y9h2Ko3A9Y" owner: "9bRSUPjfS3xS6n5EfkJzHFTRDa4AHLda8BU2pP4HoWnf" interchainSecurityModule: "0x0000000000000000000000000000000000000000" type: synthetic gas: 300000 ``` 3. Deploy using the Hyperlane CLI: `hyperlane warp deploy ` 4. Confirm the deployment: ```bash theme={null} $ cast call 0x1D622da2ce4C4D9D4B0611718cb3BcDcAd008DD4 'routers(uint32)(bytes32)' $DESTINATION_DOMAIN --rpc-url $(rpc ethereum) 1399811149 0xe9792265ec273ffc17731af890d3e9963e9d744e7b99f02491911ce1bb75b8cb ``` ### Step 4: Update the SVM token-config.json 8. Back to Solana tooling now, update the `token-config.json` with the foreign deployment: * The fields for `ethereum` should be set to values from the HWR contract artifact. * `token` should be set to `collateralAddressOrDenom` (the address of the token being bridge) * `foreignDeployment` should be set to `addressOrDenom` (the address of the HWR contract, like `HypERC20Collateral`). ```bash theme={null} { "solana": { "type": "synthetic", "decimals": 9, "name": "Renzo Restaked LST", "symbol": "pzETH", "uri": "", "interchainGasPaymaster": "5FG1TUuhXGKdMbbH8uHEnUghazD4aVfEPAgKLNGNx3SL", "remoteDecimals": 18 }, "ethereum": { "type": "collateral", "decimals": 18, "token": "0x8c9532a60e0e7c6bbd2b2c1303f63ace1c3e9811", "foreignDeployment": "0x1D622da2ce4C4D9D4B0611718cb3BcDcAd008DD4" } } ``` ### Step 5: Deployment 9. Run the final deployment command: ```bash theme={null} cargo run -- -k ~/solana-mainnet-deployer-keypair.json warp-route deploy \ --warp-route-name pzeth \ --environment mainnet3 \ --environments-dir ../environments \ --built-so-dir ../target/deploy \ --token-config-file ../environments/mainnet3/warp-routes/pzeth/token-config.json \ --registry ~/path/to/your/local/hyperlane-registry \ --ata-payer-funding-amount 50000000 ``` # Deploy HWR 2.0 Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/evm/deploy-multi-collateral-warp-routes This guide walks you through how to use Hyperlane Warp Routes 2.0 to create multi-collateral token bridges, allowing assets to be sourced from multiple chains instead of a single origin. * For a primer on Hyperlane Warp Routes 2.0 head over to: [Hyperlane Warp Routes 2.0](/docs/applications/warp-routes/multi-collateral-warp-routes) ## Prerequisites To complete this walkthrough, you should have the following: 1. Two collateral chains and one synthetic chain of your choice, between which you’d like to deploy the Hyperlane Warp Route 2.0. Make sure to have some funds on the chains to cover deployment gas fees. 2. The token(s) to be used as collateral. 3. An installed instance of the [Hyperlane CLI](https://docs.hyperlane.xyz/docs/reference/developer-tools/cli) and a wallet private key set as the `HYP_KEY` env var funded on your origin and destination networks. ## Deploy your Hyperlane Warp Route 2.0 ### 1. Create your Hyperlane Warp Route Config 1. Use the Hyperlane CLI to initialize a Hyperlane Warp Route deployment file: `hyperlane warp init` This command provides a walkthrough, prompting you for configuration choices directly in the terminal. Here's how your setup should look like: * Select three networks: choose `collateral` for the two source networks, and `synthetic` for the destination network. * Input the token address, proxy admin contracts and select if you'd like to use a trusted ISMs. Once you've made the selection, the CLI will generate a Hyperlane Warp Route config file at `./configs/warp-route-deployment.yaml`. ### 2. Deploy your Hyperlane Warp Routes 2.0 Once your configuration is ready, you can initiate the Hyperlane Warp Route deployment with: `hyperlane warp deploy` During deployment, the CLI requires access to your private key to sign transactions. You can enter it when prompted or set your private key as `HYP_KEY`. Make sure that your wallet has sufficient funds on all relevant chains to cover the gas costs for the deployment. ### 3. Testing You can initiate a test transfer with the following command: `hyperlane warp send -w TOKEN/chain1-chain2` The CLI will prompt you to: * Select a matching Hyperlane Warp Route * Choose the origin and destination chains When sending between two `collateral` chains, make sure there’s sufficient collateral available on the destination chain to complete the transfer. Synthetic tokens are minted on the destination. In collateral routes, tokens must already exist on the destination chain in order to be released. It’ll run checks and send the message. You’ll get: * A transaction link (e.g., BaseScan) * A message ID and explorer link * Confirmation once processed 🎉 **Congrats!** You have successfully deployed a Hyperlane Warp Route 2.0. Your users can now bridge assets from multiple chains! 👉 Next steps: [Deploy a Bridge UI for Hyperlane Warp Routes](/docs/guides/warp-routes/bridge-ui-guide) # Deploy Yield Routes Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/evm/deploy-yield-routes The goal of this guide is to illustrate how you can use Hyperlane Warp Routes (HWR) to create yield-generating bridges, ensuring idle bridged assets are productive by compounding yield over time. Depending on the variant (more details below), yields are distributed to the yield route owner or users. ## Pre-Requisites To complete the following walkthrough, you should have the following available: 1. An origin and destination network of choice, between which you’d like to deploy the yield route. 2. The address of an [ERC-4626 vault](https://ethereum.org/en/developers/docs/standards/tokens/erc-4626/) on the origin network from which you want yield to be generated. This vault’s underlying asset will be set as the collateral for the HWR (e.g. if vault is USDC funded, the HWR will also support USDC transfer). 3. An installed instance of the [Hyperlane CLI](https://docs.hyperlane.xyz/docs/reference/developer-tools/cli) and a wallet private key set as the `HYP_KEY` env var funded on your origin and destination networks. ## Walkthrough ### Concepts * **ERC-4626 Vault**: The Ethereum standard for tokenized yield-bearing vaults. Upon deposit, share tokens are minted representing ownership of the underlying asset. * **Yield Route (EvmHypOwnerCollateral & EvmHypSynthetic)**: The Hyperlane representation of a yield-bearing EVM collateral token. Note that the yield route’s vault’s deposited asset address is used as the HWRs collateral token. * This specific yield route variant distributes vault yields to the **owner**. There is an alternative setup where yields are distributed to the users (EvmHypCollateral & EvmHypSyntheticRebase). For most of this guide, we will refer to the former variants. The concepts remain the same. For the sake of this walkthrough, the “origin” network will refer to the network on which the yield is generated (e.g. Ethereum has a USDC lending vault that has claimable yield. A synthetic USDC is minted on the destination chain called yourchain). Below is the bridging flow between Ethereum and yourchain **Bridge USDC: Ethereum → yourchain** ```mermaid theme={null} flowchart LR A[Ethereum:
Alice] -->|Deposit USDC| B[yourchain:
EvmHypOwnerCollateral] B -->|USDC Deposit into Vault| C[Ethereum:
ERC-4626 Vault] C -->|Yield Generation| C B ==>|Bridge| E[yourchain:
EvmHypSynthetic] E -->|Mint Synthetic USDC| F[yourchain:
Alice] C[Ethereum:
ERC-4626 Vault] -->|Withdraw Yield| G[Ethereum:
Vault Owner] ``` In this example, Alice wants to bridge USDC between Ethereum and yourchain. The yield route will transfer her USDC to a yield-bearing ERC-4626 vault, and then mint her synthetic USDC on yourchain. Notice that the yield route owner can claim yields generated from that vault. **Bridge USDC: yourchain → Ethereum** ```mermaid theme={null} flowchart LR A[yourchain:
Alice] -->|Burn Synthetic USDC| B[yourchain:
EvmHypSynthetic] B ==>|Bridge| C[Ethereum:
EvmHypOwnerCollateral] D[Ethereum:
ERC-4626 Vault] -->|USDC Withdraw from Vault| C C -->|Withdraw USDC| F[Ethereum:
Alice] ``` When Alice wants to bridge back to Ethereum, the reverse happens. The yield route will burn her synthetic USDC, withdraw the USDC from the vault on Ethereum, and return her USDC. ### Yield Route Deployment Steps Using the Hyperlane CLI, deploy a USDC EvmHypOwnerCollateral and EvmHypSynthetic tokens on Ethereum and yourchain, respectively: #### 1. Run `hyperlane warp init` to generate a HWR config: 1. Select `yourchain` and `Ethereum` using space, and hit enter. 2. For Ethereum, select `collateralVault`, accept the mailbox, and enter the USDC vault address on yourchain. * Alternatively, you can select `collateralVaultRebase` which is a yield route variant that distribute yields to users by increasing their holding amount. 3. For yourchain, select `synthetic` and accept the mailbox. * If you selected `collateralVaultRebase`, you must pair it with a `syntheticRebase` #### 2. Run `hyperlane warp deploy` to deploy the HWR. ### Claiming Yield Depending on the yield route variant, yield can be claimed by either calling `HypERC4626OwnerCollateral.sweep()` or `HypERC4626Collateral.rebase()` on their respective contracts. 🎉 Congrats! You have now created a new yield route with your vault. Bridged user assets can now earn passive yield while present in the origin HWR. Please note that this collateralization strategy takes on certain ISM trust assumptions, and there is inherent risk that the underlying [ERC-4626 vault](https://ethereum.org/en/developers/docs/standards/tokens/erc-4626/) becomes under-collateralized. ## Resources For more in-depth details on these steps, follow the [Bridge a Token](/docs/guides/quickstart/deploy-warp-route) guide. Check out some additional information, published by the Hyperlane supporting team, Cheese Chain, and the Ethereum Foundation: * [Hyperlane: Introducing Yield Routes](https://medium.com/hyperlane/introducing-yield-routes-f7e8fd091443) * [ERC-4626 Tokenized Vault Standard](https://ethereum.org/en/developers/docs/standards/tokens/erc-4626/) # Extending an Hyperlane Warp Route Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/evm/extending-warp-routes # Using the Hyperlane CLI After deploying your Hyperlane Warp Route (HWR), you may want to extend it to a new chain. Extending a HWR involves deploying a new token contract on the target chain and enrolling existing tokens with it. You can extend an existing HWR using the [Hyperlane CLI](https://docs.hyperlane.xyz/docs/reference/developer-tools/cli). Gnosis Safe Users: The EOA that owns the HWR must either be a Safe signer or [delegate](https://docs.safe.global/core-api/transaction-service-guides/delegates) to be able to propose update transactions. If you already have the warp config, skip to [Step 1](#step-1-configuration). To generate the HWR config using the Hyperlane CLI, locate your token symbol on the chain on which it is deployed: You can then choose the HWR to extend. After running `hyperlane warp read`, the CLI will display a config similar to the following: ```yaml theme={null} basesepolia: mailbox: "0x6966b0E55883d49BFB24539356a2f8A673E02039" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" name: "Ether" symbol: "ETH" decimals: 18 totalSupply: "1" remoteRouters: "11155111": "0x8A73F6E36735d8C4b9A00Af910746173050B754E" type: "synthetic" sepolia: mailbox: "0xfFAEF09B3cd11D9b20d1a19bECca54EEC2884766" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" name: "Ether" symbol: "ETH" decimals: 18 totalSupply: 0 remoteRouters: "84532": "0x26243aaD2d03AAbafaCE785808Ae64fc32aFB8A1" type: "native" ``` This particular config has 2 chains: basesepolia and sepolia. This means messages can be relayed between both chains. Warp route configs are stored in your local registry at `$HOME/.hyperlane/deployments/warp_routes//`. The `warp read` command outputs the current on-chain config, which you can use as a reference when making updates. ## Step 1: Configuration Edit the warp route deployment config in your local registry (e.g., `$HOME/.hyperlane/deployments/warp_routes/ETH/sepolia-basesepolia/warp-route-deployment.yaml`) to add a new chain. ```diff title="warp-route-deployment.yaml" theme={null} sepolia: mailbox: "0xfFAEF09B3cd11D9b20d1a19bECca54EEC2884766" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" name: "Ether" symbol: "ETH" decimals: 18 totalSupply: 0 remoteRouters: "84532": "0x26243aaD2d03AAbafaCE785808Ae64fc32aFB8A1" type: "native" basesepolia: mailbox: "0x6966b0E55883d49BFB24539356a2f8A673E02039" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" name: "Ether" symbol: "ETH" decimals: 18 totalSupply: "1" remoteRouters: "11155111": "0x8A73F6E36735d8C4b9A00Af910746173050B754E" type: "synthetic" + holesky: + mailbox: "0x46f7C5D896bbeC89bE1B19e4485e59b4Be49e9Cc" + owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + name: "Ether" + symbol: "ETH" + decimals: 18 + totalSupply: "1" + type: "synthetic" ``` EOA Users: The extended config `owner` must match the EOA address from the prerequisites step to avoid deployment failure. ## Step 2: Apply Using the CLI, execute the command applicable to your HWR owner setup: Use this template to define and save a Gnosis Safe strategy: `yaml basesepolia: submitter: type: "gnosisSafe" chain: "basesepolia" safeAddress: "0x518489F9ed41Fc35BCD23407C484F31897067ff0" sepolia: submitter: type: "gnosisSafe" chain: "sepolia" safeAddress: "0x518489F9ed41Fc35BCD23407C484F31897067ff0" holesky: submitter: type: "gnosisSafe" chain: "holesky" safeAddress: "0x1f9090aaE28b8a3dCeaDf281B0F12828e676c326" ` In this case, each chain is a Gnosis Safe strategy with their respective Safe addresses. The Safe proposals **must be accepted** to complete the HWR extension. After executing, you should see a batch of transactions executed on chain, and a final message indicating that the warp config has been updated. ## Step 3: Confirm To confirm that the HWR was successfully extended using the Hyperlane CLI, run the following command with your token symbol on the chain it is deployed on: After running `warp read`, confirm that the HWR has been extended: ```yaml {23-34} theme={null} basesepolia: mailbox: "0x6966b0E55883d49BFB24539356a2f8A673E02039" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" name: "Ether" symbol: "ETH" decimals: 18 totalSupply: 0 remoteRouters: "17000": "0x9B18AfD7aB869C6B011F44638ff71786447B785B" "11155111": "0x4e63147e72d029Eb8b37F375B3837B2644622686" type: native sepolia: mailbox: "0xfFAEF09B3cd11D9b20d1a19bECca54EEC2884766" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" name: "Ether" symbol: "ETH" decimals: 18 totalSupply: "0" remoteRouters: "17000": "0x9B18AfD7aB869C6B011F44638ff71786447B785B" "84532": "0xB38cc797Ccc6D8763439a07CEa052AF253281de6" type: "synthetic" holesky: mailbox: "0x46f7C5D896bbeC89bE1B19e4485e59b4Be49e9Cc" owner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" name: "Ether" symbol: "ETH" decimals: 18 totalSupply: "0" remoteRouters: "84532": "0xB38cc797Ccc6D8763439a07CEa052AF253281de6" "11155111": "0x4e63147e72d029Eb8b37F375B3837B2644622686" type: "synthetic" ``` # Fast Native Transfers via Custom Gas Tokens Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/evm/fast-native-transfer-via-gas-token This document will walk you through how to use Hyperlane to enable fast native transfers to and from your L2 via a custom gas token. ## Primary Motives 1. Create a custom gas token to use on your L2 of choice. 2. Use this gas token to enable fast native transfers, instead of long wait times for settlement via canonical bridges. ## Pre-Requisites To complete the following walkthrough, you should have the following available: 1. A L2 network (”yourchain”) on which you are able to specify a [custom gas token](https://docs.arbitrum.io/launch-orbit-chain/how-tos/use-a-custom-gas-token) and would like to enable fast native transfers to and from. 2. A sole deployer or authorized owner to receive mint of the receipt token (more information on this token below). 3. An installed instance of the [Hyperlane CLI](https://docs.hyperlane.xyz/docs/reference/developer-tools/cli) and a wallet private key sourced as `HYP_KEY`, funded on all relevant networks. ## Walkthrough: Fast Native Transfers * Note that a “receipt token” below is a (one-time) mintable “dummy” token used to collateralize a warp-route on yourchain's corresponding L1. You will burn the minting rights to the token after creating it. - Also, depending on your L2, the token symbol of your custom gas token may be assigned the same symbol as your receipt token. If deploying on ethereum, you may want to set your symbol to `ETH`. ### 1. Deploy a Receipt Token Deploy an `ETH` receipt token to ethereum to become your L2's custom gas token. 1. For example, you may deploy your receipt token via [Remix](https://remix.ethereum.org/) with a funded wallet and a contract similar to below: ```solidity theme={null} // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract YourchainETH is ERC20 { constructor() ERC20("YourchainETH", "ETH") { _mint(msg.sender, 10000000 * (10 ** 18)); } } ``` 2. Ensure 100% of the total supply of your `ETH` receipt token is minted to the deployer or authorized address of choice. This must be a one-time mint event in order to avoid value dilution of the ethereum ↔ yourchain native HWR, below. 3. Once deployed, save the address of the contract for use below. ### 2. Set the Custom Gas Token Set the custom gas token on yourchain to the newly deployed `ETH` ERC20 receipt token. 1. To set a custom gas token using OP stack: [https://docs.optimism.io/builders/chain-operators/features/custom-gas-token](https://docs.optimism.io/builders/chain-operators/features/custom-gas-token) 2. To set a custom gas token using arbitrum orbit: [https://docs.arbitrum.io/launch-orbit-chain/how-tos/use-a-custom-gas-token](https://docs.arbitrum.io/launch-orbit-chain/how-tos/use-a-custom-gas-token) ### 3. Transfer All Receipt Tokens Use your L2's canonical bridge to transfer 100% of the `ETH` receipt token from ethereum to yourchain. 1. To transfer using the OP stack standard bridge: [https://docs.optimism.io/builders/app-developers/bridging/standard-bridge](https://docs.optimism.io/builders/app-developers/bridging/standard-bridge) 2. To transfer using the arbitrum orbit bridge: [https://docs.arbitrum.io/launch-orbit-chain/how-tos/add-orbit-chain-to-bridge-ui](https://docs.arbitrum.io/launch-orbit-chain/how-tos/add-orbit-chain-to-bridge-ui) ### 4. Deploy a Native Hyperlane Warp Route (HWR) Using the Hyperlane CLI, deploy an ethereum `ETH` EvmHypNative ↔ yourchain `ETH` EvmHypNative HWR: 1. Run `hyperlane warp init` and complete the following flow: 1. Select `ethereum` and `yourchain` using space, and hit enter. 2. For ethereum, select `native` and accept the mailbox. 3. For yourchain, select `native` and accept the mailbox. 2. Before executing the deployment, ensure yourchain’s `metadata.yaml` has a `blockExplorers` field defined. This will be needed for contract verification in order to easily collateralize yourchain's HWR. 3. Run `hyperlane warp deploy` and confirm the warp deploy config is as expected. 4. After execution, your deployment config in `$HOME/.hyperlane/deployments/warp_routes/ETH/yourid/` will look similar to the following: ```solidity theme={null} # yaml-language-server: $schema=../schema.json tokens: - addressOrDenom: "0x3e5bB1a03fef5DB15A320885E6A0C8Bff8b656bd" chainName: yourchain connections: - token: ethereum|ethereum|0x6d64832bDB4F04721D4F23CCbF17326cb636101e decimals: 18 name: Ether standard: EvmHypNative symbol: ETH - addressOrDenom: "0x6d64832bDB4F04721D4F23CCbF17326cb636101e" chainName: ethereum connections: - token: ethereum|yourchain|0x3e5bB1a03fef5DB15A320885E6A0C8Bff8b656bd decimals: 18 name: Ether standard: EvmHypNative symbol: ETH ``` ### 5. Collateralize Your HWR Deposit yourchain `ETH` as collateral into yourchain's native HWR via the `receive()` function. If needed, you may use the verified contract to do this via your scanner's UI, or a wallet such as Metamask This collateralizes the native HWR, enabling users to bridge their native assets quickly to and from yourchain. ### 6. Testing You can initiate a test transfer of a single wei with the following command: ```bash theme={null} hyperlane warp send --relay -w ETH/yourid ``` The `--relay` flag is optional and will relay the message to the destination chain. You can also run a relayer that delivers only for your HWR in the background with: ```bash theme={null} hyperlane relayer -w ETH/yourid ``` You can test in either direction between where you have the HWR set. By default, your warp route config is found in the local registry at `$HOME/.hyperlane/deployments/warp_routes/`. 🎉 Congrats! You have now enabled fast native transfer to and from yourchain via a custom gas token on your L2. ```mermaid theme={null} sequenceDiagram box ethereum L1 participant ycETH as ETH (ERC20) participant ETH as ETH (Native) end box yourchain L2 participant yETH as ETH (Native) end Note over yETH: 1) set custom gas
token to ycETH ycETH-->>yETH: 2) transfer 100%
of receipt token yETH-->>yETH: 3) deposit native
as collateral yETH-->ETH: <- fast ETH transfer -> ``` Please note that this collateralization strategy takes on certain ISM trust assumptions. ## Resources Take a look at the [inEVM bridge](https://bridge.inevm.com/) to see an example of these HWRs in action. Check out some additional information, published by the Hyperlane supporting team & Injective: * [inEVM Spotlight: Hyperlane](https://blog.injective.com/en/inevm-spotlight-hyperlane-2/) * [Connecting Injective: Hyperlane Opens the inEVM Bridge](https://medium.com/hyperlane/connecting-injective-hyperlane-opens-the-inevm-bridge-6f1d3edf0ff8) * [Hyperlane and Injective | Expanding opportunities](https://medium.com/@kobriyyu/hyperlane-and-injective-expanding-opportunities-8ce170b72da7) # Managing HWR Limits Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/evm/managing-warp-route-limits Manage Hyperlane Warp Route Limits on xERC20 and FiatToken ## xERC20 Deployments Hyperlane Warp Routes (HWR) support [`xERC20` tokens](https://github.com/defi-wonderland/xERC20). Follow these steps to configure `xERC20` for HWR usage: 1. **Ownership Transfer**: * Ensure that the ownership of the [`xERC20` contract](https://github.com/defi-wonderland/xERC20/blob/main/solidity/contracts/XERC20.sol) is transferred to a secure multisig for security purposes. This step is crucial to prevent unauthorized changes. * The `xERC20` contract uses OpenZeppelin's `Ownable` interface. Use the `transferOwnership` function to complete this step. 2. **Mint Limit Configuration**: * The minting and burning limits for the HWR contract are managed through the [`setLimits`](https://github.com/defi-wonderland/xERC20/blob/main/solidity/contracts/XERC20.sol#L85) function in the `xERC20` contract. This function must be called by the contract owner. * The `xERC20` contract uses a 24-hour window to manage limits. This is defined by the [`_DURATION`](https://github.com/defi-wonderland/xERC20/blob/main/solidity/contracts/XERC20.sol#L13) variable, which is set to 1 days (24 hours). The current available limits are calculated dynamically using the [`_getCurrentLimit`](https://github.com/defi-wonderland/xERC20/blob/main/solidity/contracts/XERC20.sol#L234) function. * If 24 hours (`_DURATION`) have passed since the last use, the limit will automatically restore to the full `maxLimit`. * Ensure limits are appropriate for the expected volume to prevent disruptions. Review and adjust the limits based on transaction volumes and expected usage patterns. ## FiatToken Deployments HWRs support [Circle's Bridged USDC in the form of a minter for `FiatToken`](https://github.com/circlefin/stablecoin-evm) (See more on the repo for documentation). There are three roles that are relevant on the `FiatToken` and `MasterMinter` contracts: 1. **`MasterMinter` owner** is the account that can set controllers and minters. 2. **`MasterMinter` controller** is the account that can set the mint limits for its assigned minters. 3. **`MasterMinter` minter** is the account that can actually call `mint` on `FiatToken`. The owner and controller should typically be set to a Safe multisig for enhanced security, the minter is the HWR contract address on the local chain. Mint limits for `FiatToken` are absolute, meaning they do not reset automatically and must be updated if required. There are three actions that should be set on the `MasterMinter` contract to be ready for usage: 1. **Remove the previous test controller:**: * As the owner, remove the previous test controller via the [`removeController(address _controller)` function](https://github.com/circlefin/stablecoin-evm/blob/master/contracts/minting/Controller.sol#L87C14-L87C51) 2. **Set the controller and minter:** * As the owner, you should set the controller and minter via the [`configureController(address controller, address worker)` function](https://github.com/circlefin/stablecoin-evm/blob/master/contracts/minting/Controller.sol#L70). The controller can be the same as the owner, the minter should be the HWR address. 3. **Set the mint limit for the minter:** * As the controller, you should set the mint limit for the minter via the [`configureMinter(uint256 _newAllowance)` function](https://github.com/circlefin/stablecoin-evm/blob/master/contracts/minting/MintController.sol#L116). This limit is not being continuously reset, so either set it to a sufficiently large value (like `cast max-uint`) or monitor the usage and adjust accordingly. # HWR 2.0: Native Rebalancing Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/evm/multi-collateral-warp-routes-rebalancing ## Overview Chains want to allow users to deposit and withdraw tokens from multiple networks. However, manually managing token liquidity across all these chains can be complex and operationally intensive. When deploying assets (like USDC, USDT, ETH) across multiple chains, liquidity gets unbalanced when: * Users deposit tokens on Chain A but withdraw from Chain B * Chain B runs out of tokens * New users cannot withdraw from Chain B until someone manually moves tokens from Chain A to Chain B Native Rebalancing automates this process. For cases where it doesn't apply, [Manual Rebalancing](#manual-rebalancing) is also covered below. ## The Solution: Native Rebalancing **Hyperlane Warp Route (HWR) 2.0** eliminates the complexity of managing multi-chain token liquidity while enabling users to deposit tokens from any supported chain to the destination chain. HWR 2.0 solves the liquidity imbalance problem with a new **Rebalancer Agent** and smart contract support. The Warp Route contracts have been upgraded to enable the new functionality, with a rebalancer role which the contract owner controls. ### Rebalancer HWR 2.0 includes a built-in **Rebalancer.** The Rebalancer is a whitelisted agent that continuously monitors and manages collateral across all chains in the warp route. This agent uses native bridges like CCTP to automatically move funds between chains, maintaining optimal liquidity distribution. For example, if users deposit USDC on Arbitrum and withdraw on Base, the Rebalancer can use CCTP to transfer USDC from Arbitrum to Base to maintain sufficient liquidity on Base. ### What Native Rebalancing enables This enables: * Deposits from any supported chain * Withdrawals to any supported chain * A seamless user experience The rebalancer role can be operated by anyone the contract owner permits. Abacus Works offers this as a managed service, with rebalancing based on configurable thresholds and policies that determine when and how collateral should move. ## How it works ### Basic Setup The diagram below shows a setup where canonical USDC exists on Base and Arbitrum, with a synthetic HWR created on a new chain. ```mermaid theme={null} flowchart subgraph base BU((User)) BWR[USDC Collateral HWR] end subgraph arbitrum AU((User)) AWR[USDC Collateral HWR] end subgraph newchain NWR[USDC Synthetic HWR] Recipient((Recipient)) end BU -- "transferRemote(newchain,
recipient, amount)" --> BWR BWR -. "{recipient, amount}" .-> NWR AU -- "transferRemote(newchain,
recipient, amount)" --> AWR AWR -. "{recipient, amount}" .-> NWR NWR -. "2 \* amount" .-> Recipient ``` ### Collateral Imbalances If more funds flow in one direction, one of the chains in the route can run out of collateral. This *imbalanced flow* prevents withdrawals until the collateral is rebalanced. ```mermaid theme={null} flowchart subgraph base BWR[USDC Collateral HWR] end subgraph arbitrum AWR[USDC Collateral HWR] end subgraph newchain NWR[USDC Synthetic HWR] NU((Recipient)) end NU -- "transferRemote(arbitrum,
recipient, 2 * amount)" --> NWR NWR -. "{recipient, 2 * amount}" .-> AWR ``` ### Managing Collateral Imbalances To maintain a smooth user experience, collateral must be balanced across chains. HWR 2.0 introduces native rebalancing capabilities that automate this process where supported — collateral is automatically moved between chains to resolve imbalances. For deployments without native rebalancing, this requires manually moving collateral between chains. ### USDC Rebalancing For USDC, native rebalancing is handled directly via [Circle CCTP](https://developers.circle.com/cctp). The Rebalancer uses CCTP to move USDC between chains without any additional infrastructure. **Requirements:** * A Rebalancer Agent (the whitelisted agent that monitors and manages collateral) * Warp Route contracts with rebalancer role support * CCTP support on each participating chain Chains without CCTP support cannot use native rebalancing for USDC. ### Inventory Rebalancing For tokens without native bridge support (USDT, ETH), Inventory Rebalancing fills the same role — automatically redistributing collateral across chains based on configurable thresholds via a cross-chain liquidity aggregator. **How It Works:** 1. **Detect**: The Rebalancer monitors collateral levels across all chains in the route and identifies imbalances against configured thresholds 2. **Move**: Inventory is moved to the target chain via a cross-chain liquidity aggregator 3. **Deposit**: Collateral is deposited and withdrawn via the warp route contracts to restore balance **Requirements:** * The route must have on-chain inventory (collateral) on the chains to be rebalanced * The HWR must support the Rebalancer role (HWR 2.0) * Fee contracts must be deployed on each collateral leg of the HWR. These ensure rebalancing costs are covered and that the route remains economically sustainable. Inventory Rebalancing supports USDT and ETH across EVM-compatible chains. Additional chains and assets are planned. ## Manual Rebalancing This section is for advanced users managing liquidity manually. The automated rebalancer is recommended where available. ### Liquidity Provider Currently, Hyperlane Warp Routes 2.0 don't have an explicit liquidity provider interface that enables local deposits/withdrawals. However, LPs can manually manage liquidity using the [Hyperlane CLI](https://www.npmjs.com/package/@hyperlane-xyz/cli) or the UI to interact with the HWRs in the [Hyperlane registry](https://github.com/hyperlane-xyz/hyperlane-registry). The stopgap procedure defined below requires at least one synthetic chain to exist within the HWR topology. * To inspect a HWRs topology, use the `warp read` command: ``` hyperlane warp read -w ETH/ethereum-base-bsc ethereum: type: native ... base: type: native ... bsc: type: synthetic ... ``` * To send a transfer (`transferRemote`) on a HWR, use the `warp send` command: ``` hyperlane warp send \ -w ETH/ethereum-base-bsc \ --origin base \ --destination bsc \ --amount \ --recipient
``` ### Depositing Liquidity LPs can deposit collateral via a `transferRemote` where: * `destination` domain is a chain where the HWRs has a `synthetic` type * `recipient` address is controlled by the LP * `amount` is liquidity denominated in the `origin` chains `collateral` token ```mermaid theme={null} flowchart LP((Liquidity Provider)) subgraph arbitrum AWR[USDC Collateral HWR] AUSDC[USDC] end subgraph mychain MWR[USDC Synthetic HWR] end AWR -- "transferFrom(LP, amount)" --> AUSDC LP -. "amount" .-> AWR LP -- "transferRemote(newchain,
LP, amount)" --> AWR AWR -. "{LP, amount}" .-> MWR MWR -. "amount" .-> LP ``` This can be done by providing liquidity on many collateral chains and representing a claim on each collateral with a single synthetic asset balance. ### Withdrawing Liquidity LPs can withdraw via a `transferRemote` where * `destination` domain is a chain where the HWR is a `collateral` type * `recipient` address is controlled by the LP * `amount` is denominated in the `destination` chains `collateral` token ```mermaid theme={null} flowchart LP((Liquidity Provider)) subgraph arbitrum AWR[USDC Collateral HWR] AUSDC[USDC] end subgraph mychain MWR[USDC Synthetic HWR] end LP -- "transferRemote(arbitrum,
LP, amount)" --> MWR LP -. "amount" .-> MWR MWR -. "{LP, amount}" .-> AWR AWR -- "transfer(LP, amount)" --> AUSDC AWR -. "amount" .-> LP ``` # Transfer and Call Pattern Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/evm/transfer-and-call-pattern ## Overview The **Transfer and Call Pattern** enables a contract to both bridge assets via [Hyperlane Warp Route (HWR)](/docs/protocol/warp-routes/warp-routes-overview) and execute an action on the destination chain after the assets arrive. This pattern is useful for cases where an action depends on token balances after bridging. While HWR handle cross-chain token transfers, this pattern extends their capabilities by using [Interchain Accounts (ICA)](docs/applications/interchain-account) to execute arbitrary logic on the destination chain. ### Use Cases Some scenarios include: * **Cross-chain governance**: A user must hold a specific NFT to vote on a proposal. The system bridges the NFT to the governance chain and ensures the vote call executes after the transfer completes. * **Bridging collateral**: A protocol sends assets from an L2 to an L1 vault for collateralization before interacting with the vault. * **Faster rollup withdrawals**: A user can claim liquidity instantly while waiting for the final bridge settlement. ## High-level Diagram ```mermaid theme={null} flowchart TB subgraph Origin chain direction TB Sender Contract ICA_Router_O[Interchain Account Router] Warp_Route_O[HWR] Mailbox_O[(Mailbox)] end subgraph Destination chain direction TB Mailbox_D[(Mailbox)] Warp_Route_D[HWR] ICA_Router_D[Interchain Account Router] ICA[Interchain Account] Recipient end Sender -->|Initiates transfer & call| Contract Contract -->|Sends tokens| Warp_Route_O Warp_Route_O -->|Receive tokens| Mailbox_O Mailbox_O -. "Relay" .- Mailbox_D Mailbox_D -->|Receive tokens| Warp_Route_D Warp_Route_D -->|Send tokens| ICA Contract -->|Sends execution request| ICA_Router_O ICA_Router_O -. "Relay" .- ICA_Router_D ICA_Router_D -->|Execute call| ICA ICA -->|Final execution| Recipient click ICA_Router_O https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/middleware/InterchainAccountRouter.sol click ICA_Router_D https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/middleware/InterchainAccountRouter.sol style Sender fill:#FF0099 style ICA fill:#FF0099 style Recipient fill:#FF0099 ``` * Currently, Interchain Accounts (ICA) are only supported on EVM-compatible chains. If broader VM support is needed, this pattern can be extended with other environments and may require additional design considerations. ## How It Works 1. Tokens are transferred from the sender to the contract. 2. An [Interchain Account (ICA)](docs/applications/interchain-account) is derived for the contract on the destination chain. 3. The HWR transfer is initiated, sending the tokens crosschain to the interchain account. 4. A remote contract call is executed on the destination chain from the interchain account after the tokens arrive. The Solidity function below demonstrates this pattern: ```solidity theme={null} function transferAndCall( uint32 destination, uint256 amount, IERC20 asset, // Tokens to transfer (not derivable from TokenRouter) TokenRouter warpRoute, CallLib.Call[] calldata calls // Array of calls to execute on the destination chain ) external payable { // Get the interchain account address for the contract on the destination chain bytes32 self = interchainAccountRouter .getRemoteInterchainAccount(destination, address(this)) .addressToBytes32(); // Quote the fees for the warp route transfer Quote[] memory quotes = warpRoute.quoteTransferRemote( destination, self, amount ); // Extract the native mailbox dispatch fee (index 0) uint256 nativeFee = quotes[0].amount; // Extract the total token amount charged by the warp route uint256 tokenFee = quotes[1].amount; // Transfer the total token amount from the sender to this contract asset.transferFrom(msg.sender, address(this), tokenFee); // Approve the warp route to spend the tokens asset.approve(address(warpRoute), tokenFee); // Initiate the HWR transfer to send tokens cross-chain warpRoute.transferRemote{value: nativeFee}(destination, self, amount); // Execute the specified interchain calls using the remaining gas funds interchainAccountRouter.callRemote{value: msg.value - nativeFee}( destination, calls ); } ``` * **Execution Ordering Consideration**: The contract must ensure that the token transfer is fully completed before executing any follow-up action. If the remote call depends on a token balance (e.g., staking, governance, deposits), it may fail if executed before the tokens arrive. The relayer retries with backoff to ensure successful ICA call execution. - The ICA may also need to perform an ERC20 approval call before executing a deposit. - If the contract executing the action is not permissioned, anyone could call it (depending on its implementation). # Create your xERC20 Token Bridge Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/evm/xerc20-warp-route This guide walks you through deploying an xERC20 Hyperlane Warp Route (HWR) between two networks of your choice. We'll use Ethereum as an example for the origin chain; however, you can select any supported network as the origin and destination. ## Prerequisites To complete this walkthrough, you should have: 1. **An origin and destination network of choice**, between which you’d like to deploy the xERC20 HWR. 2. **The address of an xERC20 or xERC20Lockbox** on the origin and destination chain. 3. **Hyperlane CLI installed** and a **wallet private key set as the `HYP_KEY` environment variable**, funded on both origin and destination networks. ### Step 1: Initialize a New HWR Run the following command to generate a HWR configuration: ```bash theme={null} hyperlane warp init ``` 1. Select **Ethereum** (origin) and **YourChain** (destination) using space, then hit enter. 2. For Ethereum (origin), choose **xERC20** or **xERC20Lockbox**, and enter the contract address. 3. For YourChain (destination), choose **xERC20** or **xERC20Lockbox**, and enter the contract address. Choosing Between xERC20 and xERC20Lockbox: * **xERC20Lockbox**: Use this if your token is already deployed on the origin chain and requires a wrapped version for cross-chain transfers. * **xERC20**: Use this if your token natively implements xERC20 and does not require a lockbox. If you're unsure, review your token’s contract structure or deployment history to determine the correct choice. ### Step 2: Deploy the xERC20 HWR Run the following command to deploy the HWR: ```bash theme={null} hyperlane warp deploy ``` This deploys the \*Hyperlane adapter contracts\*\*, either: * **HypXERC20Lockbox** (if using xERC20Lockbox) * **HypXERC20** (if using xERC20) *The CLI does not deploy non-Hyperlane contracts (e.g., existing xERC20 contracts). Those should already be deployed.* ### Step 3: Configure Minting Permissions Once the xERC20 HWR contracts are deployed, you must configure minting permissions for the destination token. Set the mint limit for the newly deployed HWR using the [`setLimits` function](https://github.com/defi-wonderland/xERC20/blob/main/solidity/contracts/XERC20.sol#L85) in your xERC20 contract. By default, these limits are found in the Registry, located at `~/.hyperlane` locally. ### Step 4: Test Cross-Chain Transfers Test transferring tokens across chains using: ```bash theme={null} hyperlane warp send -w --amount ``` * Replace `` with your warp route ID (e.g., `USDC/ethereum-yourchain`). * Replace `` with the number of tokens to transfer. ### 🎉 Congrats! You have successfully created an **xERC20 HWR**. Your xERC20 tokens can now move across chains! Please note that cross-chain operations rely on **Interchain Security Modules (ISMs)**, and there are inherent risks, such as ISM trust assumptions. ## Resources For more resources on deploying xERC20 HWRs, check out: * [xERC20 Token Standard](https://github.com/defi-wonderland/xERC20/blob/main/solidity/contracts/XERC20.sol) * [xERC20 Token transfer limits](./managing-warp-route-limits) # Deploy an SVM HWR Source: https://docs.hyperlane.xyz/docs/guides/warp-routes/svm/svm-warp-route-guide ## Outcomes You will be deploying a Hyperlane Warp Route (HWR) for an asset of your choice, between two SVM chains with an existing Hyperlane core deployment. At the time of writing this document, supported SVM chains are Solana and Eclipse, but you can find an up-to-date list [here](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/rust/sealevel/environments/mainnet3) (all chain directory names with a `core` subdirectory). **Looking for cross-VM guides?** See: * [EVM ↔ SVM Warp Route Guide](/docs/guides/warp-routes/evm-svm-warp-route-guide) * [Cosmos ↔ SVM Warp Route Guide](/docs/guides/warp-routes/cosmos-svm-warp-route-guide) If you want your SVM rollup supported as a core Hyperlane deployment, [get in touch](https://forms.gle/KyRTaWvo4XNmNvrq6)! ## HWR Types The type of token used determines the HWR type, so it's important to understand the different HWR contracts available: * [Native](/docs/protocol/warp-routes/warp-routes-types#native-token-hwrs): Handles the transfer of native gas tokens (e.g. SOL on Solana, ETH on Eclipse). * [Collateral](/docs/protocol/warp-routes/warp-routes-types#collateral-backed-erc20-hwr): Handles the transfer of existing [Token-2022](https://spl.solana.com/token-2022) or [Token](https://spl.solana.com/token) tokens (the ERC20 equivalent on SVM). * [Synthetic](/docs/protocol/warp-routes/warp-routes-types#synthetic-erc20-hwr): Handles synthetic tokens that are minted and burned as transfers occur through the HWR, to represent tokens from their origin chain. The tooling in this guide deploys a new Token-2022 token in this case, whose authority is set to the deployer key. Here are the common HWR setups (you can find more details [here](/docs/protocol/warp-routes/warp-routes-example-usage)): * **Native to Synthetic**: Lock Native tokens on the origin chain to mint Synthetic ones on the destination. When transferring back, the Synthetic is burned. An example of this is a SOL HWR between Solana and Eclipse. * **Collateral to Synthetic**: Lock Collateral tokens on the origin chain to mint Synthetic ones on the destination. When transferring back, the Synthetic is burned. An example of this is a USDC HWR between Solana and Eclipse. * Other: **Native to Native** (such as ETH between Optimism and Arbitrum), as well as **Collateral to Collateral**, are also possible if the token already exists on both origin and destination chains. Rebalancing liquidity is an important consideration in this case. ## Before You Start Deploying a HWR requires there to be a core Hyperlane deployment that is connected (i.e. actively relayed and secured) to the rest of the Hyperlane ecosystem. The core Hyperlane deployments used in this guide are Solana ([core artifacts](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/sealevel/environments/mainnet3/solanamainnet/core/program-ids.json)) and Eclipse ([core artifacts](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/sealevel/environments/mainnet3/eclipsemainnet/core/program-ids.json)). You may need to refer to these core artifacts throughout the guide. ## Walkthrough: Deploy a Sealevel HWR ### Step 1: Build the HWR Programs 1. Clone the [hyperlane-monorepo](https://github.com/hyperlane-xyz/hyperlane-monorepo) ```bash theme={null} git clone https://github.com/hyperlane-xyz/hyperlane-monorepo cd hyperlane-monorepo/rust/sealevel/programs ``` 2. Build the HWR programs on your machine. The `./build-programs.sh` script handles installing and using the required Solana CLI version automatically. ```bash theme={null} # run from this directory cd rust/sealevel/programs # build the token programs ./build-programs.sh token ``` This [script](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/sealevel/programs/build-programs.sh) will **compile the Solana programs**, which is needed for deployment. It will use the required Solana CLI version (`3.0.14`) automatically and reset back to the previously used version afterward. To verify the build output, check the target/deploy directory for `.so` files in `hyperlane-monorepo/rust/sealevel/target/deploy` ### Step 2: Prepare for Deployment 1. To deploy the contracts, install `solana-cli 3.0.14`. Note that you **must** use this version, otherwise deployment may fail. ```bash theme={null} sh -c "$(curl -sSfL https://release.anza.xyz/v3.0.14/install)" ``` After installing you can verify the version with: ```bash theme={null} solana --version ``` 2. Create a **Solana keypair**. This key pays for the deployment and will be the owner of the deployed programs. An existing funded key can be used if you'd like. ```bash theme={null} solana-keygen new --outfile ./warp-route-deployer-key.json ``` * To read the public key you just created: ```bash theme={null} solana-keygen pubkey ./warp-route-deployer-key.json ``` * Check the balance: ```bash theme={null} solana balance --keypair ./warp-route-deployer-key.json ``` ### Step 3: Configure the HWR 1. Create a directory for your HWR in `rust/sealevel/environments/mainnet3/warp-routes` with the name you want your HWR deployment to have. ```bash theme={null} mkdir -p rust/sealevel/environments/mainnet3/warp-routes/ ``` For example, the existing SOL HWR between Solana and Eclipse lives in `rust/sealevel/environments/mainnet3/warp-routes/eclipsesol`. 2. Inside the directory you just created, create a configuration file named `token-config.json`. Configure the parameters of your HWR based on the `serde_json` serialization of the [TokenConfig](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/a5afd20f3ae69ccb3289d845d44b99dbdcde2c62/rust/sealevel/client/src/warp_route.rs#L114) Rust struct. The value to set for the `interchainGasPaymaster`, can be found in the [core deployment artifacts](#before-you-start). The example below shows a testnet **Native to Synthetic HWR** that transfers SOL from Solana and mints synthetic SOL on Eclipse. You can also check [this configuration](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/a5afd20f3ae69ccb3289d845d44b99dbdcde2c62/rust/sealevel/environments/mainnet3/warp-routes/eclipsesol/token-config.json) of a production SOL HWR. ```json theme={null} { "solanatestnet": { "type": "native", "decimals": 9, "interchainGasPaymaster": "" }, "eclipsetestnet": { "type": "synthetic", "decimals": 9, "name": "Solana (testnet)", "symbol": "SOL", "uri": "" "interchainGasPaymaster": "" } } ``` 3. (Optional) If your HWR creates a Synthetic token, you can open a PR to the `hyperlane-registry` with metadata to associate with this token (example PR [here](https://github.com/hyperlane-xyz/hyperlane-registry/pull/142)). The `hyperlane-registry` also gives your HWR visibility within the Hyperlane ecosystem. ### Step 4: Deploy the HWR 1. Fund the new keypair on both networks the HWR is being deployed to. * The public key should be the same across SVM networks, but double check with the wallets recommended by each chain, by loading the private key into them. * The funding should be enough to cover rent for all accounts related to the HWR, pay for transaction fees, and fund the [ATA](https://www.alchemy.com/overviews/associated-token-account) payer accounts (more on this below). For reference, the observed rent from one HWR account is `2.35 SOL` on Solana and `0.025 ETH` on Eclipse, so it's a good idea to fund the key with at least `5 SOL` / `0.05 ETH`. 2. Deploy the HWR using the `warp-route deploy` subcommand from the `rust/sealevel/client` directory: Example usage: ```bash theme={null} cargo run -- -k ./warp-route-deployer-key.json \ warp-route deploy \ --warp-route-name \ --environment mainnet3 \ --environments-dir ../environments \ --built-so-dir ../target/deploy \ --token-config-file ../environments/mainnet3/warp-routes//token-config.json \ --registry ~/path/to/your/local/hyperlane-registry \ --ata-payer-funding-amount ``` Please choose a reasonable amount to fund the HWR ATA payer accounts. The recommended initial funding amount is `alert_threshold * 2`, with the threshold value found [here](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/typescript/infra/src/warp/helm.ts). * Overview of CLI flags: * `--warp-route-name`: should match the directory name picked for the HWR earlier * `--environment`: keep as `mainnet3` * `--environments-dir ../environments`: keep as `../environments` * `--built-so-dir`: keep as `../target/deploy`, as it points to the compilation output directory of HWR programs * `--token-config-file`: point this to the `token-config.json` file created earlier * `--registry`: path to your local clone of the hyperlane-registry * `--ata-payer-funding-amount`: this flag specifies by how much to fund the HWR [ATA](https://www.alchemy.com/overviews/associated-token-account) payer accounts on both chains the deployment happens on. It's expressed in the lowest currency denomination, which means that it's interpreted as Lamports on Solana and Gwei on Eclipse (since it uses ETH as its native currency). In the command below, the value `1000000` works out to `0.001` ETH and `0.001` SOL, which is enough for an initial deployment, but not for production usage. ATA payers can always be topped up later. For reference, every HWR transfer costs the ATA payer `0.000000001 SOL` (on Solana) and `0.000021 ETH` (on Eclipse) on the destination chain. Note that since our goal was to make this tooling accessible to developers as soon as possible, it's not as reliable as we would hope. Please get in touch through a [GitHub issue](https://github.com/hyperlane-xyz/hyperlane-monorepo/issues) or via the [GitHub Discussions](https://github.com/hyperlane-xyz/hyperlane-monorepo/discussions) if you run into issues. #### Troubleshooting tips * The script is unlikely to work from the first try due to network congestion and program size, but the script should be idempotent and skip contracts that were already deployed/initialized. * Errors like `Error: 11 write transactions failed` or `Error: Custom: Invalid blockhash` can always be retried by re-running the command. If retriable errors persist, consider increasing the compute unit price [here](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/44e0ff0733baf0da4d2b0304915f5f6cce92ffc7/rust/sealevel/client/src/cmd_utils.rs#L76). * For other error types, you may need to close the buffers and programs of your deployer key and redeploy everything from scratch. To display buffers and programs and close them one by one, follow the commands below. Closing programs also helps recover their rent deposit. ```bash theme={null} solana program show --programs --keypair ./warp-route-deployer-key.json --url solana program show --buffers --keypair ./warp-route-deployer-key.json --url # You'll need to add the `--bypass-warning` flag when closing program accounts (as opposed to closing buffers) solana program close --url ``` * To increase the odds of the deployment succeeding faster, you can configure a private RPC URL in your local clone of the hyperlane-registry. (e.g. in `solanamainnet.rpcUrls.http`) * If deploying a synthetic token, the command below will create a new token mint and use the metadata token extension to set the token name, symbol, and metadata json using the fields in the `--token-config-file` file, run `warp-route deploy`: ```bash theme={null} # run from `rust/sealevel/client` cargo run -- -k ./warp-route-deployer-key.json warp-route deploy \ --warp-route-name eclipsesol \ --environment mainnet3 \ --environments-dir ../environments \ --built-so-dir ../target/deploy \ --token-config-file ../environments/mainnet3/warp-routes/eclipsesol/token-config.json \ --registry ~/path/to/your/local/hyperlane-registry \ --ata-payer-funding-amount 10000000 ``` ## Interacting with the HWR 1. **Query the HWR Program** You can check the program details like Mint Account, Mint Authority, and ATA payer account using the following command: ```bash theme={null} # run from `rust/sealevel/client` cargo run -- -k ./warp-route-deployer-key.json \ -u token query \ --program-id ``` Replace: * ``: e.g., [https://api.devnet.solana.com](https://api.devnet.solana.com) * ``: base58 address from program-ids.json (located in your warp-route directory). * ``: native|synthetic|collateral If deploying a synthetic token, query the Mint Authority account to check out the metadata: ```bash theme={null} solana account --url ``` 2. **Transfer Tokens Through the HWR** To test token transfers across chains, run the following command: ```bash theme={null} # run from `rust/sealevel/client` cargo run -- -u \ -k ./warp-route-deployer-key.json \ token transfer-remote ./warp-route-deployer-key.json \ \ --program-id ``` * ``: You'll need the domain ID of the chain you're sending to, which you can find in the chain's `metadata.yaml` entry from the [hyperlane-registry](https://github.com/hyperlane-xyz/hyperlane-registry/tree/main/chains). * ``: base58 address from program-ids.json (located in your warp-route directory). * ``: Type of token on the origin chain, options are: native|synthetic|collateral 3. **Verify the Balance on the Destination Chain** Look for the balance of the recipient on the destination chain, by querying the Mint Account address: ```bash theme={null} spl-token balance --owner ./warp-route-deployer-key.json \ -u ``` * The final parameter here is the SPL token ID. So if this is a synthetic HWR you want to check the balance of, you need to use the Mint address from a prior query you made a few steps ago. * You can also check out the last tx made to the recipient account in the explorer 4. **Explore Additional CLI Commands** This guide has made heavy use of the `hyperlane-sealevel-client` CLI from `hyperlane-monorepo`. You may find its various commands useful for configuring the HWR, making state queries, sending transfers, and more. Check out the other utilities it provides, in particular those under the `token` subcommand. ```bash theme={null} # run from `rust/sealevel/client` cargo run -- --help ``` For production deployments, we strongly recommend avoiding the use of hotkeys like those used in this guide. Instead, transfer ownership to a **multisig setup**, such as [Squads](https://squads.so/), for enhanced security. # Intro to Hyperlane Source: https://docs.hyperlane.xyz/docs/intro ## What is Hyperlane? Hyperlane is a permissionless interoperability protocol for cross-chain communication across different blockchain environments. It enables message passing and asset transfers across different chains without relying on centralized intermediaries or requiring any permissions. ### Key Features * **Permissionless**: Anyone can [deploy Hyperlane](/docs/guides/chains/deploy-hyperlane), whether it is a layer 1, rollup, or app-chain, and start building cross-chain applications right away—no approvals, no intermediaries. * **Modular Security**: Hyperlane's [Interchain Security Modules (ISM)](/docs/protocol/ISM/modular-security) allow developers to configure, compose, and customize their security model according to their application's needs. * **Multi-VM Support**: Hyperlane enables cross-chain communication for multiple virtual machines (VMs), including EVM, SVM and CosmWasm. * Hyperlane also supports **cross-VM interactions**, such as EVM ↔ SVM asset transfers. ## Start Building with Hyperlane[​](#start-building-with-hyperlane "Direct link to Start Building with Hyperlane") Get started with Hyperlane by exploring deployment guides & key features: * **[Bridge any token with Hyperlane Warp Routes (HWR)](/docs/guides/quickstart/deploy-warp-route)**: HWRs let you deploy a custom token bridge, enabling any native or `ERC20` token to be transferred across chains. * For **EVM-based chains**, use the **[EVM HWR Guide](/docs/guides/quickstart/deploy-warp-route)**. * For **Solana Virtual Machine (SVM) chains**, see the **[SVM HWR Guide](/docs/guides/warp-routes/svm/svm-warp-route-guide)**. * For **Cosmos SDK-based chains**, use the **[Cosmos SDK Module](/docs/alt-vm-implementations/cosmos-sdk)**. * For **cross-chain transfers between EVM and SVM**, check out the **[EVM-SVM HWR Guide](/docs/guides/warp-routes/evm-svm-warp-route-guide)**. * **[Learn about General Message Passing](/docs/reference/messaging/send)**: Send arbitrary messages between chains. * **Use [Interchain Accounts](/docs/applications/interchain-account)**: Execute smart contract calls on remote chains from a single account. * **[Deploy Hyperlane to your chain](/docs/guides/chains/deploy-hyperlane)**: Set up Hyperlane on a new chain. * **Join our Ecosystem:** [GitHub Discussions](https://github.com/hyperlane-xyz/hyperlane-monorepo/discussions) | [Twitter](https://x.com/hyperlane) # Agent Configuration Source: https://docs.hyperlane.xyz/docs/operate/config/agent-config All agents use the same method of configuration which is a multi-layered config approach which allows for easy overriding of default configs. Each layer overrides overlapping values in the previous. ## Config layers 1. Base configuration from "default deployments" are in the [monorepo](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/rust/main/config) and all of these are loaded automatically. 2. Config files passed in via the `CONFIG_FILES` env var are loaded next; this env var should be a comma separated list of paths to json files that should be loaded in order from first to last. 3. `HYP_` prefixed env vars will be read next. 4. `HYP__` prefixed env vars are then read and apply ONLY for the current agent. I.e. `RELAYER`, `VALIDATOR`, and `SCRAPER` will only read their respective prefixes. 5. Command line arguments will be read last ## Command line arguments[​](#command-line-arguments "Direct link to Command line arguments") Command line arguments are added after the application name, such as`./relayer --originChainNames="test1,test2,test3"` The following formats are supported: * `--argName argValue` * `--argName "argValue"` * `--argName 'argValue'` * `--argName=argValue` * `--argName="argValue"` * `--argName='argValue'` Argument names are case-insensitive, so in this guide we may show them in camel-case for easier reading, but `--argName` is equivalent to `--ARGNAME` and `--argname.` Examples: * `{ "db": "/path/to/dir" }` can be set with `--db "/path/to/dir"` * `{ "chains": { "ethereum": { "name": "ethereum" } } }` (abbreviated as `chains.ethereum.name` or `chains..name`) can be set with `--chains.ethereum.name ethereum` * `{ "chains": { "avalanche": { "customRpcUrls": "https://some-url.com" } } }` (abbreviated as `chains..customrpcurls`) can be set with `--chains.avalanche.customrpcurls "https://some-url.com"` ## Environment variables[​](#environment-variables "Direct link to Environment variables") The config file format is the preferred way to set things which are not secret and do not need to change for each run as it is the easiest format to inspect and edit. Every config value in the file can be set as an env var if you use the correct name, however, there are a few env vars that cannot be set in the config such as `CONFIG_FILES`. `HYP_` and `HYP__` are equivalent prefixes with the only difference being which order they are loaded in and can refer to all of the config values in the config files. The env name will be one of those two prefixes, and then the underscore-separated path of the uppercased path components to the config value. For example: * `{ "db": "/path/to/dir" }` can be set with `HYP_DB="/path/to/dir"` or `HYP_RELAYER_DB="/path/to/dir"` * `{ "chains": { "ethereum": { "name": "ethereum" } } }` (abbreviated as `chains.ethereum.name` or `chains..name`) can be set with `HYP_CHAINS_ETHEREUM_NAME="ethereum"` or `HYP_VALIDATOR_CHAINS_ETHEREUM_NAME="ethereum"` or `HYP_RELAYER_CHAINS_ETHEREUM_NAME="ethereum"` ... * `{ "chains": { "avalanche": { "customRpcUrls": "https://some-url.com" } } }` (abbreviated as `chains..customrpcurls`) can be set with `HYP_CHAINS_AVALANCHE_CUSTOMRPCURLS="https://some-url.com"` or `HYP_VALIDATOR_AVALANCHE_CUSTOMRPCURLS="https://some-url.com"` and so on... ## Config files with Docker Running with the agent in Docker adds an extra layer of complexity because the config files need to be accessible from within the Docker container. The base configs that can be found in [the repo](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/rust/main/config) are already part of the provided Docker image and will all be loaded by default. Mounting a single config file can be done with the flag `--mount type=bind,source=$LOCAL_CONFIG_PATH,target=/config/$CONFIG_NAME,readonly` and then adding the config file to `CONFIG_FILES` so it is loaded. Mounting an entire directory can be done with the flag `--mount source=$LOCAL_CONFIG_DIR_PATH,target=/config,readonly` then adding the individual config files to `CONFIG_FILES` that you want so they are loaded. For example, suppose you have a config file at your local machine's path `/home/workspace/ethereum.json` and want to run the validator with it. ```bash theme={null} docker run -it \ --mount type=bind,source=/home/workspace/ethereum.json,target=/config/ethereum.json,readonly \ -e CONFIG_FILES=/config/ethereum.json $DOCKER_IMAGE ./validator ``` The `source` path is the path on your local machine, the `target` path is where the source path contents will be made available within the Docker container, and the `CONFIG_FILES` should specify config(s) from the target path. # Configuration Reference Source: https://docs.hyperlane.xyz/docs/operate/config/config-reference ## CONFIG\_FILES **Description:** (Env only) List of additional configuration file paths to load in order (such as those in `hyperlane-monorepo/rust/main/config`). They will be merged first to last, so if both the first one and the last one specify a specific config path, the value set in the last file listed will be used. These files must be accessible within the filesystem your agent has access to. If you're running in Docker, see [the agent configuration guide](./agent-config#config-files-with-docker) for tips on mounting your config files into your Docker container. **Optional:** Yes **Agents:** All **Type:** `string` (Comma separated list of file paths) ```bash As Arg theme={null} # Not supported as an argument ``` ```bash As Env theme={null} export CONFIG_FILES='./config/ethereum/my-config.json,./config/ethereum/my-validator-config.json' ``` ```json As Config theme={null} # Not supported in configuration files ``` ## chains **Description:** Configuration for each of the chains that must be used by an agent. **Optional:** No **Agents:** All **Type:** `Map` (See `chains.*` for `ChainSetup` values) ```bash As Arg theme={null} --chains.${CHAIN_NAME}.* ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_*="...." export HYP_CHAINS_ETHEREUM_*="...." ``` ```json As Config theme={null} { "chains": { "": {}, "ethereum": {} } } ``` ## chains.``.name **Description:** Name of the domain. Allows specifying a different name for the domain than the chain's true name. This should *almost always* be the same as `chain_name`. **Requires:** Alignment with domain id if it is a known domain name. **Optional:** No **Agents:** All **Type:** `string` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.name $DOMAIN_NAME --chains.ethereum.name ethereum ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_NAME="$DOMAIN_NAME" export HYP_CHAINS_ETHEREUM_NAME="ethereum" ``` ```json As Config theme={null} { "chains": { "": { "name": "" }, "ethereum": { "name": "ethereum" } } } ``` ## chains.``.domain **Description:** Hyperplane domain id to uniquely identify the domain. See also: [Domain Identifiers](/docs/reference/domains). **Requires:** Alignment with domain name if it is a known domain. **Optional:** No **Agents:** All **Type:** `Numeric (string | number)` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.domain $DOMAIN_ID --chains.ethereum.domain 1 ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_DOMAIN="$DOMAIN_NAME" export HYP_CHAINS_ETHEREUM_DOMAIN=1 ``` ```json As Config theme={null} { "chains": { "": { "domain": "" }, "ethereum": { "domain": 1 } } } ``` ## chains.``.mailbox **Description:** Address of the mailbox contract on the chain. See also [contract addresses](/docs/reference/addresses/deployments/mailbox). **Optional:** No **Agents:** All **Type:** `Hash (string)` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.mailbox "$MAILBOX_ADDRESS" --chains.ethereum.mailbox "0x35231d4c2D8B8ADcB5617A638A0c4548684c7C70" ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_MAILBOX="$MAILBOX_ADDRESS" export HYP_CHAINS_ETHEREUM_MAILBOX="0x35231d4c2D8B8ADcB5617A638A0c4548684c7C70" ``` ```json As Config theme={null} { "chains": { "": { "addresses": { "mailbox": "" } }, "ethereum": { "addresses": { "mailbox": "0x35231d4c2D8B8ADcB5617A638A0c4548684c7C70" } } } } ``` ## chains.``.interchainGasPaymaster **Description:** Address of the interchain gas paymaster contract on the chain. See also [contract addresses](/docs/reference/addresses/deployments/interchainGasPaymaster). **Optional:** No **Agents:** All **Type:** `Hash (string)` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.interchainGasPaymaster "$IGP_ADDRESS" --chains.ethereum.interchainGasPaymaster "0x6cA0B6D22da47f091B7613223cD4BB03a2d77918" ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_INTERCHAINGASPAYMASTER="$IGP_ADDRESS" export HYP_CHAINS_ETHEREUM_INTERCHAINGASPAYMASTER="0x6cA0B6D22da47f091B7613223cD4BB03a2d77918" ``` ```json As Config theme={null} { "chains": { "": { "addresses": { "interchainGasPaymaster": "" } }, "ethereum": { "addresses": { "interchainGasPaymaster": "0x6cA0B6D22da47f091B7613223cD4BB03a2d77918" } } } } ``` ## chains.``.validatorAnnounce **Description:** Address of the validator announce contract on the chain. See also [contract addresses](/docs/reference/addresses/deployments/validatorAnnounce). **Optional:** No **Agents:** All **Type:** `Hash (string)` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.validatorAnnounce "$VALIDATOR_ANNOUNCE_ADDRESS" --chains.ethereum.validatorAnnounce "0x9bBdef63594D5FFc2f370Fe52115DdFFe97Bc524" ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_VALIDATORANNOUNCE="$VALIDATOR_ANNOUNCE_ADDRESS" export HYP_CHAINS_ETHEREUM_VALIDATORANNOUNCE="0x9bBdef63594D5FFc2f370Fe52115DdFFe97Bc524" ``` ```json As Config theme={null} { "chains": { "": { "addresses": { "validatorAnnounce": "" } }, "ethereum": { "addresses": { "validatorAnnounce": "0x9bBdef63594D5FFc2f370Fe52115DdFFe97Bc524" } } } } ``` ## chains.``.merkleTreeHook **Description:** Address of the merkle tree hook contract on the chain. See also [contract addresses](/docs/reference/addresses/deployments/merkleTreeHook). **Optional:** No **Agents:** All **Type:** `Hash (string)` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.merkleTreeHook "$MERKLE_TREE_HOOK_ADDRESS" --chains.ethereum.merkleTreeHook "0x48e6c30B97748d1e2e03bf3e9FbE3890ca5f8CCA" ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_MERKLETREEHOOK="$MERKLE_TREE_HOOK_ADDRESS" export HYP_CHAINS_ETHEREUM_MERKLETREEHOOK="0x48e6c30B97748d1e2e03bf3e9FbE3890ca5f8CCA" ``` ```json As Config theme={null} { "chains": { "": { "addresses": { "merkleTreeHook": "" } }, "ethereum": { "addresses": { "merkleTreeHook": "0x48e6c30B97748d1e2e03bf3e9FbE3890ca5f8CCA" } } } } ``` ## chains.``.signer **Description:** The signer that should be used this chain **Optional:** Yes (Will use `defaultsigner` if not specified) **Agents:** All **Type:** `SignerConf (Object)` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.signer.* ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_SIGNER_*="...." ``` ```json As Config theme={null} { "chains": { "": { "signer": {} }, "ethereum": { "signer": {} } } } ``` ## chains.``.signer.type **Description:** The type of signer that is defined. A `HexKey` signer uses a private key, an `Aws` signer uses an AWS based KMS, and `Node` assumes the local node will sign RPC calls. **Optional:** Yes; Defaults to `node` unless a `key` is specified in which case it defaults to `hexKey` **Agents:** All **Type:** `Enum ("hexKey" | "aws" | "cosmosKey" | "node")` Accepted values for the different VMs are: * EVM: `hexKey` (ECDSA) or `aws` (ECDSA) * sealevel: `hexKey` (ED25519) * cosmos: `cosmosKey` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.signer.type hexKey --chains.ethereum.signer.type node ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_SIGNER_TYPE="hexKey" ``` ```json As Config theme={null} { "chains": { "": { "signer": { "type": "hexKey" } }, "ethereum": { "signer": { "type": "node" } } } } ``` ## chains.``.signer.key **Description:** A hex key. The hex string of a private key. **Requires:** `chains..signer.type = "hexKey" | undefined` **Optional:** No (iff requirements are met) **Agents:** All **Type:** `string` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.signer.key "8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61" ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_SIGNER_KEY="8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61" ``` ```json As Config theme={null} { "chains": { "": { "signer": { "key": "" } }, "ethereum": { "signer": { "key": "8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61" } } } } ``` ## chains.``.signer.id **Description:** The UUID identifying the AWS KMS key **Requires:** `chains..signer.type = "aws"` **Optional:** No (iff requirements are met) **Agents:** All **Type:** `string` ```bash As Arg theme={null} --chains.ethereum.signer.type "alias/validator-signer-ethereum" ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_SIGNER_ID="alias/validator-signer-ethereum" ``` ```json As Config theme={null} { "chains": { "ethereum": { "signer": { "type": "aws", "id": "alias/validator-signer-ethereum" } } } } ``` ## chains.``.signer.region **Description:** The AWS region **Requires:** `chains..signer.type = "aws"` **Optional:** No (iff requirements are met) **Agents:** All **Type:** `string` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.signer.region us-east-1 ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_SIGNER_REGION="us-east-1" ``` ```json As Config theme={null} { "chains": { "": { "signer": { "type": "aws", "region": "us-east-1" } } } } ``` ## chains.``.protocol **Description:** Connection protocol to use. **Optional:** Defaults to `"ethereum"` **Agents:** All **Type:** `Enum ("ethereum" | "fuel")` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.protocol ethereum --chains.ethereum.protocol ethereum ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_PROTOCOL="ethereum" export HYP_CHAINS_ARBITRUM_PROTOCOL="ethereum" ``` ```json As Config theme={null} { "chains": { "": { "protocol": "" }, "arbitrum": { "protocol": "ethereum" } } } ``` ## chains.``.rpcConsensusType **The consensus type currently only applies to EVM chains.** Connections to non-EVM chains only support a single RPC url. If more than one RPC url is specified in [rpcUrls](#chains-\-rpcurls), only the first one will be used. **Description:** How to communicate with the provider * `"single"` uses a basic http connection * `"fallback"` will try the first URL and then automatically "fall back" on a connection or other provider failure to the next provider; this should only retry calls which fail due to the provider and not the call itself such; an insufficient gas error for instance would not fall back. * `"quorum"` requires a majority of the URLs to agree with the exception of submitting transactions; it will automatically coordinate the "latest" block if not specified to reduce sync errors. **Requires:** `chains..protocol = "ethereum" | undefined` **Optional:** Defaults to `"fallback"` **Agents:** All **Type:** `Enum ("fallback", "single", "quorum")` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.rpcConsensusType single ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_RPCCONSENSUSTYPE="single" export HYP_CHAINS_ETHEREUM_RPCCONSENSUSTYPE="single" ``` ```json As Config theme={null} { "chains": { "": { "rpcConsensusType": "single" }, "ethereum": { "rpcConsensusType": "single" } } } ``` ## chains.``.customRpcUrls Connections to non-EVM chains only support a single RPC url. If more than one RPC url is specified, only the first one will be used. **Description:** Comma-separated URLs to connect the provider to. The difference between `customRpcUrls` and [rpcUrls](#chains-\-rpcurls) is that `customRpcUrls` allows for more user friendly inputs from the CLI or environment variables (comma-separated vs array). **Type:** `string` (comma separated list of urls without spaces) ```bash As Arg theme={null} --chains.${CHAIN_NAME}.customrpcurls "$CONNECTION_URLS" --chains.ethereum.customrpcurls "http://127.0.0.1:8545,http://127.0.0.1:8546,http://127.0.0.1:8547" ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_CUSTOMRPCURLS="$CONNECTION_URLS" export HYP_CHAINS_ETHEREUM_CUSTOMRPCURLS="http://127.0.0.1:8545,http://127.0.0.1:8546,http://127.0.0.1:8547" ``` ```json As Config theme={null} { "chains": { "ethereum": { "customRpcUrls": "http://127.0.0.1:8545,http://127.0.0.1:8546" } } } ``` ## chains.``.rpcUrls Connections to non-EVM chains only support a single RPC url. If more than one RPC url is specified, only the first one will be used. **Description:** URLs to connect the provider to. The first one is initially used, and on failure the other ones are tried. See [rpcConsensusType](#chains-\-rpcconsensustypee) for more information. **Requires:** ``` (chains..protocol = "ethereum" | undefined) AND (chains..connection.type = "fallback" | "quorum") OR chains..protocol = "cosmos" | "sealevel" | "fuel" ``` **Optional:** No (iff requirements are met) **Agents:** All **Type:** `string` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.rpcurls.0.https "$CONNECTION_URL_0" --chains.${CHAIN_NAME}.rpcurls.1.https "$CONNECTION_URL_1" --chains.${CHAIN_NAME}.rpcurls.2.https "$CONNECTION_URL_2" --chains.ethereum.rpcurls.0.https "http://127.0.0.1:8545" --chains.ethereum.rpcurls.1.https "http://127.0.0.1:8546" --chains.ethereum.rpcurls.2.https "http://127.0.0.1:8547" ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_RPCURLS_0_HTTPS="$CONNECTION_URL_0" export HYP_CHAINS_${CHAIN_NAME}_RPCURLS_1_HTTPS="$CONNECTION_URL_1" export HYP_CHAINS_${CHAIN_NAME}_RPCURLS_2_HTTPS="$CONNECTION_URL_2" export HYP_CHAINS_ETHEREUM_RPCURLS_0_HTTPS="http://127.0.0.1:8545" export HYP_CHAINS_ETHEREUM_RPCURLS_1_HTTPS="http://127.0.0.1:8546" export HYP_CHAINS_ETHEREUM_RPCURLS_2_HTTPS="http://127.0.0.1:8547" ``` ```json As Config theme={null} { "chains": { "": { "rpcUrls": [ { "http": "" }, { "http": "" } ] }, "ethereum": { "rpcUrls": [ { "http": "http://127.0.0.1:8545" }, { "http": "http://127.0.0.1:8546" } ] } } } ``` ## chains.``.customGrpcUrls Connections to Cosmos chains require **both** RPC and gRPC URLs. There is **no `rpcConsensusType` configuration** for Cosmos chains, and gRPC URLs always operate in **fallback mode**—if the first URL fails, the next one is used. **Description:** Comma-separated gRPC URLs used to connect to the provider. Similar to [`customRpcUrls`](#chains-\-customrpcurls). **Type:** `string` (comma-separated list of URLs without spaces) ```bash As Arg theme={null} --chains.${CHAIN_NAME}.customgrpcurls "$CONNECTION_URLS" --chains.cosmos.customgrpcurls "http://127.0.0.1:8545,http://127.0.0.1:8546,http://127.0.0.1:8547" ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_CUSTOMGRPCURLS="$CONNECTION_URLS" export HYP_CHAINS_COSMOS_CUSTOMGRPCURLS="http://127.0.0.1:8545,http://127.0.0.1:8546,http://127.0.0.1:8547" ``` ```json As Config theme={null} { "chains": { "cosmos": { "customRpcUrls": "", "customGrpcUrls": "http://127.0.0.1:8545,http://127.0.0.1:8546,http://127.0.0.1:8547" } } } ``` ## chains.``.index.from **Description:** Height at which to start indexing contracts. **Optional:** Defaults to `0` **Agents:** Relayer & Scraper **Type:** `Numeric (string | number)` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.index.from 0 --chains.ethereum.index.from 16271503 ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_INDEX_FROM=0 export HYP_CHAINS_ETHEREUM_INDEX_FROM=16271503 ``` ```json As Config theme={null} { "chains": { "": { "index": { "from": 0 } }, "ethereum": { "index": { "from": 16271503 } } } } ``` ## chains.``.index.chunk **Description:** Number of blocks to query at once when indexing contracts. Note that the configured providers must support whatever value is set. The default should work with nearly all providers. **Optional:** Defaults to `1999` **Agents:** Relayer & Scraper **Type:** `Numeric (string | number)` ```bash As Arg theme={null} --chains.${CHAIN_NAME}.index.chunk 1999 --chains.ethereum.index.chunk 1999 ``` ```bash As Env theme={null} export HYP_CHAINS_${CHAIN_NAME}_INDEX_CHUNK=1999 export HYP_CHAINS_ETHEREUM_INDEX_CHUNK=1999 ``` ```json As Config theme={null} { "chains": { "": { "index": { "chunk": 1999 } }, "ethereum": { "index": { "chunk": 1999 } } } } ``` ## defaultsigner Because each VM supports a different signer type, the default signer can only support a single VM type. For instance, if the default signer is a ECDSA one, it will only be able to sign on EVM chains. **Description:** The default signer that should be used for all chains which did not specify their own. **Optional:** Yes **Agents:** All **Type:** `SignerConf (Object)` ```bash As Arg theme={null} --defaultSigner.* ``` ```bash As Env theme={null} export HYP_DEFAULTSIGNER_*="...." ``` ```json As Config theme={null} { "defaultsigner": {} } ``` ## defaultsigner.type **Description:** The type of signer that is defined. A `HexKey` signer uses a private key, an `Aws` signer uses an AWS-based KMS, and `Node` assumes the local node will sign RPC calls. **Optional:** Yes; Defaults to `node` unless a `key` is specified in which case it defaults to `hexKey` **Agents:** All **Type:** `Enum ("hexKey" | "aws" | "cosmosKey" | "node")` ```bash As Arg theme={null} --defaultSigner.type hexKey ``` ```bash As Env theme={null} export HYP_DEFAULTSIGNER_TYPE="hexKey" ``` ```json As Config theme={null} { "defaultsigner": { "type": "hexKey" } } ``` ## defaultsigner.key **Description:** A hex key. The hex string of a private key. **Requires:** `defaultsigner.type = "hexKey" | undefined` **Optional:** No (iff requirements are met) **Agents:** All **Type:** `string` ```bash As Arg theme={null} --defaultSigner.key "8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61" ``` ```bash As Env theme={null} export HYP_DEFAULTSIGNER_KEY="8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61" ``` ```json As Config theme={null} { "defaultsigner": { "type": "hexKey", "key": "8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61" } } ``` ## defaultsigner.id **Description:** The UUID identifying the AWS KMS key **Requires:** `defaultsigner.type = "aws"` **Optional:** No (iff requirements are met) **Agents:** All **Type:** `string` ```bash As Arg theme={null} --defaultSigner.id "alias/validator-signer-ethereum" ``` ```bash As Env theme={null} export HYP_DEFAULTSIGNER_ID="alias/validator-signer-ethereum" ``` ```json As Config theme={null} { "defaultsigner": { "type": "aws", "id": "alias/validator-signer-ethereum" } } ``` ## defaultsigner.region **Description:** The AWS region **Requires:** `defaultsigner.type = "aws"` **Optional:** No (iff requirements are met) **Agents:** All **Type:** `string` ```bash As Arg theme={null} --defaultSigner.region us-east-1 ``` ```bash As Env theme={null} export HYP_DEFAULTSIGNER_REGION="us-east-1" ``` ```json As Config theme={null} { "defaultsigner": { "type": "aws", "region": "us-east-1" } } ``` ## metricsport **Description:** Port to expose prometheus metrics on **Optional:** Defaults to `9090` **Agents:** All **Type:** `Numeric (string | number)` ```bash As Arg theme={null} --metrics-port 9090 ``` ```bash As Env theme={null} export HYP_METRICSPORT=9090 ``` ```json As Config theme={null} { "metrics": 9090 } ``` ## log.format **Description:** Configuration for the log module. This controls logging. **Optional:** Defaults to `pretty` **Agents:** All **Type:** `Enum ("pretty" | "json" | "full" | "compact")` ```bash As Arg theme={null} --log.format pretty ``` ```bash As Env theme={null} export HYP_LOG_FORMAT="pretty" ``` ```json As Config theme={null} { "log": { "format": "pretty" } } ``` ## log.level **Description:** Configuration for the log module. This controls logging. For full verbosity (including that of dependencies), use `dependencyTrace`. **Optional:** Defaults to `info` **Agents:** All **Type:** `Enum ("dependencyTrace" | "trace" | "debug" | "info" | "warn" | "error" | "off")` ```bash As Arg theme={null} --log.level info ``` ```bash As Env theme={null} export HYP_LOG_LEVEL="info" ``` ```json As Config theme={null} { "log": { "level": "info" } } ``` ## originchainname **Description:** Name of the chain a validator should validate for and name of the chain a relayer should relayer messages from. **Deprecated for Relayer, use** [#relaychains](#relaychains) **instead.** **Optional:** No - Validators; Yes - Relayer **Agents:** Validator & Relayer **Type:** `string` ```bash As Arg theme={null} --originChainName ethereum ``` ```bash As Env theme={null} export HYP_ORIGINCHAINNAME="ethereum" ``` ```json As Config theme={null} { "originchainname": "ethereum" } ``` ## validator **Description:** The signer that should be used by the validator. **Optional:** Yes **Agents:** All **Type:** `SignerConf (Object)` ```bash As Arg theme={null} --validator.* ``` ```bash As Env theme={null} export HYP_VALIDATOR_*="...." ``` ```json As Config theme={null} { "validator": {} } ``` ## validator.type **Description:** The type of EVM signer that is defined. Note that regardless of the VM the validator is operating on, checkpoints are always signed using the EVM ECDSA curve. A `HexKey` signer uses a private key, an `Aws` signer uses an AWS based KMS, and `Node` assumes the local node will sign RPC calls. **Optional:** Yes; Defaults to `node` unless a `key` is specified in which case it defaults to `hexKey` **Agents:** All **Type:** `Enum ("hexKey" | "aws" | "node")` ```bash As Arg theme={null} --validator.type hexKey ``` ```bash As Env theme={null} export HYP_VALIDATOR_TYPE="hexKey" ``` ```json As Config theme={null} { "validator": { "type": "hexKey" } } ``` ## validator.key **Description:** A hex key. The hex string of a private key. **Requires:** `validator.type = "hexKey" | undefined` **Optional:** No (iff requirements are met) **Agents:** All **Type:** `string` ```bash As Arg theme={null} --validator.key 8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61 ``` ```bash As Env theme={null} export HYP_VALIDATOR_KEY="8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61" ``` ```json As Config theme={null} { "validator": { "type": "hexKey", "key": "8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61" } } ``` ## validator.id **Description:** The UUID identifying the AWS KMS key **Requires:** `validator.type = "aws"` **Optional:** No (iff requirements are met) **Agents:** All **Type:** `string` ```bash As Arg theme={null} --validator.id "alias/validator-signer-ethereum" ``` ```bash As Env theme={null} export HYP_VALIDATOR_ID="alias/validator-signer-ethereum" ``` ```json As Config theme={null} { "validator": { "type": "aws", "id": "alias/validator-signer-ethereum" } } ``` ## validator.region **Description:** The AWS region **Requires:** `validator.type = "aws"` **Optional:** No (iff requirements are met) **Agents:** All **Type:** `string` ```bash As Arg theme={null} --validator.region us-east-1 ``` ```bash As Env theme={null} export HYP_VALIDATOR_REGION="us-east-1" ``` ```json As Config theme={null} { "validator": { "type": "aws", "region": "us-east-1" } } ``` ## checkpointsyncer.type **Description:** Defines the method of syncing checkpoints **Optional:** No **Agents:** Validator **Type:** `Enum ("localStorage" | "s3")` ```bash As Arg theme={null} --checkpointSyncer.type localStorage ``` ```bash As Env theme={null} export HYP_CHECKPOINTSYNCER_TYPE="localStorage" ``` ```json As Config theme={null} { "checkpointsyncer": { "type": "localStorage" } } ``` ## checkpointsyncer.path **Description:** Path on the local disk of a local storage type checkpoint syncer configuration. **Requires:** `checkpointsyncer.type = "localStorage"` **Optional:** No (iff conditions are met) **Agents:** Validator **Type:** `string` ```bash As Arg theme={null} --checkpointSyncer.path "/tmp/syncer" ``` ```bash As Env theme={null} export HYP_CHECKPOINTSYNCER_PATH="/tmp/syncer" ``` ```json As Config theme={null} { "checkpointsyncer": { "type": "localStorage", "path": "/tmp/syncer" } } ``` ## checkpointsyncer.bucket **Description:** S3 bucket name **Requires:** `checkpointsyncer.type = "s3"` **Optional:** No (iff conditions are met) **Agents:** Validator **Type:** `string` ```bash As Arg theme={null} --checkpointSyncer.bucket signatures-ethereum ``` ```bash As Env theme={null} export HYP_CHECKPOINTSYNCER_BUCKET="signatures-ethereum" ``` ```json As Config theme={null} { "checkpointsyncer": { "type": "s3", "bucket": "signatures-ethereum" } } ``` ## checkpointsyncer.folder **Description:** Folder in the S3 bucket **Requires:** `checkpointsyncer.type = "s3"` **Optional:** No (iff conditions are met) **Agents:** Validator **Type:** `string` ```bash As Arg theme={null} --checkpointSyncer.folder signatures-ethereum ``` ```bash As Env theme={null} export HYP_CHECKPOINTSYNCER_FOLDER="signatures-ethereum" ``` ```json As Config theme={null} { "checkpointsyncer": { "type": "s3", "folder": "signatures-ethereum" } } ``` ## checkpointsyncer.region **Description:** S3 bucket region **Requires:** `checkpointsyncer.type = "s3"` **Optional:** No (iff conditions are met) **Agents:** Validator **Type:** `string` ```bash As Arg theme={null} --checkpointSyncer.region us-east-1 ``` ```bash As Env theme={null} export HYP_CHECKPOINTSYNCER_REGION="us-east-1" ``` ```json As Config theme={null} { "checkpointsyncer": { "type": "s3", "region": "us-east-1" } } ``` ## interval **Description:** How frequently the validator should check for new checkpoints in seconds? See also [latencies](/docs/reference/addresses/validators/latencies). **Optional:** No **Agents:** Validator **Type:** `Numeric (string | number)` ```bash As Arg theme={null} --interval 30 ``` ```bash As Env theme={null} export HYP_INTERVAL=30 ``` ```json As Config theme={null} { "interval": 30 } ``` ## db **Description:** This is a local filesystem path to where the agents store relevant data on disk. **This must be unique per agent!** Multiple agents must have different paths. The path is relative to the current working directory if it does not start with a system defined root path such as `/` on unix. When using docker images, ensure that this folder gets persisted across runs. For the scraper, this is the connection string to a postgresql database. **Optional:** For validators and relayer it is optional and defaults to a path in the current working directory which includes the `originchainname`. For the scraper it is required. **Agents:** All **Type:** `string` ```bash As Arg theme={null} # Validator --db "/tmp/hyp/validator/ethereum-cache" # Relayer --db "/tmp/hyp/relayer/ethereum-cache" # Scraper --db "postgresql://postgres:password@localhost:5432/dbname" ``` ```bash As Env theme={null} # Validator export HYP_DB="/tmp/hyp/validator/ethereum-cache" # Relayer export HYP_DB="/tmp/hyp/relayer/ethereum-cache" # Scraper export HYP_DB="postgresql://postgres:password@localhost:5432/dbname" ``` ```json As Config theme={null} # For the validator: { "db": "/tmp/hyp/validator/ethereum-cache" } # For the relayer: { "db": "/tmp/hyp/relayer/ethereum-cache" } # For the scraper: { "db": "postgresql://postgres:password@localhost:5432/dbname" } ``` ## relaychains **Description:** List of chains to deliver messages between. **Optional:** No **Agents:** Relayer **Type:** `string` (comma separated list) ```bash As Arg theme={null} --relayChains "arbitrum,ethereum,bsc" ``` ```bash As Env theme={null} export HYP_RELAYCHAINS="arbitrum,ethereum,bsc" ``` ```json As Config theme={null} { "relaychains": "arbitrum,ethereum,bsc" } ``` ## gaspaymentenforcement **Description:** JSON stringified array of gas payment enforcement configurations sorted by highest priority first. The last policy should be a catch-all and handle any messages that did not match a previous policy. **Optional:** Defaults to no enforcement (`[{"type": "none"}]`) **Agents:** Relayer **Type:** `JSON (string)` ```typescript Type Definition theme={null} type gaspaymentenforcement = Array; type GasPaymentEnforcementPolicy = | // fields specific to each type... // No requirements - all messages are processed regardless of gas payment ({ type: "none"; } & { // Messages that have paid a minimum amount will be processed type: "minimum"; payment: U256; } & { type: "onChainFeeQuoting"; gasfraction?: GasFraction }) // to on-chain fee quoting. `gasfraction` defaults to "1 / 2". // Required amount of gas on the foreign chain has been paid according | { // all types have the following fields... // If a message matches, this policy will be used. // If no matching list is specified, all messages will match. matchingList?: MatchingList; }; // A list of matching rules. A message matches if any of the list // elements matches the message. type MatchingList = Array; // Matches a message if any of the provided values matches. interface MatchingListElement { originDomain?: NumericFilter; senderAddress?: HashFilter; destinationDomain?: NumericFilter; recipientAddress?: HashFilter; } type NumericFilter = Wildcard | U32 | Array; type HashFilter = Wildcard | H256 | Array; // 32-bit unsigned integer type U32 = number | string; // 256-bit unsigned integer; Note: `number` type has limited precision. type U256 = string | number; // 256-bit hash (can also be less) encoded as hex type H256 = string; // Matches anything type Wildcard = "\*"; // A numeric string in the form `{numerator} / {denominator}`, e.g. "1 / 2" type GasFraction = string; ``` ```bash As Arg theme={null} --gasPaymentEnforcement '[ {"type": "none", "matchingList": [{"senderAddress": "0xa441b15fe9a3cf56661190a0b93b9dec7d041272"}]}, {"type": "minimum", "payment": 100000} ]' ``` ```bash As Env theme={null} export HYP_GASPAYMENTENFORCEMENT='[ {"type": "none", "matchingList": [{"senderAddress": "0xa441b15fe9a3cf56661190a0b93b9dec7d041272"}]}, {"type": "minimum", "payment": 100000} ]' ``` ```json As Config theme={null} { "gaspaymentenforcement": "[{\"type\": \"none\", \"matchingList\": [{\"senderAddress\": \"0xa441b15fe9a3cf56661190a0b93b9dec7d041272\"}]}, {\"type\": \"minimum\", \"payment\": 100000}]" } ``` ## whitelist **Description:** A matching list to define what messages should be allowed. Any messages which do not match this list will not be relayed. If no whitelist is supplied all messages will be allowed. See also [message filtering](/docs/operate/relayer/message-filtering) **Optional:** Yes **Agents:** Relayer **Type:** `JSON (string)` ```typescript Type Definition theme={null} // A list of matching rules. A message matches if any of the list // elements matches the message. type MatchingList = Array; // Matches a message if any of the provided values matches. interface MatchingListElement { originDomain?: NumericFilter senderAddress?: HashFilter destinationDomain?: NumericFilter recipientAddress?: HashFilter } type NumericFilter = Wildcard | U32 | Array; type HashFilter = Wildcard | H256 | Array; // 32-bit unsigned integer type U32 = number | string; // 256-bit hash (can also be less) encoded as hex type H256 = string; // Matches anything type Wildcard = "\*"; ``` ```bash As Arg theme={null} --whitelist '[ {"senderAddress": "0xa441b15fe9a3cf56661190a0b93b9dec7d041272", "originDomain": [1, 42]}, {"destinationDomain": 1} ]' ``` ```bash As Env theme={null} export HYP_WHITELIST='[ {"senderAddress": "0xa441b15fe9a3cf56661190a0b93b9dec7d041272", "originDomain": [1, 42]}, {"destinationDomain": 1} ]' ``` ```json As Config theme={null} { "whitelist": "[{\"senderAddress\": \"0xa441b15fe9a3cf56661190a0b93b9dec7d041272\", \"originDomain\": [1, 42]}, {\"destinationDomain\": 1}]" } ``` ## blacklist **Description:** A matching list to define what messages should be ignored. Any messages which match this list will not be relayed. If no blacklist is supplied all messages will be allowed. See also [message filtering](/docs/operate/relayer/message-filtering) **Optional:** Yes **Agents:** Relayer **Type:** `JSON (string)` ```typescript Type Definition theme={null} type blacklist = MatchingList | undefined; // A list of matching rules. A message matches if any of the list // elements matches the message. type MatchingList = Array; // Matches a message if any of the provided values matches. interface MatchingListElement { originDomain?: NumericFilter; senderAddress?: HashFilter; destinationDomain?: NumericFilter; recipientAddress?: HashFilter; } type NumericFilter = Wildcard | U32 | Array; type HashFilter = Wildcard | H256 | Array; // 32-bit unsigned integer type U32 = number | string; // 256-bit hash (can also be less) encoded as hex type H256 = string; // Matches anything type Wildcard = "\*"; ``` ```bash As Arg theme={null} --blacklist '[ {"senderAddress": "0xa441b15fe9a3cf56661190a0b93b9dec7d041272", "originDomain": [1, 42]}, {"destinationDomain": 1} ]' ``` ```bash As Env theme={null} export HYP_BLACKLIST='[ {"senderAddress": "0xa441b15fe9a3cf56661190a0b93b9dec7d041272", "originDomain": [1, 42]}, {"destinationDomain": 1} ]' ``` ```json As Config theme={null} { "blacklist": "[{\"senderAddress\": \"0xa441b15fe9a3cf56661190a0b93b9dec7d041272\", \"originDomain\": [1, 42]}, {\"destinationDomain\": 1}]" } ``` ## transactiongaslimit **Description:** The max allowable gas to relay a transaction. **Optional:** Defaults to no limit **Agents:** Relayer **Type:** `Numeric (string | number)` ```bash As Arg theme={null} --transactionGasLimit 250000000 ``` ```bash As Env theme={null} export HYP_TRANSACTIONGASLIMIT="250000000" ``` ```json As Config theme={null} { "transactiongaslimit": "250000000" } ``` ## skiptransactiongaslimitfor **Description:** List of domain ids to skip applying the `transactiongaslimit` for. **Optional:** Defaults to using the `transactiongaslimit` for all domains **Agents:** Relayer **Type:** `string` (comma separated list of domain ids) ```bash As Arg theme={null} --skipTransactionGasLimitFor "43114,10,42220" ``` ```bash As Env theme={null} export HYP_SKIPTRANSACTIONGASLIMITFOR="43114,10,42220" ``` ```json As Config theme={null} { "skiptransactiongaslimitfor": "43114,10,42220" } ``` ## allowlocalcheckpointsyncers **Description:** Whether to allow local `checkpointsyncer` types, if `false` it will ignore them. **Optional:** Defaults to `false` **Agents:** Relayer **Type:** `boolean` ```bash As Arg theme={null} --allowLocalCheckpointSyncers false ``` ```bash As Env theme={null} export HYP_ALLOWLOCALCHECKPOINTSYNCERS=false ``` ```json As Config theme={null} { "allowlocalcheckpointsyncers": false } ``` ## maxmessageretries **Description:** The maximum number of retries to attempt before dropping a message from the relayer queues. This prevents messages from being retried indefinitely. **Optional:** Defaults to a system default value of 66 **Agents:** Relayer **Type:** `Numeric (string | number)` ```bash As Arg theme={null} --maxMessageRetries 120 ``` ```bash As Env theme={null} export HYP_MAXMESSAGERETRIES="120" ``` ```json As Config theme={null} { "maxmessageretries": "120" } ``` ## AWS\_ACCESS\_KEY\_ID **Description:** (Env only) The access key ID of your validator's AWS IAM user. **Optional**: Required if any signer configuration uses `aws` **Agents:** Relayer & Validator **Type:** `string` ```bash As Arg theme={null} # Not supported as an argument ``` ```bash As Env theme={null} export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE" ``` ```json As Config theme={null} # Not supported in configuration files ``` ## AWS\_SECRET\_ACCESS\_KEY **Description:** (Env only) The secret access key of your validator's AWS IAM user. **Optional:** Required if any signer configuration uses `aws` **Agents:** Relayer & Validator **Type:** `string` ```bash As Arg theme={null} # Not supported as an argument ``` ```bash As Env theme={null} export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" ``` ```json As Config theme={null} # Not supported in configuration files ``` # AVS Operator Guide Source: https://docs.hyperlane.xyz/docs/operate/guides/avs-operator-guide ## Overview Hyperlane validators are light offchain agents responsible for security - they observe messages on an origin chain's [Mailbox](/docs/protocol/core/mailbox) and if needed sign a merkle root that attests the current state of the mailbox. This signature is stored and made publicly available (e.g. in an S3 bucket), which is then used by the offchain Relayer and Interchain Security Modules onchain. Validators are *not* networked together and do not need to reach consensus. As you follow this guide, you'll run a Hyperlane validator on [**any of the chains**](https://github.com/hyperlane-xyz/hyperlane-registry/tree/main/chains) the protocol is live on, including Arbitrum, Optimism, BSC, Base, Blast, Linea, Mode, and Polygon. After that you'll link your validator with your EigenLayer Operator by interacting with the AVS contract on Ethereum Mainnet or Holesky. This process, like the entire Hyperlane framework, is open source and permissionless - no whitelisting or staking minimums needed. ## 1. Install CLI Install the latest version of the `@hyperlane-xyz/cli` package with `npm install -g @hyperlane-xyz/cli`. Detailed CLI install instructions are available [here](/docs/reference/developer-tools/cli). ## 2. Run the validator Operators that want to quickly deploy a production ready environment using Docker Compose and AWS may wish to use the [Docker Compose quickstart guide](/docs/operate/guides/docker-quickstart). Follow the validator guide [here](/docs/operate/validators/run-validators) with the AWS setup to run the validator on [any chain](https://github.com/hyperlane-xyz/hyperlane-registry/tree/main/chains) within the Hyperlane network. You can also easily generalize for other storage providers like [GCP](https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/3156) and Azure, or other key management solutions. Ensure that your KMS key has funds on that chain to announce itself. ### Monitoring You can monitor EigenLayer specific endpoints via the `--metrics` port you specified in the validator configuration. Read more about the example endpoints and what should be expected [here](https://docs.eigenlayer.xyz/eigenlayer/avs-guides/spec/api/). The supported endpoints are: | Endpoint | Description | | ---------------------------- | ------------------------------------------ | | **GET /eigen/node** | for node info | | **GET /eigen/node/health** | for node health | | **GET /eigen/node/services** | for a list of services the node is running | You'll need the validator address (address of the signing key) for the next step. ## 3. Set up keys There is a distinction between the operator key and the AVS signing key. The operator key is meant for just interacting with the AVS contracts whereas the AVS signing key is used for active operations, which in our case will be signing checkpoints with a Hyperlane validator. ## 4. Register your operator First, make sure you're registered with your operator key [as an EigenLayer operator](https://docs.eigenlayer.xyz/eigenlayer/operator-guides/operator-installation#operator-configuration-and-registration) on Mainnet or Holesky. You'll only need the ECDSA key. Next, to register your operator to Hyperlane AVS, you can use the Hyperlane CLI. Register your operator key (generated via the EigenLayer CLI) by creating an ECDSA signature and submitting it along with the AVS signing key, which is your Hyperlane validator address from above (not a private key). ```bash theme={null} hyperlane avs register --operatorKeyPath \ --chain \ --avsSigningKeyAddress ``` The `AVS_NETWORK` is the network you're registering on, which can be `Ethereum` or `Holesky`. Your AVS signing key can be reused across multiple validators and doesn't require additional registration for each. If you use different AVS signing keys for each validator, you'll need to register each as an operator. ### Confirming registration To confirm you are registered on mainnet, run `hyperlane avs check --chain ethereum --operatorAddress ` using the Hyperlane CLI and see if your validator address is there. This query may take a few minutes to complete. Additionally, you can search your address under the `operatorRegistry` function [on Etherscan](https://etherscan.io/address/0x272CF0BB70D3B4f79414E0823B426d2EaFd48910#readProxyContract#F12) or check on EigenLayer's UI for [Ethereum](https://app.eigenlayer.xyz/avs/0xe8e59c6c8b56f2c178f63bcfc4ce5e5e2359c8fc) or [Holesky](https://holesky.eigenlayer.xyz/avs/0xc76e477437065093d353b7d56c81ff54d167b0ab). Congrats on registering with the Hyperlane AVS! Now any Hyperlane message receiver can leverage your validator signatures, helping secure rollup interop. ## Learn more * You can read more about the AVS protocol design [here](/docs/protocol/ISM/economic-security/hyperlane-avs). # Deploy with Terraform Source: https://docs.hyperlane.xyz/docs/operate/guides/deploy-with-terraform For those more familiar with deploying to AWS through infrastructure-as-code tools such as Terraform, we provide an [**example configuration in GitHub**](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/rust/main/terraform) designed to set up the necessary infrastructure for a Hyperlane Validator on AWS. It automates the creation of resources such as ECS clusters, VPCs, subnets, and security groups required for running a Validator agent. The configuration provided is intended to only be an *example* of running a Validator for a core supported network. You may have to modify the Validator module to support more advanced configurations. It is recommended to test thoroughly before using this setup in a production environment. ## Overview The provided terraform has a few key parts: * IAM/KMS module: automatically completes [Agent Keys](/docs/operate/set-up-agent-keys) configuration for you. * S3 module: automatically completes [AWS Signatures Bucket](/docs/operate/validators/validator-signatures-aws) configuration for you. * EFS module: sets up a persistent volume that can be mounted to the Validator. * Validator module: uses the above modules to run an instance of a Validator. * `global.tf`: top-level networking configuration for a cluster that Validators can run in. * `main.tf`: configures Validators for deployment. The diagram below shows how it fits together. ```mermaid theme={null} graph LR subgraph VPC_Network ["VPC Network"] Subnet -- Protected by --> SG[AWS Security Group] subgraph SG ["AWS Security Group"] NATG[AWS NAT Gateway] IGW[AWS Internet Gateway] end end subgraph ECS_Validator ["Validator Module"] ECSTask[ECS Task: Validator] -- Executes in --> Subnet end subgraph S3_Subgraph ["S3 Module"] S3Bucket[AWS S3 Bucket] -- Accessed by --> ECSTask ECSTask -- Writes to --> S3Bucket[Validator Signatures] end subgraph EFS_Subgraph ["EFS Module"] EFS[AWS EFS] -- Mounted on --> ECSTask end subgraph IAM_KMS ["IAM / KMS Module"] IAMUser[Validator IAM User] KMSKey[KMS Key] end Internet -- Accessing Metrics --> IGW NATG -- RPC Calls --> Internet %% Additional Interconnections ECSTask -- Signs with --> KMSKey ECSTask -- Perms from --> IAMUser ``` ## Usage As a prerequisite, you need to have Terraform installed and the AWS CLI configured with your credentials. To initialize the terraform state: ```bash theme={null} terraform init ``` To generate the plan of infrastructure changes: ```bash theme={null} terraform plan ``` To preview and apply the infrastructure changes: ```bash theme={null} terraform apply ``` To list the outputs such as KMS, IAM or S3 information, you will have to parse the JSON output: ```bash theme={null} terraform output -json ``` ## Modules Several modules exist so you can choose which parts of the Validator setup you would like managed by terraform. ### IAM / KMS The `iam_kms` module creates an IAM user and a KMS key for secure signing operations. It also sets up IAM policies and attachments to grant the necessary permissions for using the KMS key and other AWS services, such as S3, EFS and ECS later on. ### S3 The `s3` module creates an S3 bucket for storing Validator-related data, such as signatures. It also sets bucket policies to manage access and permissions, including public access restrictions and versioning. ### EFS The `efs` module defines an EFS file system and access point, allowing the Validator application to store and access data on EFS. It also sets up a mount target for connecting the EFS file system to the network. This module is only required when using the `validator` module. ### Validator The `validator` module uses all of the above to integrate the EFS, IAM/KMS, and S3 configurations. In addition to: * Creating a new IAM user and relevant roles to run a Validator. * Creating an S3 bucket that a Validator can write signatures to. * Creating an EFS volume to persist data in the service. This module also: * Defines an ECS task definition for running the Validator application, including container definitions, volume configurations, and logging. * Creates an ECS service to manage the deployment and scaling of the Validator tasks. ## Main Configuration The root level configuration sets up a VPC, subnets, internet gateway, NAT gateway, route tables, and security groups for network infrastructure. It also provides example usage of the `validator` module. ```hcl theme={null} module "your_validator_name" { source = "./modules/validator" validator_name = "your-validator-name" origin_chain_name = "originChainName" aws_region = var.aws_region validator_cluster_id = aws_ecs_cluster.validator_cluster.id validator_subnet_id = aws_subnet.validator_subnet.id validator_sg_id = aws_security_group.validator_sg.id validator_nat_gateway_id = aws_nat_gateway.validator_nat_gateway.id # Disabling the Validator task allows you to set up all the required infrastructure # without running the actual Validator yet. This is useful when setting up a Validator for # the first time, so that you can find out the Validator's address and fund it before it # performs the announcement transaction. # validator_task_disabled = true } ``` ### Outputs The root-level `outputs.tf` passes forward all outputs from the Validators configured in `main.tf`. **You will have to update this as you add, modify or remove Validators.** ### Example architecture The diagram below shows how the Validator ECS cluster fits into the top-level network infrastructure. ```mermaid theme={null} graph TD subgraph VPC_Network ["VPC Network"] VPC[AWS VPC] Public_Subnet[AWS Public Subnet] Private_Subnet[AWS Private Subnet] VPC -- Connected to --> IGW[AWS Internet Gateway] VPC -- Contains --> SG[AWS Security Group] Public_Subnet -- Internet Access via --> IGW Private_Subnet -- Internet Access via NAT --> NAT_Gateway[AWS NAT Gateway] NAT_Gateway -- Utilizes --> EIP[AWS Elastic IP] NAT_Gateway -- Located in --> Public_Subnet subgraph Routing ["Routing"] Public_Subnet -- Associates --> Public_Route_Table[AWS Public Route Table] Public_Route_Table -- Routes Internet Traffic --> IGW Private_Subnet -- Associates --> Private_Route_Table[AWS Private Route Table] Private_Route_Table -- Routes Traffic To --> NAT_Gateway end end subgraph ECS_Infrastructure ["ECS Infrastructure"] VPC -- Hosts --> ECS_Cluster[AWS ECS Cluster] SG -- Secures --> ECS_Cluster end %% Additional Details SG -- Secures --> Public_Subnet SG -- Secures --> Private_Subnet %% Internet Node Internet[Internet] IGW -- Connects to --> Internet EIP -- Connects to --> Internet ``` ## Known issues ### PI configuration It is non-trivial to set custom configuration values for PI chains, such as ones you've deployed Hyperlane to yourself. Currently you may have to just pass a long list of environment variables or command line arguments. ### Individual agent logs Currently all agents log to the same log group - `DefaultLogGroup`. To separate them per agent, you may have to adjust the log group name and update the agent's log policy with the new group name. ### Relayer module The docker image supports running both types of agents. Therefore, if you choose to do so, you can use the Validator module as a starting point for a new Relayer module. # Quickstart with Docker Compose and AWS Source: https://docs.hyperlane.xyz/docs/operate/guides/docker-quickstart Using Docker Compose provides a structured way to manage validator deployments while maintaining the flexibility of raw Docker. You can find the full specification of the format in the [Docker docs](https://docs.Docker.com/compose/compose-file/). ## 1. Setup validator key Follow the guide [here](/docs/operate/set-up-agent-keys#2-aws-kms) for creating agent keys with AWS KMS. ## 2. Create S3 bucket for signatures Follow the guide [here](/docs/operate/validators/validator-signatures-aws) for creating and configuring an S3 bucket for your validator to write signatures to. ## 3. (AVS Operators Only) Register with Hyperlane AVS[​](#3-avs-operators-only-register-with-hyperlane-avs "Direct link to 3. (AVS Operators Only) Register with Hyperlane AVS") If you are an AVS operator, follow the guide [here](/docs/operate/guides/avs-operator-guide#4-register-your-operator) to register with the Hyperlane AVS. ## 4. Setup validator environment ### Create config files In this example, we will run three chains. ```bash theme={null} mkdir -p ethereum/hyperlane_db optimism/hyperlane_db base/hyperlane_db && \ touch ethereum/config.json optimism/config.json base/config.json docker-compose.yml .env.ethereum .env.optimism .env.base ``` ### Edit each config.json You can read more about Agent Configs [here](/docs/operate/config/agent-config). | Parameter | Description | | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `customRpcUrls` | A comma-separated list of performant RPC endpoints for the chain you wish to support. We recommend using paid providers to avoid rate limiting. | | `chains.ethereum` | Should be changed to `chains.base` in the base/config.json, and `chains.optimism` in optimism/config.json. | | `signer.region` | Should be adjusted to your AWS region. | | `validator.region` | Should be adjusted to your AWS region. | | `signer.id` | Should be adjusted to your AWS KMS id you configured in step 3, prefixed with `alias/`. | | `validator.id` | Should be adjusted to your AWS KMS id you configured in step 3, prefixed with `alias/`. | | `originChainName` | Should be the chain you are validating. | | `checkpointSyncer.bucket` | Should reflect the name of the S3 bucket. | | `checkpointSyncer.folder` | The name of the folder the validator will use within the bucket. You may use the same bucket for multiple validators, but ensure each folder name is unique per validator. | | `reorgPeriod` | May be different for each chain. [Find the reorgPeriods](https://github.com/hyperlane-xyz/hyperlane-registry/tree/main/chains). | Here is an example agent config. ```json theme={null} { "chains": { "ethereum": { "customRpcUrls": "https://eth.llamarpc.com,https://rpc.mevblocker.io", "signer": { "region": "us-east-1", "type": "aws", "id": "alias/hyperlane-validator-signer" } } }, "originChainName": "ethereum", "db": "/mnt/hyperlane_db", "validator": { "id": "alias/hyperlane-validator", "type": "aws", "region": "us-east-1" }, "checkpointSyncer": { "bucket": "hyperlane-validator-signatures", "region": "us-east-1", "type": "s3", "folder": "ethereum" }, "reorgPeriod": 14, "metricsPort": "9090" } ``` ### Edit each .env file You should change the service name, AWS credentials for each chain. ```bash theme={null} AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= SERVICE_NAME=ethereum ``` ## 5. Configure Docker Compose (docker-compose.yml) ```yaml theme={null} x-common-attributes: &common-validator image: ghcr.io/hyperlane-xyz/hyperlane-agent:agents-v2.2.0 command: ./validator container_name: ${SERVICE_NAME}-validator environment: CONFIG_FILES: /config.json AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} volumes: - ./${SERVICE_NAME}/hyperlane_db:/mnt/hyperlane_db - ./${SERVICE_NAME}/config.json:/config.json restart: unless-stopped services: ethereum-validator: <<: *common-validator ports: - "9091:9090/tcp" optimism-validator: <<: *common-validator ports: - "9092:9090/tcp" base-validator: <<: *common-validator ports: - "9093:9090/tcp" ``` Your directory structure should look similar to this: ```bash theme={null} . ├── base │ ├── config.json │ └── hyperlane_db ├── docker-compose.yml ├── ethereum │ ├── config.json │ └── hyperlane_db ├── .env.base ├── .env.ethereum ├── .env.optimism └── optimism ├── config.json └── hyperlane_db ``` ## 6. Run the Hyperlane Validators Bring the containers up: Remember to fund your validator address so the validator can announce. ```bash theme={null} docker compose --env-file .env.ethereum up ethereum-validator -d docker compose --env-file .env.optimism up optimism-validator -d docker compose --env-file .env.base up base-validator -d ``` Ensure there are no errors: ```bash theme={null} docker logs -f ethereum-validator docker logs -f optimism-validator docker logs -f base-validator ``` **Running Multiple Validators**: Running multiple validators improves reliability and ensures message validation continues even if one fails. Learn more about the setup and requirements [here](/docs/operate/validators/run-validators#running-multiple-validators). # Agents Overview Source: https://docs.hyperlane.xyz/docs/operate/overview-agents The Hyperlane protocol decouples the transport layer from the security layer of cross-chain message passing. To run a deployment, it relies on offchain agents that observe onchain activity and carry out either the transport or security aspects of the protocol. 1. Hyperlane [Validators](#validators) are light offchain agents responsible for security - they observe messages on an origin chain's [Mailbox](/docs/protocol/core/mailbox) and if needed sign a merkle root that attests the current state of the mailbox. 2. [Relayers](#relayer) fulfil the message transport requirement of the protocol. They aggregate off-chain security metadata for the [`IInterchainSecurityModule` interface](/docs/protocol/ISM/modular-security) and deliver messages to their recipients. ## Validators [Validators](/docs/protocol/agents/validators) fulfil the security requirement of the protocol, as part of the [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM) or the [Hyperlane AVS](/docs/protocol/ISM/economic-security/hyperlane-avs), by attesting to the validity of [Mailbox](/docs/protocol/core/mailbox) messages and making their signatures available to a Relayer. This signature is stored and made publicly available (e.g. in an S3 bucket), which is then used by the offchain Relayer and Interchain Security Modules onchain. Validators are *not* networked together and do not need to reach consensus; they also do not regularly submit onchain transactions. Validators are configured with a number of block confirmations to wait before attesting to message finality. You can view the [latencies here](/docs/reference/addresses/validators/latencies) (Note that while this reflects the default ISM configuration, validators can configure their own confirmation thresholds based on their security requirements). If a reorg causes a different set or ordering of dispatched messages, the merkle tree that the validators are indexing will have an inconsistent root from the one already observed. When this happens, validators will halt signing new messages and write a reorg flag to their checkpoint storage (e.g., S3 bucket). Remediation is handled on a case-by-case basis. This is the agent that community operators run to help secure an origin chain, and it's the most important duty one can perform to help decentralize message passing on Hyperlane. **Note that just running a Validator doesn't mean it's actively contributing to securing messages:** a Multisig ISM on the destination chain must have enrolled the Validator's checkpoint-signing key, and that ISM must be used by message recipients. These agents are implemented in Rust and distributed as Docker images and binaries. Learn more about Validators [here](/docs/protocol/agents/validators) ## Relayer A Hyperlane [Relayer](/docs/protocol/agents/relayer) delivers interchain messages to their recipients. Relaying is permissionless, and one honest Relayer running between a chain pair is sufficient for ensuring liveness. Running a Relayer is: 1. much more operationally complex than a Validator. 2. not required for securing the network. 3. only recommended for permissionless deployments of Hyperlane. Hyperlane Relayers are configured to relay messages between one or more origin chains and destination chains. Every Hyperlane message involves two transactions: 1. To [`dispatch`](/docs/reference/messaging/send) and send a message on the origin chain. 2. To [`process`](/docs/reference/messaging/receive) and deliver the message on destination chain. A Relayer's job is to deliver the message on the destination chain. To fulfill this responsibility: * The Relayer keeps track of new messages as they come in on the origin chain. * It checks the [Interchain Security Module (ISM)](/docs/protocol/ISM/modular-security) specified by the recipient to gather the necessary metadata to secure the message. For example, it may retrieve Multisig ISM signatures from Validator checkpoint storage. * After assembling the security metadata, the Relayer then sends the message to the recipient on the destination chain. If the message delivery fails (e.g. due to a lack of liquidity to transfer out of a Hyperlane Warp Route contract), the Relayer retries the delivery with an exponential backoff mechanism until successful. A Relayer has no special permissions in Hyperlane. If Relayer keys are compromised, only the tokens held by those keys are at risk. Learn more about Relayers [here](/docs/protocol/agents/relayer). # Relayer HTTP API Source: https://docs.hyperlane.xyz/docs/operate/relayer/api The relayer provides a comprehensive HTTP API for inspecting database contents and managing operations. Each endpoint below includes an interactive playground where you can test the API directly. Make sure to update the server URL to match your relayer instance before testing endpoints. ## API Endpoints The following endpoints are available for interacting with the relayer: ### Messages API * [Get Messages](/docs/operate/relayer/api/messages/get-messages) - Query messages by domain and nonce range in the database * [Insert Messages](/docs/operate/relayer/api/messages/post-messages) - Add new messages to the database ### Operation Management * [List Operations](/docs/operate/relayer/api/operations/get-operations) - View pending messages in operation queues * [Retry Messages](/docs/operate/relayer/api/operations/post-message-retry) - Trigger retry of failed messages (resets retry count) * [Reprocess Message](/docs/operate/relayer/api/operations/post-reprocess-message) - Re-queue messages for processing on demand **Retry vs Reprocess**: Retry handles failed messages currently in the operation queues (memory), while reprocess re-queues messages from the database (storage) for processing - either already-delivered messages that need reprocessing or to allow external services to trigger message delivery instead of relying on queue backoff. ### Data Inspection * [Get Merkle Tree Insertions](/docs/operate/relayer/api/merkle-tree-insertions/get-merkle-tree-insertions) - Query merkle tree insertion in the database * [Insert Merkle Tree Insertions](/docs/operate/relayer/api/merkle-tree-insertions/post-merkle-tree-insertions) - Insert merkle tree insertion ### IGP Management * [List IGP Rules](/docs/operate/relayer/api/igp/get-igp-rules) - View current gas payment rules * [Add IGP Rule](/docs/operate/relayer/api/igp/post-igp-rules) - Create new gas payment rules * [Remove IGP Rules](/docs/operate/relayer/api/igp/delete-igp-rules) - Delete existing gas payment rules IGP endpoints are only available when gas enforcers are configured (`mod.rs:82-83`). ## Authentication Most endpoints do not require authentication for read operations. Write operations may require proper API keys or authentication depending on your relayer configuration. ## Base URL The default base URL for local development is: ``` http://localhost:9090 ``` Update this to match your relayer's actual endpoint when deployed. # Remove IGP Rule Source: https://docs.hyperlane.xyz/docs/operate/relayer/api/igp/delete-igp-rules DELETE http://localhost:9090/igp_rules/:index Remove existing Interchain Gas Payment (IGP) rules. This endpoint is only available when gas enforcers are configured. Index of the IGP rule to remove ```bash curl theme={null} curl -X DELETE "http://localhost:9090/igp_rules/1" ``` ```javascript JavaScript theme={null} const response = await fetch('http://localhost:9090/igp_rules/1', { method: 'DELETE', }); ``` ```python Python theme={null} import requests response = requests.delete('http://localhost:9090/igp_rules/1') ``` # List IGP Rules Source: https://docs.hyperlane.xyz/docs/operate/relayer/api/igp/get-igp-rules GET http://localhost:9090/igp_rules Get current Interchain Gas Payment (IGP) rules. This endpoint is only available when gas enforcers are configured. Policies Gas payment enforcement policy Matching list ```json Response theme={null} { "policies": { "subtensor": [ { "policy": "None", "matching_list": [] } ] } } ``` ```bash curl theme={null} curl "http://localhost:9090/igp_rules" ``` ```javascript JavaScript theme={null} const response = await fetch('http://localhost:9090/igp_rules'); const rules = await response.json(); ``` ```python Python theme={null} import requests response = requests.get('http://localhost:9090/igp_rules') rules = response.json() ``` # Add IGP Rule Source: https://docs.hyperlane.xyz/docs/operate/relayer/api/igp/post-igp-rules POST http://localhost:9090/igp_rules Add a new Interchain Gas Payment (IGP) rule. This endpoint is only available when gas enforcers are configured. Gas payment enforcement policy Matching list ```bash curl theme={null} curl -X POST "http://localhost:9090/igp_rules" \ -H "Content-Type: application/json" \ -d \ '{ "policy": "None", "matching_list": [ { "messageid": "0x03ae9509ddf792965c98729b43f0988d689ae17c79619e87e6c670f61eb1d4bc" } ] }' ``` ```javascript JavaScript theme={null} const response = await fetch('http://localhost:9090/igp_rules', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ policy: "None", matching_list: [ { messageid: "0x03ae9509ddf792965c98729b43f0988d689ae17c79619e87e6c670f61eb1d4bc" } ] }) }); ``` ```python Python theme={null} import requests response = requests.post('http://localhost:9090/igp_rules', json={ "policy": "None", "matching_list": [ { "messageid": "0x03ae9509ddf792965c98729b43f0988d689ae17c79619e87e6c670f61eb1d4bc" } ] }) ``` ```json Response theme={null} { "count": 4, "skipped": [] } ``` # Get Merkle Tree Insertions Source: https://docs.hyperlane.xyz/docs/operate/relayer/api/merkle-tree-insertions/get-merkle-tree-insertions GET http://localhost:9090/merkle_tree_insertions Gets merkle tree insertions in the relayetr database Chain domain ID (u32) Starting leaf index (inclusive) (u32) Ending leaf index (inclusive) (u32) Array of merkle tree insertion data Block number of merkle tree insertion Leaf index Message ID ```json Response theme={null} { "merkle_tree_insertions": [ { "insertion_block_number": null, "leaf_index": 100, "message_id": "0xabc..." } ] } ``` ```bash curl theme={null} curl localhost:9090/merkle_tree_insertions?domain_id=1&leaf_index_start=100&leaf_index_end=200 ``` ```javascript JavaScript theme={null} const response = await fetch('http://localhost:9090/merkle_tree_insertions'); const insertions = await response.json(); ``` ```python Python theme={null} import requests response = requests.get('http://localhost:9090/merkle_tree_insertions') insertions = response.json() ``` # Insert Merkle Tree Insertions Source: https://docs.hyperlane.xyz/docs/operate/relayer/api/merkle-tree-insertions/post-merkle-tree-insertions POST http://localhost:9090/merkle_tree_insertions Insert merkle tree insertion into the relayer database. Array of Merkle Tree Insertions Chain of merkle tree insertion Block number of merkle tree insertion Leaf index Message ID Number of merkle tree insertions inserted successfully List of merkle tree insertions that were skipped ```bash curl theme={null} curl "http://localhost:9090/merkle_tree_insertions" \ -H "Content-Type: application/json" \ -d \ '{ "merkle_tree_insertions": [ { "chain": 1, "insertion_block_number": 100000, "leaf_index": 5000, "message_id": "0x006ce24a2b5aff423febad6587a68541f2f997a8ba12f0d239748b68f4e0dde5" } ] }' ``` ```javascript JavaScript theme={null} const response = await fetch('http://localhost:9090/igp_rules', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ merkle_tree_insertions: [ { chain: 1, insertion_block_number: 100000, leaf_index: 5000, message_id: "0x006ce24a2b5aff423febad6587a68541f2f997a8ba12f0d239748b68f4e0dde5" } ] }) }); ``` ```python Python theme={null} import requests response = requests.post('http://localhost:9090/igp_rules', json={ "merkle_tree_insertions": [ { "chain": 1, "insertion_block_number": 100000, "leaf_index": 5000, "message_id": "0x006ce24a2b5aff423febad6587a68541f2f997a8ba12f0d239748b68f4e0dde5" } ] }) ``` ```json Response theme={null} { "count": 4, "skipped": [] } ``` # Get Messages Source: https://docs.hyperlane.xyz/docs/operate/relayer/api/messages/get-messages GET http://localhost:9090/messages Query messages for a specific domain within a nonce range. Chain domain ID (u32) Starting nonce (inclusive) (u32) Ending nonce (inclusive) (u32) Validation: Requires `nonce_end > nonce_start`, returns 400 if invalid Array of HyperlaneMessage objects Hyperlane version number Message nonce Message origin Message destination Message sender Message recipient Message body ```bash curl theme={null} curl "http://localhost:9090/messages?domain_id=1&nonce_start=100&nonce_end=200" ``` ```javascript JavaScript theme={null} const response = await fetch('http://localhost:9090/messages?domain_id=1&nonce_start=100&nonce_end=200'); const { messages } = await response.json(); ``` ```python Python theme={null} import requests response = requests.get('http://localhost:9090/messages', params={ 'domain_id': 1, 'nonce_start': 100, 'nonce_end': 200 }) messages = response.json() ``` ```json Response theme={null} { "messages": [ { "version": 3, "nonce": 1235, "origin": 1, "destination": 2, "sender": "0xabc...", "recipient": "0xdef...", "body": [0, 3, 0, 23, 43, 65] } ] } ``` # Insert Messages Source: https://docs.hyperlane.xyz/docs/operate/relayer/api/messages/post-messages POST http://localhost:9090/messages Insert new messages into the database. List of messages to insert The block number the message was dispatched at The message Number of messages inserted successfully List of messages that were skipped ```bash curl theme={null} curl -X POST "http://localhost:9090/messages" \ -H "Content-Type: application/json" \ -d \ '{ "messages": [ { "dispatched_block_number": 10000, "message": { "version": 3, "nonce": 1234, "origin": 1, "destination": 2, "sender": "0xabc...", "recipient": "0xdef...", "body": [0, 3, 0, 23, 43, 65] } }, { "dispatched_block_number": 10010, "message": { "version": 3, "nonce": 1235, "origin": 1, "destination": 2, "sender": "0xabc...", "recipient": "0xdef...", "body": [0, 3, 0, 23, 43, 65] } } ] }' ``` ```javascript JavaScript theme={null} const response = await fetch('http://localhost:9090/messages', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ messages: [ { dispatched_block_number: 10000, message: { version: 3, nonce: 1234, origin: 1, destination: 2, sender: "0xabc...", recipient: "0xdef...", body: [0, 3, 0, 23, 43, 65] } }, { dispatched_block_number: 10010, message: { version: 3, nonce: 1235, origin: 1, destination: 2, sender: "0xabc...", recipient: "0xdef...", body: [0, 3, 0, 23, 43, 65] } } ] }) }); ``` ```python Python theme={null} import requests response = requests.post('http://localhost:9090/messages', json={ "messages": [ { "dispatched_block_number": 10000, "message": { "version": 3, "nonce": 1234, "origin": 1, "destination": 2, "sender": "0xabc...", "recipient": "0xdef...", "body": [0, 3, 0, 23, 43, 65] } }, { "dispatched_block_number": 10010, "message": { "version": 3, "nonce": 1235, "origin": 1, "destination": 2, "sender": "0xabc...", "recipient": "0xdef...", "body": [0, 3, 0, 23, 43, 65] } } ] }) ``` ```json Response theme={null} { "count": 4, "skipped": [] } ``` # List Operations Source: https://docs.hyperlane.xyz/docs/operate/relayer/api/operations/get-operations GET http://localhost:9090/list_operations List pending messages in operation queues. Returns current messages being processed by the relayer. Array of pending operations ```json Response theme={null} [ { "message_id": "0x123...", "status": "pending", "attempts": 1, "last_attempt": "2024-01-01T12:00:00Z" } ] ``` ```bash curl theme={null} curl "http://localhost:9090/list_operations" ``` ```javascript JavaScript theme={null} const response = await fetch('http://localhost:9090/list_operations'); const operations = await response.json(); ``` ```python Python theme={null} import requests response = requests.get('http://localhost:9090/list_operations') operations = response.json() ``` # Retry Messages Source: https://docs.hyperlane.xyz/docs/operate/relayer/api/operations/post-message-retry POST http://localhost:9090/message_retry Trigger retry of failed messages matching specific patterns. This resets the retry count to 0 and re-queues the messages for processing. Specific message ID to retry (hex string) Message origin domain Message destination domain Sender address Recipient address Body regex UUID of the retry request How many pending operations were evaluated How many of the pending operations matched the retry request pattern ```bash curl theme={null} curl -X POST "http://localhost:9090/message_retry" \ -H "Content-Type: application/json" \ -d \ '[ { "messageid": "0x123..." } ]' ``` ```javascript JavaScript theme={null} const response = await fetch('http://localhost:9090/message_retry', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify([ { messageid: "0x123..." } ]) }); ``` ```python Python theme={null} import requests response = requests.post('http://localhost:9090/message_retry', json=[ { 'messageid': '0x123...' } ]) ``` # Reprocess Message Source: https://docs.hyperlane.xyz/docs/operate/relayer/api/operations/post-reprocess-message POST http://localhost:9090/reprocess_message Re-queue a message for processing on demand. This endpoint allows external services to trigger message delivery instead of relying on queue backoff, and can handle scenarios like blockchain network reorganizations or manual message processing. For purely on-demand processing without automatic retries, combine this endpoint with `max_message_retries := 0` in your relayer configuration. This ensures messages are only processed when explicitly triggered via this API. Domain/chain ID where the message originated Hex-encoded message identifier (H256) Whether the message was successfully re-queued for processing Details about the reprocessing operation ```bash curl theme={null} curl -X POST "http://localhost:9090/reprocess_message" \ -H "Content-Type: application/json" \ -d \ '{ "origin_id": 1399811149, "message_id": "0x9484bd5c635b17b28cb382249d7a6fe5ca15debfd4f824247c68d47badc5b7de" }' ``` ```javascript JavaScript theme={null} const response = await fetch('http://localhost:9090/reprocess_message', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ origin_id: 1399811149, message_id: "0x9484bd5c635b17b28cb382249d7a6fe5ca15debfd4f824247c68d47badc5b7de" }) }); ``` ```python Python theme={null} import requests response = requests.post('http://localhost:9090/reprocess_message', json={ 'origin_id': 1399811149, 'message_id': '0x9484bd5c635b17b28cb382249d7a6fe5ca15debfd4f824247c68d47badc5b7de' }) ``` ```json Success Response theme={null} { "success": true, "message": "Message re-queued for processing" } ``` ```json Error Response (400 Bad Request) theme={null} { "error": "Invalid message_id format" } ``` ```json Error Response (404 Not Found) theme={null} { "error": "Message or context not found" } ``` # Message Filtering Source: https://docs.hyperlane.xyz/docs/operate/relayer/message-filtering Configure which messages to relay, and which to ignore By default, the Relayer will attempt to deliver messages sent from its origin chain to any of the configured destination chains. Relayers may want to further filter the messages they attempt to deliver. For example, someone building an interchain app may want to run a Relayer that only delivers messages sent to that application. Similarly, some Relayers may wish to only relay messages to a subset of available chains. Relayers may **optionally** filter the messages they deliver by setting the `--whitelist` or `--blacklist` environment variables. See also the [configuration reference's](/docs/operate/config/config-reference) whitelist section. These configs are stringified JSON objects with the following format: ```typescript theme={null} // A list of matching rules. A message matches if any of the list // elements matches the message. type MatchingList = Array; // Matches a message if any of the provided values matches. interface ListElement { originDomain?: NumericFilter; senderAddress?: HashFilter; destinationDomain?: NumericFilter; recipientAddress?: HashFilter; } type NumericFilter = Wildcard | U32 | Array; type HashFilter = Wildcard | H256 | Array; // 32-bit unsigned integer type U32 = number | string; // 256-bit hash (can also be less) encoded as hextype H256 = string; // Matches anything type Wildcard = "*"; ``` Both the whitelist and blacklists have "any" semantics. In other words, the Relayer will deliver messages that match *any* of the whitelist filters, and ignore messages that match *any* of the blacklist filters. For example, the following config used as a whitelist will ensure the Relayer will relay any messages sent to Ethereum, any messages sent from address `0xca7f632e91B592178D83A70B404f398c0a51581F` to either Celo or Avalanche, and any messages sent to address `0xca7f632e91B592178D83A70B404f398c0a51581F` on Arbitrum or Optimism. ```json theme={null} [ { "senderAddress": "*", "destinationDomain": ["1"], "recipientAddress": "*" }, { "senderAddress": "0xca7f632e91B592178D83A70B404f398c0a51581F", "destinationDomain": ["42220", "43114"], "recipientAddress": "*" }, { "senderAddress": "*", "destinationDomain": ["42161", "420"], "recipientAddress": "0xca7f632e91B592178D83A70B404f398c0a51581F" } ] ``` A valid config may look like ```bash theme={null} --whitelist='[ {"senderAddress":"*", "destinationDomain":["1"], "recipientAddress":"*"}, {"senderAddress":"0xca7f632e91B592178D83A70B404f398c0a51581F", "destinationDomain":["42220","43114"], "recipientAddress":"*"}, {"senderAddress":"*", "destinationDomain":["42161","420"], "recipientAddress":"0xca7f632e91B592178D83A70B404f398c0a51581F"} ]' ``` The blacklist supersedes the whitelist, i.e. if a message matches both the whitelist *and* the blacklist, it will not be delivered. # Monitoring & Alerting Source: https://docs.hyperlane.xyz/docs/operate/relayer/monitoring-alerting The relayer exposes metrics on the port number specified by the argument . Port is the default, though any valid port can be chosen. We recommend using Prometheus to scrape these metrics and Grafana to visualize them, using [this dashboard JSON template](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/2f7f714c5b698fedcead9825f52da6ef95f96be1/tools/grafana/easy-relayer-dashboard-template.json), as seen below. The benefit of this dashboard is that it displays multiple validators at the same time. The screenshot shows metrics grouped by chain or by kubernetes pod. Relayer Grafana Dashboard Template If running as a Docker image, make sure to port-forward the metrics endpoint port. For, instance, to forward port 9090 on the local port 80, add the following flag to your `docker run` command: `-p 9090:80` ## Metrics The dashboard template includes the following metrics. | Metric | Description | | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `hyperlane_messages_processed_count` | The messages processed by the relayer, by origin and destination chain ("Messages Processed"). | | `hyperlane_submitter_queue_length{queue_name="prepare_queue"}` | Length of the submitter's prepare queue ("Prepare Queues"). Each destination chain has a submitter running, and all pending / retriable messages end up in the prepare queue, awaiting to be (re)submitted. An increase in this queue may either mean that the volume of messages exceeds the relayer's processing throughput or that submitting is failing for various reasons (bad RPCs, low balance). | | `hyperlane_submitter_queue_length{queue_name="submit_queue"}` | Length of the submitter's submit queue ("Submit Queues"). These are messages that have been prepared but not submitted yet. | | `hyperlane_submitter_queue_length{queue_name="confirm_queue"}` | Length of the submitter's confirm queue ("Confirm Queues"). These are messages that have been submitted but not confirmed (finalized) yet. | Other relevant metrics include: | Metric | Description | | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `hyperlane_request_count` | Records the number of successful or failed RPCs using the following labels: `chain`, `status` (failure or success), `provider_node` (the responsible base RPC URL), and RPC `method`. Present for all agents, but only supported on EVM chains at the moment. | | `hyperlane_wallet_balance{agent="relayer"}` | The relayer's balance on every chain, expressed in the lowest denomination unit | | `hyperlane_critical_error` | Boolean marker for critical errors on a chain, signalling loss of liveness. | | `hyperlane_block_height` | The block height of the RPC node the agent is connected to. If this metric is not increasing, the RPC may be unhealthy and need changing. | | `hyperlane_span_events_total{agent="relayer", event_level="error"}` | The total number of errors logged. If the derivative of this metric exceeds 1 over the last hour, at least a low-severity alert is warranted. Note that the dashboard query groups metrics by kubernetes pod name, so you may need to adjust this query if you are not running in a kubernetes environment. | | `hyperlane_span_events_total{agent="relayer", event_level="warn"}` | The total number of warnings logged. If the derivative of this metric exceeds 1 over the last hour, at least a low-severity alert is warranted. Note that the dashboard query groups metrics by kubernetes pod name, so you may need to adjust this query if you are not running in a kubernetes environment. | ## Alerts The metrics above can be combined to create alerts that minimize false positives. Some example critical alerts: ### For all agents * `hyperlane_block_height` for any chain has not increased in the last 15 minutes * The rate of `hyperlane_request_count{status="failure"}` in the last 10 minutes is > 60% of the rate of `hyperlane_request_count{status=~"success|failure"}`. Most agent issues are due to bad RPCs, and this is likely to catch these issues. ### For relayers * `hyperlane_critical_error` is `1` for a chain, meaning the relayer has lost liveness there. While operations on other chains are not affected by this, this is a high severity alert - usually to do with unreliable RPCs for the affected chain. * Using `hyperlane_submitter_queue_length{queue_name="prepare_queue"}`, the prepare queue length has been increasing, and the confirm queue length was zero, and error/warning count diffs have been increasing, over the last 30 minutes. This could mean that the relayer has run out of balance and cannot pay for gas, or that the destination chain RPC url is not working correctly, or just that all new messages are unprocessable * `hyperlane_wallet_balance` has dropped below a certain threshold. For example, the current balance divided by the difference in the last 24h is less than 2, meaning balance must be topped up within two days If you get alerted, always check the logs for what the problem could be. # Run a Relayer Source: https://docs.hyperlane.xyz/docs/operate/relayer/run-relayer * For an introduction on Relayers in Hyperlane, you can check out the [Overview section](/docs/operate/overview-agents). * We recommend you read through the [**Deploy Hyperlane Local Agents**](/docs/guides/chains/deploy-hyperlane-with-local-agents) guide to understand how to configure and run the Relayer locally, as well as the [**Run Validators**](/docs/operate/validators/run-validators) documentation before trying to run a production Relayer. ## Requirements * **RPC nodes** * A Relayer uses RPC nodes to read the origin chain(s), and deliver messages to the destination chain(s). The Relayer must be configured with an RPC node for all origin and destination chains. * **One or more signing keys** * In order to deliver messages, the Relayer must be configured with a signing key to submit transactions on each destination chain (thus need funds on those chains). * The Relayer uses this key to sign `Mailbox.process()` transactions. The Hyperlane Relayer agent currently supports configuration with AWS KMS keys that are accessed via API keys/secrets or raw hexadecimal private keys. * **A machine to run on** * Relayer operators can compile the Rust binary themselves, or run a Docker image provided by Abacus Works. The binary can be run using your favorite cloud service. **Running a Single Relayer**: A single relayer is generally sufficient and can handle message delivery across 100+ chains efficiently. You don't need to run separate relayers for each network - this approach can increase operational complexity without providing performance benefits. ## Guide * The local agent setup shows how you can run a Relayer on your *local machine*, which is **only for testing and development purposes**. * We strongly encourage you to follow the [local agents guide](/docs/guides/chains/deploy-hyperlane-with-local-agents) to understand how to configure and run the Relayer locally. ### Keys The Relayer needs to be able to submit transactions to many destination chains, and therefore requires access to a key for signing transactions. There are two supported key types: hexadecimal private keys (for in-memory signing), and AWS KMS based keys (best practice for production environments). #### Hexadecimal keys A hexadecimal private key used for in-memory signing can be used by your Relayer to sign transactions. This is the recommended setup for testing or development purposes, but may also be used in production. #### AWS KMS keys An AWS KMS key can be used by your Relayer to sign transactions. This is the recommended setup for a production Relayer. See the [Agent Keys](/docs/operate/set-up-agent-keys) page to set up your Hexadecimal or AWS KMS keys. ### Configuration #### RPC Configuration Hyperlane Validators and Relayers can use **multiple RPC URLs** to improve reliability and redundancy. The setup varies based on the chain type. EVM-based chains support configuring multiple RPC endpoints for redundancy and can specify how they are used. * **Configure multiple RPCs:** Use [`customRpcUrls`](/docs/operate/config/config-reference#chains-\-customrpcurls). * **RPC Selection Mode ([`rpcConsensusType`](/docs/operate/config/config-reference#chains-\-rpcconsensustype))**: * **Fallback**: The agent tries the first URL and switches to the next if needed. * **Quorum**: Requires a majority of the URLs to agree with the exception of submitting transactions. Cosmos-based chains require both **RPC and gRPC endpoints** for proper operation. * **Configure multiple RPCs:** Use [`customRpcUrls`](/docs/operate/config/config-reference#chains-\-customrpcurls). * **Configure gRPC endpoints:** Use \[`customGrpcUrls`]. * **Fallback Mechanism:** Cosmos agents always use **fallback mode**. SVM-based chains support configuring multiple RPC endpoints. Agents automatically use **fallback mode**: if the current RPC fails or times out, they switch to the next available endpoint. * **Configure RPCs:** Use [`customRpcUrls`](/docs/operate/config/config-reference#chains-\-customrpcurls). For **SVM chains**, only **Fallback mode** is supported. SVM agents will automatically switch between configured RPC URLs when encountering errors or timeouts. **SVM Relayer Funding**: When relaying messages to SVM chains, make sure your Relayer key has sufficient funds on the destination chain. The Relayer performs view calls via simulations that require the sender to have funds for successful simulation, even for read operations. Without sufficient funds, you may encounter `No return data from InboxGetRecipientIsm instruction` errors. #### Configuration Settings Like the local setup, there are a few base arguments you should provide when configuring your Relayer. | Argument | Description | | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--relayChains` | Comma separated names of the origin and destination chains to relay messages between. For example: `ethereum,polygon,avalanche`. | | `--db` | The path to where the Relayer should write persistent data to disk. Ensure this path to be persistent when using cloud setups. When using Docker, make sure to mount the persistent path/volume into the container. See [config-reference](/docs/operate/config/config-reference#db) for more info. | | `--allowLocalCheckpointSyncers` | If `true`, this will allow the Relayer to look for Validator signatures on the Relayer's local filesystem. In a production environment, this should be `false`. If you're running a Validator on the same machine by following the Validator local setup instructions, set this to `true` so that your Relayer can access the local Validator signatures. | Your Relayer takes both command line arguments and environment variables as configuration. Take a look at the [agent configuration](/docs/operate/config/agent-config) page and the [configuration reference](/docs/operate/config/config-reference) for a full list of configuration possibilities. You can also provide the path to additional configuration files as a comma separated list with the [`CONFIG_FILES` environment variable](/docs/operate/config/config-reference#config_files). If you choose to run in Docker, see the docker section of [agent configuration](/docs/operate/config/agent-config) for tips on mounting your config files into your Docker container. ### Setup-specific configuration These configurations requirements differ depending on which key setup instructions you followed. If you created a [hexadecimal key](../set-up-agent-keys), configure the default signer like so: | Argument | Description | | --------------------- | -------------------------------------------------------------------------------------------------- | | `--defaultSigner.key` | A hexadecimal private key used to sign transactions for all chains. For example: `1b3dead...beef`. | If you created an [AWS KMS key](../set-up-agent-keys), configure the default signer like so: | Argument | Description | | ------------------------ | ---------------------------------------------------------------------------------------------------------- | | `--defaultSigner.type` | Set to `aws`. | | `--defaultSigner.id` | The alias of your Relayer's AWS KMS key, prefixed with `alias/`. For example: `alias/hyperlane-relayer-1`. | | `--defaultSigner.region` | The region of your AWS KMS key. For example: `us-east-1`. | For chain-specific signers (i.e. to customize the key to use for each chain) take a look at the [configuration reference](/docs/operate/config/config-reference) ## Start Relaying ### Setup The recommended installation method for a production environment is using a Docker image. First download the docker image: ```bash theme={null} docker pull --platform linux/amd64 ghcr.io/hyperlane-xyz/hyperlane-agent:agents-v2.2.0 ``` **Clone and setup** First, clone the Hyperlane monorepo: ```sh theme={null} git clone git@github.com:hyperlane-xyz/hyperlane-monorepo.git ``` Then follow the [setup instructions](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/README.md) in the `rust` directory. This should setup `rustup` as well as Rosetta 2 if you are on Apple Silicon. ```sh theme={null} # install rustup curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # (apple silicon only) install rosetta 2 softwareupdate --install-rosetta --agree-to-license ``` Build the Relayer: ```sh theme={null} cargo build --release bin relayer ``` ### Running the agent If the Relayer's keys have been configured with AWS KMS, you will have to provide the AWS access key and secret as environment variables. | Environment variable | Description | | ----------------------- | ----------------------------------------------------- | | `AWS_ACCESS_KEY_ID` | The access key ID of your Relayer's AWS IAM user. | | `AWS_SECRET_ACCESS_KEY` | The secret access key of your Relayer's AWS IAM user. | For a refresher, check out the [Agent Keys](/docs/operate/set-up-agent-keys) guide. Then start the container with the relevant arguments. For example, your configuration for AWS: ```sh theme={null} docker run \ -it \ -e AWS_ACCESS_KEY_ID=ABCDEFGHIJKLMNOP \ -e AWS_SECRET_ACCESS_KEY=xX-haha-nice-try-Xx \ --mount ... \ ghcr.io/hyperlane-xyz/hyperlane-agent:agents-v2.2.0 \ ./relayer \ --db /hyperlane_db \ --relayChains , \ --defaultSigner.type aws \ --defaultSigner.id alias/hyperlane-relayer-1 \ --defaultSigner.region us-east-1 \ ``` If you're running Validators with a local setup on the same machine and running a local Relayer to access these Validator signatures, be sure to [mount](https://docs.docker.com/storage/bind-mounts/) your local Validator's signature directory into your Relayer at the same path that you used when [announcing your Validator](/docs/operate/validators/run-validators#announcing-your-validator) For example, if your local Validator is writing signatures to `/tmp/hyperlane-validator-signatures-ethereum`, you should mount a directory for the Docker container: ```sh theme={null} docker run \ -it \ -e CONFIG_FILES=/config/agent-config.json \ --mount type=bind,source=$CONFIG_FILES,target=/config/agent-config.json,readonly \ --mount type=bind,source="$(pwd)"/hyperlane-validator-signatures-ethereum,target=/tmp/hyperlane-validator-signatures-ethereum,readonly \ --mount type=bind,source="$(pwd)"/hyperlane_db,target=/hyperlane_db \ ghcr.io/hyperlane-xyz/hyperlane-agent:agents-v2.2.0 \ ./relayer \ --db /hyperlane_db \ --relayChains ethereum,polygon,avalanche \ --allowLocalCheckpointSyncers true \ --defaultSigner.key \ ``` See these instructions for building from source without Docker. We can run the built binary from within the `hyperlane-monorepo/rust` directory: ```sh theme={null} # set AWS environment variables export AWS_ACCESS_KEY_ID=ABCDEFGHIJKLMNOP export AWS_SECRET_ACCESS_KEY=xX-haha-nice-try-Xx # run the Relayer ./target/release/relayer \ --db /hyperlane_db \ --relayChains , \ --defaultSigner.type aws \ --defaultSigner.id alias/hyperlane-relayer-1 \ --defaultSigner.region us-east-1 \ ``` ## Indexing The Relayer needs to index all historic messages for the origin chain(s). This information is stored in a local database on disk (set with `db` in the config). This means running a Relayer for the first time may take some extra time to catch up with the current state. # Agent Keys Source: https://docs.hyperlane.xyz/docs/operate/set-up-agent-keys Hyperlane agents - Validators and the Relayer - must be configured with private keys in order to operate. Validators use private keys to sign [message checkpoints](/docs/resources/glossary#checkpoint), and the Relayer uses private keys to sign transactions that deliver messages. Hyperlane agents currently support being configured with private keys in one of two ways. ## 1. Hexadecimal keys A raw hexadecimal private key used for in-memory signing. This is the easiest and fastest setup. Hexadecimal keys are less secure than AWS KMS keys. ### Generate a hexadecimal key Keep track of your address and private key for use with your agent. Do not lose or leak it. Using [Foundry's cast](https://book.getfoundry.sh/cast/), you can create a new key pair: ```sh theme={null} cast wallet new ``` The output will look something like this: ``` Successfully created new keypair. Address: 0x32e6d32E7b1C8691Ef4ad3841003371214a0eebC Private Key: 0x2958f0eb2ab71bbfb5ea1422835e20e488778b61e3c107f369572e2b53b578f9 ``` You can visit [https://privatekeys.pw/keys/ethereum/random](https://privatekeys.pw/keys/ethereum/random), which will automatically display a list of hexadecimal private keys and their addresses. Please note that because these are generated by a website, these private keys should be considered insecure and should not be used for anything other than testing purposes! ## 2. AWS KMS A key generated by AWS and stored in a CloudHSM. This is the recommended setup for production agents. ### Create an IAM user This IAM user will be given permission to sign with the KMS key that you will later configure. Your Hyperlane agent will use this identity when signing transactions. 1. Go to AWS's Identity and Access Management (IAM) in the [AWS console](https://us-east-1.console.aws.amazon.com/iamv2/home). 2. On the left, under "Access management", click "Users". 3. Click the orange button "Add users". 4. Pick a friendly and informative username, like `hyperlane-validator-${chain_name}` or `hyperlane-relayer-${chain_name}`. This username will be referenced in future steps, so if you choose a different username be sure to use your correct username in the future. 5. Click "Next", you do not need to assign the user any permissions. 6. Click "Create user". 7. Click into the user that you just created 8. Click the "Security Credentials" tab 9. Scroll down to "Access Keys" and click "Create Access Key" 10. Select "Application running outside AWS" and click "Next" 11. Click "Next", no need to add a description tag 12. Click "Create access key" 13. Copy the "Access key ID" and "Secret access key" to a safe place. These will be passed to your Hyperlane Relayer as environment variables. ### Create a KMS key This key will be used by your agent for signing. 1. Go to AWS's Key Management Service (KMS) in the AWS console. 2. Ensure you are in the region you want to create the key in. This can be confirmed by viewing the region at the top right of the console, or by finding the name in the URL's subdomain (e.g. `us-west-2.console.aws.amazon.com` means you're operating in the region `us-west-2`). 3. On the left, click "Customer managed keys". 4. Click "Create key". 5. Select the "Asymmetric" key type. 6. Select the "Sign and verify" key usage. 7. Select the `ECC_SECG_P256K1` key spec. 8. Click "Next". 9. Set the Alias to something friendly and informative, like `hyperlane-validator-signer-${chain_name}` or `hyperlane-relayer-signer-${chain_name}` 10. While not necessary, feel free to write a description and add any tags that you think will be useful. 11. Click "Next". 12. A key administrator is not required, but if you want, you can select one. 13. Click "Next". 14. Give usage permissions to the IAM user you created in section #1. 15. Click "Next". 16. In the Review page, scroll to the "Key policy". The generated key policy is acceptable, but you can make the access even less permissive if you wish by: 1. Removing the `kms:DescribeKey` and `kms:Verify` actions from the statement whose "Sid" is "Allow use of the key" 2. Removing the entire statement whose "Sid" is "Allow attachment of persistent resources". 17. Click "Finish" Advanced users may consider using the [IAM/KMS Terraform module](/docs/operate/guides/deploy-with-terraform#modules) instead to create the IAM user and KMS key. ### Query address In some cases you may need to know the address associated with the KMS key you generated. ```sh With cast theme={null} AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_KMS_KEY_ID=alias/your-key-alias cast wallet address --aws ``` ```sh Using a script theme={null} # The script at the following repo will allow you to query this address: # https://github.com/tkporter/get-aws-kms-address ``` # Monitoring & Alerting Source: https://docs.hyperlane.xyz/docs/operate/validators/monitoring-alerting Validators expose metrics on the port number specified by the argument . Port is the default, though any valid port can be chosen. We recommend using Prometheus to scrape these metrics and Grafana to visualize them, using [this dashboard JSON template](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/84e8c5c218ac5d211c766cf4d5a135aee10e508c/tools/grafana/validator-dashboard-template.json), as seen below. The benefit of this dashboard is that it displays multiple validators at the same time. The screenshot shows metrics grouped by chain or by kubernetes pod. Validator Grafana Dashboard Template If running as a Docker image, make sure to port-forward the metrics endpoint port. For instance, to forward port 9090 on the local port 80, add the following flag to your `docker run` command: `-p 9090:80` ## Metrics The dashboard template includes the following metrics. | Metric | Description | | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `hyperlane_latest_checkpoint` | The latest checkpoint observed by the validator | | `hyperlane_block_height` | The block height of the RPC node the agent is connected to. This metric is updated periodically independently from the checkpoint indexing functionality of validator. | | `hyperlane_contract_sync_liveness` | The timestamp which is reported on every iteration of the indexing loop of validator. | | `hyperlane_contract_sync_block_height` | The block height observed by validator as part of indexing loop. | | `hyperlane_cursor_current_block` | The block height observed by internal cursor of the validator. | | `hyperlane_span_events_total{agent="validator", event_level="error"}` | The total number of errors logged, visualized as 30 min increases ("Error log count diffs"). If the derivative of this metric exceeds 1 over the last hour, at least a low-severity alert is warranted. Note that the dashboard query groups metrics by kubernetes pod name, so you may need to adjust this query if you are not running in a kubernetes environment. | | `hyperlane_span_events_total{agent="validator", event_level="warn"}` | The total number of warnings logged, visualized as 30 min increases ("Warning log count diffs"). If the derivative of this metric exceeds 1 over the last hour, at least a low-severity alert is warranted. Note that the dashboard query groups metrics by kubernetes pod name, so you may need to adjust this query if you are not running in a kubernetes environment. | ## Charts The dashboard template includes the following charts. | Chart | Description | | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Signed Checkpoint Diffs (30m)` | The latest checkpoint observed by the validator, visualized as 30 min increases. If values not positive in spite of `Latest Block Diffs (30m)` stable, it could mean that either there are no new messages, or that the validator stopped signing checkpoints. | | `Diff observed - processed checkpoints` | The difference between checkpoints which validator observed on blockchain and the checkpoints which validator signed and published. This chart should be zero most of the time with occasional and short lived positive values. If it is positive for extended period of time, it means that validator has issues with signing and publishing checkpoints. | | `Latest Block Diffs (30m)` | The block height of the RPC node the agent is connected to, visualized as 30 min increases ("Latest block diffs"). If this metric is not increasing, the RPC may be unhealthy and need changing. | | `Contract Sync Liveness` | Renders metric `hyperlane_contract_sync_liveness` as it is. The graph should always go up. If it is constant, it indicates an issue. If chart contains metrics for several chains, they will be rendered on top of each other. It is normal when nothing is broken. Deviations will be visible if there is an issue which should be investigated. | | `Contract Sync Block Diffs (30m)` | Renders metric `hyperlane_contract_sync_block_height` as 30 min increases. It should approximately match the number of blocks produced by the chain during last 30 minutes. If the metric deviate significantly in any direction, becomes zero, it should be investigated. | | `Cursor Block Diffs (30m)` | Renders metric `hyperlane_cursor_current_block` as 30 min increases. It should approximately match the number of blocks produced by the chain during last 30 minutes. If the metric deviate significantly in any direction, becomes zero, it should be investigated. | | `Error log count diffs (30m)` | The total number of errors logged, visualized as 30 min increases ("Error log count diffs"). If the derivative of this metric exceeds 1 over the last hour, at least a low-severity alert is warranted. Note that the dashboard query groups metrics by kubernetes pod name, so you may need to adjust this query if you are not running in a kubernetes environment. | | `Warning log count diffs (30m)` | The total number of warnings logged, visualized as 30 min increases ("Warning log count diffs"). If the derivative of this metric exceeds 1 over the last hour, at least a low-severity alert is warranted. Note that the dashboard query groups metrics by kubernetes pod name, so you may need to adjust this query if you are not running in a kubernetes environment. | ## Alerts All the metrics above can be combined to create alerts that minimize false positives. Some example critical alerts: * the `hyperlane_latest_checkpoint` stopped increasing, but the `hyperlane_block_height` is still increasing, and `error` and `warn` log counts have also been increasing, over the last 6 hours * `hyperlane_block_height` has not increased in the last 30 minutes If you get alerted, always check the logs for what the problem could be. # Run Validators Source: https://docs.hyperlane.xyz/docs/operate/validators/run-validators For an introduction on Validators in Hyperlane, you can check out the [Overview section](/docs/operate/overview-agents). As you follow this guide, you can run a Hyperlane validator on any of the existing [chains](https://github.com/hyperlane-xyz/hyperlane-registry/tree/main/chains) the protocol is live on. Hyperlane Validators are run on a per-origin-chain basis, and these instructions are written for a single chain. ## Requirements * **Secure Signing Key** * Validators use this key to sign the `Mailbox`'s latest merkle root. Securing this key is important. If it is compromised, attackers can attempt to falsify messages, causing the Validator to be slashed. * The Hyperlane Validator agent currently supports signing with AWS KMS keys that are accessed via API keys/secrets as well as hexadecimal plaintext keys. See more under [agent keys](/docs/operate/set-up-agent-keys). * **Publicly Readable Storage** * Validators write their signatures off-chain to publicly accessible, highly available, storage, so that they can be aggregated by the [Relayer](/docs/protocol/agents/relayer). * The Hyperlane Validator agent currently supports storing signatures on AWS S3 using the same AWS API key above, as well as storing signatures in the local filesystem for testing. * The design is [open source](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/56be527d691a11a1ff2de4a390fd0dae8bb77347/typescript/infra/src/agents) and generalizable to other storage and key solutions. There is a community-submitted work-in-progress [PR for GCS](https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/3156). * **Machine Requirements** * Validators can compile the Rust binary themselves or run a Docker image provided by Abacus Works. The binary can be run using your favorite cloud service. You can even run multiple instances of them in different regions for high availability, as Hyperlane has no notion of "double signing." * Hardware requirements & costs are minimal - validators often start with a 2-Core / 2GB RAM / 4GB Storage setup with typical costs around \$75/mo * **RPC Node** * Validators make simple view calls to read merkle roots from the [Mailbox](/docs/protocol/core/mailbox) contract on the chain they are validating for. You must use your own RPC urls not any public ones. * Validators should configure multiple RPC URLs for redundancy and reliability. Different chains have different configurations—check the Configuration section for details. Operating a Validator for Polygon mainnet requires access to an archive node. This is because Validators should only sign roots once they've been finalized, and Polygon requires 256 block confirmations to achieve finality. ## Guide ### Pre-Requisites As a recap - before running a production Validator you need to have: 1. Created a key for your Validator to sign with, see the [Agent Keys](/docs/operate/set-up-agent-keys) documentation. 2. Set up the destination for your Validator signatures to be posted, see the [AWS Signatures Bucket Setup](/docs/operate/validators/validator-signatures-aws) guide. ### Configuration Experienced operators may prefer to [deploy agents with Terraform](/docs/operate/guides/deploy-with-terraform) or a community-submitted [Ansible playbook](https://github.com/polkachu/hyperlane) instead. This process will automatically create agent keys, Validator buckets, permissions and any other auxiliary setup required to run a Validator cluster on AWS. #### RPC Configuration Hyperlane Validators and Relayers can use **multiple RPC URLs** to improve reliability and redundancy. The setup varies based on the chain type. EVM-based chains support configuring multiple RPC endpoints for redundancy and can specify how they are used. * **Configure multiple RPCs:** Use [`customRpcUrls`](/docs/operate/config/config-reference#chains-\-customrpcurls). * **RPC Selection Mode ([`rpcConsensusType`](/docs/operate/config/config-reference#chains-\-rpcconsensustype))**: * **Fallback**: The agent tries the first URL and switches to the next if needed. * **Quorum**: Requires a majority of the URLs to agree with the exception of submitting transactions; it will automatically coordinate the "latest" block if not specified to reduce sync errors. Cosmos-based chains require both **RPC and gRPC endpoints** for proper operation. * **Configure multiple RPCs:** Use [`customRpcUrls`](/docs/operate/config/config-reference#chains-\-customrpcurls). * **Configure gRPC endpoints:** Use [`customGrpcUrls`](/docs/operate/config/config-reference#chains-\-customrpcurls). * **Fallback Mechanism:** Cosmos agents always use **fallback mode**. SVM-based chains support configuring multiple RPC endpoints. Agents automatically use **fallback mode**: if the current RPC fails or times out, they switch to the next available endpoint. * **Configure RPCs:** Use [`customRpcUrls`](/docs/operate/config/config-reference#chains-\-customrpcurls). For **SVM chains**, only **Fallback mode** is supported. SVM agents will automatically switch between configured RPC URLs when encountering errors or timeouts. **SVM Relayer Funding**: When relaying messages to SVM chains, make sure your Relayer key has sufficient funds on the destination chain. The Relayer performs view calls via simulations that require the sender to have funds for successful simulation, even for read operations. Without sufficient funds, you may encounter `No return data from InboxGetRecipientIsm instruction` errors. #### Configuration Settings Like the local setup, there are a few base arguments you should provide when configuring your Validator. | Parameter | Description | | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | `--db` | Path for writing persistent data to disk. | | `--originChainName` | Name of the chain being validated. For example: `ethereum`. | | `--chains.[originChainName].customRpcUrls` | Override the default RPC URLs used by the Validator for your origin chain. | | `--chains.[originChainName].blocks.reorgPeriod` | Number of block confirmations the Validator needs to wait for before signing the `Mailbox` merkle root. | Your Validator takes both command line arguments and environment variables as configuration. Take a look at the [agent configuration](/docs/operate/config/agent-config) page and the [configuration reference](/docs/operate/config/config-reference) for a full list of configuration possibilities. You can also provide the path to additional configuration files as a comma separated list with the [`CONFIG_FILES` environment variable](/docs/operate/config/config-reference#config_files). If you choose to run in Docker, see the docker section of [agent configuration](/docs/operate/config/agent-config) for tips on mounting your config files into your Docker container. ### Setup-specific configuration These configurations requirements differ depending on which environment you are setting up. #### Checkpoint signer configuration | Argument | Description | | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | `--validator.key` | Your Validator's private key, which is used to sign merkle roots. | | `--chains.${localChainName}.signer.key` | Your Validator's private key, which will be used to submit a transaction onchain that publicly announces your Validator's checkpoint syncer. | | Argument | Description | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `--validator.region` | The region of your AWS KMS key. For example: `us-east-1`. | | `--validator.type` | Set to the `aws` literal. | | `--validator.id` | The alias of your Validator's AWS KMS key, prefixed with `alias/`. For example: `alias/hyperlane-validator-signer-${originChainName}`. | #### Transaction signer configuration The key configured in this step needs a small amount of funds to send the initial announcement transaction. This is the same as the local configuration for the checkpoint signer. | Argument | Description | | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | `--chains.${localChainName}.signer.key` | Your Validator's private key, which will be used to submit a transaction onchain that publicly announces your Validator's checkpoint syncer. | | Argument | Description | | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `--chains.${originChainName}.signer.type` | Set to the `aws` literal. | | `--chains.${originChainName}.signer.region` | The region of your AWS KMS key. For example: `us-east-1`. | | `--chains.${originChainName}.signer.id` | The alias of your Validator's AWS KMS key, prefixed with `alias/`. For example: `alias/hyperlane-validator-signer-${originChainName}`. | | Argument | Description | | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | `--chains.${originChainName}.signer.type` | Set to the `cosmosKey` literal. | | `--chains.${originChainName}.signer.prefix` | Set to the prefix literal associated with the chain's address format. Example: `osmo`. | | `--chains.${originChainName}.key` | Your Validator's hex private key, which will be used to submit a transaction onchain that publicly announces your Validator's checkpoint syncer. | #### Checkpoint syncer configuration | Argument | Description | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--checkpointSyncer.type` | Set to `localStorage`. | | `--checkpointSyncer.path` | The path to your local directory where Validator signatures will be written. This should be the value of `$MY_VALIDATOR_SIGNATURES_DIRECTORY` from the local setup. For example: `--checkpointSyncer.path='/tmp/hyperlane-validator-signatures-ethereum'`. | Note that the Relayer **must** be configured with `--allowLocalCheckpointSyncers` to be able to read signatures from this Validator. | Argument | Description | | --------------------------- | --------------------------------------------------------------------- | | `--checkpointSyncer.type` | Set to `s3`. | | `--checkpointSyncer.bucket` | The AWS S3 bucket name. | | `--checkpointSyncer.region` | The region of your AWS S3 bucket. For example: `us-east-1`. | | `--checkpointSyncer.folder` | A folder name to use for this validator, can be the name of the chain | ## Start Validating ### Setup The recommended installation method for a production environment is using a Docker image. First download the docker image: ```bash theme={null} docker pull --platform linux/amd64 ghcr.io/hyperlane-xyz/hyperlane-agent:agents-v2.2.0 ``` **Clone and setup** First, clone the Hyperlane monorepo: ```sh theme={null} git clone git@github.com:hyperlane-xyz/hyperlane-monorepo.git ``` Then follow the [setup instructions](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/rust/README.md) in the `rust` directory. This should setup `rustup` as well as Rosetta 2 if you are on Apple Silicon. ```sh theme={null} # install rustup curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # (apple silicon only) install rosetta 2 softwareupdate --install-rosetta --agree-to-license ``` Build the Validator: ```sh theme={null} cargo build --release bin validator ``` ### Running the binary For production Validators that write their signatures to an S3 bucket and have their keys configured with AWS KMS, you will have to provide the AWS access key and secret as environment variables. | Environment variable | Description | | ----------------------- | ------------------------------------------------------- | | `AWS_ACCESS_KEY_ID` | The access key ID of your Validator's AWS IAM user. | | `AWS_SECRET_ACCESS_KEY` | The secret access key of your Validator's AWS IAM user. | For a refresher, check out the [Agent Keys](/docs/operate/set-up-agent-keys) guide. Then start the container with the relevant arguments. For example, your configuration for AWS: ```sh theme={null} docker run \ -it \ -e AWS_ACCESS_KEY_ID=ABCDEFGHIJKLMNOP \ -e AWS_SECRET_ACCESS_KEY=xX-haha-nice-try-Xx \ --mount ... \ ghcr.io/hyperlane-xyz/hyperlane-agent:agents-v2.2.0 \ ./validator \ --db /hyperlane_db \ --originChainName \ --reorgPeriod 1 \ --validator.region us-east-1 \ --checkpointSyncer.region us-east-1 \ --validator.type aws \ --chains..signer.type aws \ --validator.id alias/hyperlane-validator-signer- \ --chains..signer.id alias/hyperlane-validator-signer- \ --checkpointSyncer.type s3 \ --checkpointSyncer.bucket hyperlane-validator-signatures- \ --checkpointSyncer.folder \ ``` See these instructions for building from source without Docker. We can run the built binary from within the `hyperlane-monorepo/rust` directory: ```sh theme={null} # set AWS environment variables export AWS_ACCESS_KEY_ID=ABCDEFGHIJKLMNOP export AWS_SECRET_ACCESS_KEY=xX-haha-nice-try-Xx # run the Validator ./target/release/validator \ --db /hyperlane_db \ --originChainName \ --reorgPeriod 1 \ --validator.region us-east-1 \ --checkpointSyncer.region us-east-1 \ --validator.type aws \ --chains..signer.type aws \ --chains..signer.region \ --validator.id alias/hyperlane-validator-signer- \ --chains..signer.id alias/hyperlane-validator-signer- \ --checkpointSyncer.type s3 \ --checkpointSyncer.bucket hyperlane-validator-signatures- ``` ### Announcing your Validator The [Relayer](/docs/operate/relayer/run-relayer) needs to know where to find your Validator's signatures. Your Validator will automatically attempt to announce itself by writing to the `ValidatorAnnounce` contract on the chain that you're validating. To do this, your Validator must have a small amount of tokens to pay for the gas for this transaction. If your Validator has not yet announced itself, and does not have enough tokens to pay for gas, it will log a message specifying how many tokens are needed. ### Success! The Validator will index the origin Mailbox contract for messages. If a message has been sent, you should see log messages that the Validator has signed them. If everything is configured correctly, you should see json files being written to your S3 bucket (if you followed the AWS setup) or to your local signatures directory if you followed the local setup. New json files get written every time a new outbound message is inserted into the mailbox. ## Running Multiple Validators We encourage folks to validate on as many chains as they are interested in supporting. This section provides an overview of the considerations and instructions to set up multiple validators. Running multiple validators improves security and redundancy. By deploying validators across different chains or regions, you reduce the risk of a single point of failure. If one validator encounters downtime or issues, others can continue to operate, ensuring the integrity and availability of the validation process. ### Running Multiple Validators: Key Considerations * **Reusing Keys**: The same key can be used by multiple validators. * **Shared AWS Account**: The same AWS account can be used by multiple validators. * **Using a Shared S3 Bucket**: The same checkpoint syncer S3 bucket can be used by multiple validators, however each **must** use a different folder (e.g., `--checkpointSyncer.folder validator-1`, `--checkpointSyncer.folder validator-2`). ### Additional Steps for Multiple Validators #### 1. Create an Agent Configuration * Generate an agent [configuration](#configuration) file for each validator, specifying the chains they will validate and the corresponding RPC URLs. * Ensure that each configuration file points to the correct signing key and S3 folder. #### 2. Run Each Validator * Ensure each Validator is assigned a unique database path (e.g., `--db /hyperlane_db_validator1`). * Configure each validator to expose metrics on a unique port (e.g., `--metrics-port 9090`, `--metrics-port 9091`). * If running multiple validators on the same machine, allocate sufficient system resources (CPU, memory, and storage). * Ensure logs are directed to separate files or services for easier debugging and monitoring. * If using Docker, assign unique container names and network configurations to avoid conflicts. By following these additional steps, you can efficiently manage multiple Hyperlane Validators. ## Design Reference ```mermaid theme={null} flowchart TB V(("Validator(s)")) Relayer((Relayer)) subgraph Origin Sender M_O[(Mailbox)] POS[Proof of Stake] Sender -- "dispatch(destination, recipient, body)" --> M_O end subgraph Cloud aws[(Metadata
Database)] end M_O -. "indexing" .-> Relayer M_O -. "indexing" .-> V POS == "staking" === V V -- "signatures" --> aws subgraph Destination Recipient M_D[(Mailbox)] ISM[MultisigISM] M_D -- "verify(metadata, [origin, sender, body])" --> ISM M_D -- "handle(origin, sender, body)" --> Recipient ISM -. "interchainSecurityModule()" .- Recipient end Relayer -- "process()" --> M_D aws -. "metadata" .-> Relayer aws -. "moduleType()" .- ISM POS -. "validators()" .- ISM click ISM https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/interfaces/isms/IMultisigIsm.sol style Sender fill:#efab17 style Recipient fill:#efab17 ``` # AWS Signatures Bucket Setup Source: https://docs.hyperlane.xyz/docs/operate/validators/validator-signatures-aws Configure your signing key and S3 bucket These instructions are for a production environment where Validator keys exist in AWS's Key Management Service and Validator signatures are posted publicly in an S3 bucket. If you're only intending to run a Validator for testing or development purposes, consider following the [local setup guide](/docs/guides/chains/deploy-hyperlane-with-local-agents) instead. ### 1. Create an AWS IAM user, and a signing key Follow the instructions in [Agent Keys](/docs/operate/set-up-agent-keys) to generate an AWS IAM user and either a KMS or a hexadecimal key. You will use this key's credentials in the following steps. ### 2. Create an S3 bucket Note that Step 1 (creating the IAM user) is required for setting up the S3 bucket, so is required regardless of the type of key used. Your Validator will post their signatures to this bucket. 1. Go to AWS's S3 in the AWS console. 2. On the right, click the orange "Create Bucket" button 3. Pick an informative bucket name, such as `hyperlane-validator-signatures-${validator_name}-${chain_name}` 4. Consider choosing the same region as the KMS key you created in the previous step. 5. Keep the recommended "ACLs disabled" setting for object ownership. 6. Configure public access settings so that the relayer can read your signatures 1. Uncheck "Block all public access" 2. Check the first two options that block access via access control lists 3. Leave the last two options unchecked, we will be granting public read access via a bucket policy 4. Acknowledge that these settings may result in public access to your bucket 7. The remaining default settings are fine, click the orange "Create bucket" button on the bottom ### 3. Configure S3 bucket permissions Your Validator IAM user will need write permissions, and it should be publicly readable by the Relayer. 1. Navigate back to "Identity and Access Management (IAM)" in the AWS console 2. Under "IAM resources" you should see at least one "User", click into that 3. Click on the name of the user that you provisioned earlier (e.g. `hyperlane-validator-${chain_name}`) 4. Copy the "User ARN" to your clipboard, it should look something like `arn:aws:iam::791444913613:user/hyperlane-validator-${chain_name}` 5. Navigate back to "S3" in the AWS console 6. Click on the name of the bucket you just created 7. Just under the name of the bucket, click "Permissions" 8. Scroll down to "Bucket policy" and click "Edit" 9. Enter the following contents. The Bucket ARN is shown just above where you enter the policy ```json theme={null} { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": ["s3:GetObject", "s3:ListBucket"], "Resource": ["${BUCKET_ARN}", "${BUCKET_ARN}/*"] }, { "Effect": "Allow", "Principal": { "AWS": "${USER_ARN}" }, "Action": ["s3:DeleteObject", "s3:PutObject"], "Resource": "${BUCKET_ARN}/*" } ] } ``` Advanced users may consider using the [S3 Terraform module](/docs/operate/guides/deploy-with-terraform#modules) instead to create the S3 bucket with the correct permissions. # Hyperlane Protocol Economics Source: https://docs.hyperlane.xyz/docs/protocol-economics/intro Hyperlane is a permissionless interoperability protocol for cross-chain communication, enabling messages to move across different blockchains. HYPER is Hyperlane's native token introduced to align incentives within the Hyperlane ecosystem and empower the community. It is used to secure cross-chain communication via staking and rewards network participants for their contribution to protocol activity. ## HYPER Token Overview ### HYPER HYPER is the native token for the Hyperlane protocol. It exists on multiple networks including Ethereum Mainnet, Base, OP Mainnet, Arbitrum One, and BSC. HYPER is used to secure the Hyperlane protocol through staking. Validators are selected to provide default message security based in part by staking HYPER. | Token | Network | Contract Address | | --------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------ | | **HYPER** | Ethereum Mainnet | [0x93A2Db22B7c736B341C32Ff666307F4a9ED910F5](https://etherscan.io/token/0x93A2Db22B7c736B341C32Ff666307F4a9ED910F5) | | **HYPER** | Arbitrum One | [0xC9d23ED2ADB0f551369946BD377f8644cE1ca5c4](https://arbiscan.io/token/0xC9d23ED2ADB0f551369946BD377f8644cE1ca5c4) | | **HYPER** | Base | [0xC9d23ED2ADB0f551369946BD377f8644cE1ca5c4](https://basescan.org/token/0xC9d23ED2ADB0f551369946BD377f8644cE1ca5c4) | | **HYPER** | OP Mainnet | [0x9923DB8d7FBAcC2E69E87fAd19b886C81cd74979](https://optimistic.etherscan.io/token/0x9923DB8d7FBAcC2E69E87fAd19b886C81cd74979) | | **HYPER** | BSC | [0xC9d23ED2ADB0f551369946BD377f8644cE1ca5c4](https://bscscan.com/token/0xC9d23ED2ADB0f551369946BD377f8644cE1ca5c4) | ### stHYPER stHYPER is a liquid staking token that users receive when they lock HYPER into the [Symbiotic vault](https://docs.symbiotic.fi/modules/vault/introduction/). stHYPER is available on Ethereum Mainnet and BSC. It serves as a receipt token, representing a user's staked HYPER. Claiming rewards is available where stHYPER exists. | Token | Network | Contract Address | | ----------- | ---------------- | ------------------------------------------------------------------------------------------------------------------- | | **stHYPER** | Ethereum Mainnet | [0xE1F23869776c82f691d9Cb34597Ab1830Fb0De58](https://etherscan.io/token/0xE1F23869776c82f691d9Cb34597Ab1830Fb0De58) | | **stHYPER** | BSC | [0x6E9804a08092D8ba4E69DaCF422Df12459F2599E](https://bscscan.com/token/0x6e9804a08092d8ba4e69dacf422df12459f2599e) | ### HYPER vs. stHYPER | Token | What it is | Where it exists | Rewards | | ----------- | ----------------------------------------- | --------------------------------------------- | ------- | | **HYPER** | Native token of the Hyperlane protocol | Ethereum, Base, OP Mainnet, Arbitrum One, BSC | - | | **stHYPER** | Liquid staking token from Symbiotic vault | Ethereum, BSC | ✅ Yes | ## Staking Staking is how participants contribute to the economic security of the Hyperlane protocol and earn rewards. To stake, users lock HYPER tokens into the Symbiotic vault on Ethereum. This generates stHYPER, a liquid staking token representing the user's staked position. **HYPER Vault on Symbiotic**: The HYPER Vault does not restake to other protocols or networks. It only delegates to the Hyperlane network on Symbiotic, reducing external slashing risk. ### How Staking Works * **Staking Flow**: HYPER holders can stake their tokens on the Symbiotic app by selecting the HYPER Vault, and locking their HYPER tokens. * **Epoch Length**: Rewards are calculated algorithmically and automatically distributed per epoch, which is currently set to \~1 month. This duration reflects the maximum settlement delay on default [ Interchain Security Modules (ISMs)](/docs/protocol/ISM/modular-security) validator set chains. * **Unstaking Flow**: Unstaking requires user action on the steps outlined below. To withdraw HYPER you must: 1. Initiate the unstake action on the Symbiotic user interface. 2. Epoch start and end dates are defined by the protocol, meaning once you initiate unstaking, you'll need to wait roughly one full epoch (\~30 to 60 days, up to \~0.99 + 1 epochs) for your withdrawal to become available. 3. Finalize the withdrawal manually from the stake contract in the UI after the epoch ends. ### Economic Security Allocation HYPER in the HYPER Vault on Symbiotic is delegated to Validators based on an Economic Security Allocation algorithm. The allocation algorithm aims to distribute the economic security to the domains (chains) relative to their economic activity. This means domains with higher economic activity receive a greater share of the staked HYPER delegated to their validator sets. These validator sets are responsible for securing the default Interchain Security Module (ISM) for each domain. ISMs are smart contract modules that are responsible for verifying that messages being delivered on the destination chain were sent on the origin chain. Validators in the ISM validate the messages to ensure they are valid and trustworthy before they're processed. The allocation algorithm outputs an allocation percentage per domain, which is used to distribute the total staked HYPER across validator sets on each domain. *More details on this process will follow.* ## Hyperlane Validator Selection and Registration While Hyperlane's ISM model enables full customization of security, there is a default ISM on each provided Mailbox. Validators selected into this ISM (and only those validators) will receive Validator Rewards. ### Selection process Prospective validators (referred to as Operators in the Symbiotic network) must complete the [Hyperlane Validator Survey](https://docs.google.com/forms/d/e/1FAIpQLSfLo8D5GcrQVtR_ug3QcgVrXDgfdGPpz30ZLq7J9t2tHnB5xQ/viewform). Validators of the Hyperlane Protocol are responsible for attesting to messages of a certain origin chain. Thus, entities will be evaluated based on a set of weighted criteria around operational practices and uptime. This includes, but is not limited to: * **Operating Best Practices** * Chain Node Operations (e.g., RPC set-up, management, etc.) * Operational Security Practices (monitoring/alerts, secure secret management, engineering on-call rotation etc.) * **Operating History** * Historic Uptime * Operating History * Number of Hyperlane validators run * **Economic Security** * HYPER self-stake in Hyperlane Symbiotic Vault Validators are evaluated continuously based on operating history and performance, which determines their ability to maintain a position in the default ISM set. *Note: Validators will only earn rewards if they are selected to be a part of Hyperlane's default ISMs.* ### Registering as a Symbiotic Operator and Opting In Once selected for the default ISM, Validators must register as Operators on Symbiotic to receive delegation (stake) and rewards. #### Operator Registration Please refer to the Symbiotic docs on the steps to register as an operator through the [Symbiotic CLI](https://github.com/symbioticfi/cli): * [Operator Registration](https://docs.symbiotic.fi/handbooks/operators-handbook#through-cli) * [CLI Write Command Guide for Operators](https://docs.symbiotic.fi/guides/cli/#write-commands---for-operators) #### Metadata Submission After completing registration, submit a pull request to the [Symbiotic mainnet metadata repo](https://github.com/symbioticfi/metadata-mainnet) with your operator/network details and an icon. Use the same address you used for registration in the previous step. The metadata must meet several requirements as outlined in the Symbiotic documentation. Please note that pull requests that do not meet these requirements cannot be accepted. Metadata can be adjusted later, but any changes will require review by the Symbiotic team before being applied. #### Opting into Hyperlane's Network and Vault Before operators can start receiving delegations and rewards, they must complete two opt-in steps: 1. Opt-in to the [Hyperlane Network](https://app.symbiotic.fi/network/0x59cf937Ea9FA9D7398223E3aA33d92F7f5f986A2) on Symbiotic: 1. Use the [CLI opt-in command](https://docs.symbiotic.fi/guides/cli/#opt-in-network). 2. Verify the opt-in using the [CLI check command](https://docs.symbiotic.fi/guides/cli#check-opt-in-network). 2. Opt-in to the [HYPER Vault](https://app.symbiotic.fi/vault/0xE1F23869776c82f691d9Cb34597Ab1830Fb0De58) on Symbiotic: 1. Use the [CLI opt-in command](https://docs.symbiotic.fi/guides/cli/#opt-in-vault). 2. Verify the opt-in using the [CLI check command](https://docs.symbiotic.fi/guides/cli/#check-opt-in-vault). ### Joining Hyperlane's default ISM Once the validator has submitted the Hyperlane Validator Survey, and completed the Symbiotic Operator registration/opt-ins, the Validator can be selected when a default ISM validator position becomes available. Default ISM positions open when: * Hyperlane expands to new chains. * Validator positions on existing chains become available due to: 1. Validators being rotated out. 2. Validator position expansion due to security requirements. Once mutual interest is established via a shared communication channel, Validators can proceed with deployment (they may also deploy earlier if they choose). See [Run Validators](/docs/operate/validators/run-validators). For Validator Rewards claiming, head over to the [Validator Rewards Section](#validator-rewards). ## Slashing Slashing is a mechanism designed to encourage honest participation in the Hyperlane protocol. Participants who stake HYPER to secure the Hyperlane protocol take on slashing risk in case of a safety violation. If a quorum of validators signs messages that leads to safety violation (for example, if a quorum signs a message that is not included in the canonical chain state), a portion of the HYPER delegated to the chain can be slashed. This means that the stakers' staked HYPER would be slashed. Slashing occurs when there is proven fraud by validators. ### Fraud and Onchain Fraud Attribution Fraud is proven on all chains in the default ISM set via smart contracts. These contracts implement a fraud attribution system via the [`AttributeCheckpointFraud` contract](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/AttributeCheckpointFraud.sol). The contract defines specific types of fraudulent behavior. The `AttributeCheckpointFraud` contract attributes fraud to validators using specific `attribute` functions, depending on the type of violation. These attributions are then used to trigger slashing logic in the HYPER vault. **Fraud Types** There are four types of fraud as defined in the `AttributeCheckpointFraud` contract: 1. **Whitelist:** The validator used a Merkle tree implementation that wasn't valid. 2. **Premature:** The validator signed and submitted a checkpoint too early. 3. **Message ID:** The checkpoint commits to a wrong message ID that doesn't match the actual message. 4. **Root:** The Merkle root in the checkpoint is invalid. ### Slashing Penalties and Process Slashing penalties are socialized across all HYPER stakers. For example, if 5% of HYPER is slashed due to a fault, then all HYPER stakers would lose 5% of their staked HYPER. At launch, slashing is overseen by the Hyperlane Foundation and the Security Council, who can approve or veto slashing decisions. Over time, this process is expected to transition to on-chain enforcement through modules like trustless ISMs. ## Rewards Rewards are a core part of how the protocol aligns incentives and maintains active participation. The Hyperlane protocol distributes rewards to different participants based on their contributions. These include securing the network, sending messages, and operating validators. There are three main types of recipients: | **Recipient** | **Reward** | | --------------------------------------------------------------------- | --------------------- | | **Stakers** (stHYPER holders) | **Staker Rewards** | | **Validators** (default ISM Validator set) | **Validator Rewards** | | **Users** (EOAs who sign a transaction sending a cross-chain message) | **Expansion Rewards** | ### Staker Rewards The protocol distributes rewards to participants who stake HYPER in the Symbiotic Vault. These rewards are designed to incentivize contributions to Hyperlane's economic security. * **Eligibility**: Anyone holding stHYPER is eligible to receive rewards. * **Distribution**: Rewards are emitted at a fixed rate per epoch (\~30 days). * **Reward Calculation**: Rewards are based on the total staked amount and how long it remains staked. Stakers will receive rewards pro-rata to their stake after the Validator rewards commission is paid. This reward stream helps incentivize users to provide economic security for the Hyperlane protocol. ### Validator Rewards The protocol distributes rewards to participants who are part of the default Interchain Security Module(ISM) Validator set. These participants help secure the protocol by verifying cross-chain messages. Validator rewards are paid as a commission of the Staking rewards. * **Eligibility**: Validators in the default ISM Validator set. * **Distribution**: Rewards are allocated through Symbiotic UI. * Validators can claim the rewards via the ['claimRewards()'](https://github.com/symbioticfi/rewards/blob/7844a6ceaf4d740c7083a37e410194c1ef7867d3/src/contracts/defaultOperatorRewards/DefaultOperatorRewards.sol#L75) function with a Merkle proof that can be obtained via the [Symbiotic CLI](https://github.com/symbioticfi/rewards/blob/main/specs/OperatorRewards.md#cli). For details please refer to: [Symbiotic Operator Rewards](https://docs.symbiotic.fi/modules/extensions/rewards/#default-operator-rewards). * Validator rewards will be allocated directly to the Operator key during registration. * **Becoming part of the Hyperlane default ISM Validator set**: Validators are assessed based on criteria that includes operational security practices, historic performance and amount of HYPER staked. More details on this are provided in the Validator Selection section. *Please note that validators who are a part of other ISMs, such as application-specific ISMs, will not rewarded by the Hyperlane Protocol directly.* This reward stream helps incentivize operating Hyperlane Validators. ### Expansion Rewards The protocol distributes rewards to users who drive protocol activity by sending cross-chain messages. A user is any externally owned account (EOA) that signs a transaction sending a Hyperlane message. * **Eligibility**: Expansion Rewards will be distributed to Hyperlane users and applications that generate fees that pass a set threshold (i.e., stHYPER will be distributed as a relative share based on the users' or applications' fees as a percentage of the total fees in excess of the threshold). For more information, refer to the Hyperlane Foundation resources. * **How it works**: Expansion Rewards are distributed retroactively to users of the Hyperlane protocol based on protocol usage. * **Claiming rewards**: Eligible addresses will be able to claim rewards through a user interface. * **Frequency**: Rewards will not be distributed at regular frequencies. This reward stream helps incentivize real usage and adoption of the protocol. ### Streak Multiplier: HyperStreak With Hyperlane rewards, Hyperlane introduces a new incentive model designed to reward long-term alignment with the protocol. A core part of this model is the **HyperStreak** mechanism. #### What is HyperStreak? HyperStreak is a system that rewards users who continuously stake and hold stHYPER over a continuous period of time. Users with a HyperStreak will be eligible for boosted rewards based on their streak. Instead of requiring users to lock their tokens upfront, HyperStreak tracks how long users maintain their stHYPER, encouraging sustained participation. #### How it works * **Eligibility**: Users must hold stHYPER to be eligible for accumulating a HyperStreak. * **Streak Accumulation**: Each day a user holds stHYPER without moving or withdrawing, their HyperStreak grows by one day. If the user withdraws or transfers their staked HYPER, their streak resets (subject to policy on grace periods). * **Streak Levels**: HyperStreak has 4 levels. The longer a user maintains their streak, the higher the level (level 4) they achieve. Each level provides a boost to the user's reward. * **Level Assignment**: The system uses a dynamic approach for assigning levels. Users are ranked based on the proportion of the maximum possible streak. During the early phase (first 90 days after launch), any user who stakes and holds stHYPER without interruption qualifies for the highest level. The way to initially qualify for level 4 is to stake and keep idle the tokens received or purchased on the launch day. This level assignment is used to determine additional rewards. #### Reward Distribution & Allocation Rewards are distributed alongside Expansion Rewards based on a weighting system that allocates the Expansion Reward pool proportionally according to each user's weight. These additional rewards come from the same Expansion Reward pool. As a result, users with longer streaks receive a proportionally larger share, which reduces the amount available to those without a streak. A user's weight is determined by the streak level. | Level | B (bonus percentage) | Weight | | ------------- | -------------------- | ------ | | **Level 4** | 0.6 | 1.60 | | **Level 3** | 0.4 | 1.40 | | **Level 2** | 0.3 | 1.30 | | **Level 1** | 0.2 | 1.20 | | **No Streak** | 0 | 1.00 | Given a total reward pool R, each user's share is determined by: $$ {User Reward} = \left( \frac{\text{User's Weight}}{\sum_{i=1}^{N} \text{User}_i\text{'s Weight}} \right) \times R $$ The HyperStreak mechanism encourages users to engage consistently with the protocol and rewards those who do so from the beginning. It's designed to support the long-term sustainability of the Hyperlane protocol by aligned incentives. ## Additional Resources * [Hyperlane Foundation Blog post](https://medium.com/@hyperlane_fdn/introducing-hyper-f3846883f1f5) # Create Your Own ISM Source: https://docs.hyperlane.xyz/docs/protocol/ISM/custom-ISM Developers can specify or override the default ISM by implementing the `ISpecifiesInterchainSecurityModule` interface in their application. If no ISM is specified, or if the specified ISM is the null address, the default ISM configured on the destination chain's Mailbox will be used. ## ISM Interface ISMs must implement the `InterchainSecurityModule` interface. This implementation can be configured, composed, and customized according to the needs of their application. Specifically, this interface must be implemented in the same smart contract that implements `handle()`. The interface consists of two functions: `verify` and `moduleType`. ```solidity Solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; enum ModuleType { UNUSED, ROUTING, AGGREGATION, LEGACY_MULTISIG, MERKLE_ROOT_MULTISIG, MESSAGE_ID_MULTISIG, NULL, // used with relayer carrying no metadata CCIP_READ, ARB_L2_TO_L1, POLYGON_POS, OP_STACK } interface InterchainSecurityModule { /\*\* _ @notice Returns an enum that represents the type of security model _ encoded by this ISM. _ @dev Relayers infer how to fetch and format metadata. _/ function moduleType() external view returns (uint8); /** * @notice Defines a security model responsible for verifying interchain * messages based on the provided metadata. * @param _metadata Off-chain metadata provided by a relayer, specific to * the security model encoded by the module (e.g. validator signatures) * @param _message Hyperlane encoded interchain message * @return True if the message was verified */ function verify( bytes calldata _metadata, bytes calldata _message ) external returns (bool); } ``` ## Verify ```solidity theme={null} /** * @notice Defines a security model responsible for verifying interchain * messages based on the provided metadata. * @param _metadata Off-chain metadata provided by a relayer, specific to * the security model encoded by the module (e.g. validator signatures) * @param _message Hyperlane encoded interchain message * @return True if the message was verified */ function verify( bytes calldata _metadata, bytes calldata _message ) external returns (bool); ``` The primary function that ISMs must implement is `verify()`. The [Mailbox](/docs/protocol/core/mailbox) will call `IInterchainSecurityModule.verify()` before delivering a message to its recipient. If `verify()` reverts or returns `false`, the message will not be delivered. ### Parameters * `_metadata`: consists of arbitrary bytes provided by the [Relayer](/docs/protocol/agents/relayer). Typically, these bytes are specific to the ISM. For example, the `_metadata` for a [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM) must include validator signatures. * `_message`: consists of the Hyperlane message being verified. ISMs can use this to inspect details about the message being verified. For example, a [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM) could change validator sets based on the origin chain of the message. See the [`Message.sol`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/libs/Message.sol) library for more information on the format of the Hyperlane message passed to `verify()`. ## Module Type The secondary function that ISMs must implement is `moduleType()`. ```solidity theme={null} function moduleType() external view returns (uint8); ``` This is used to signal to the [Relayer](/docs/protocol/agents/relayer) what to include in `_metadata`. ISMs **must** return one of the supported module types. ```solidity theme={null} enum ModuleType { UNUSED, ROUTING, AGGREGATION, LEGACY_MULTISIG, MERKLE_ROOT_MULTISIG, MESSAGE_ID_MULTISIG, NULL, // used with relayer carrying no metadata CCIP_READ, ARB_L2_TO_L1, POLYGON_POS, OP_STACK } ``` * All ISM contracts must implement the ISM interface, which requires `moduleType` to be defined. This type is branched on by the Relayer in order to determine the required metadata for that ISM. For more information on module types and their metadata formats, see [Protocol](/docs/protocol/ISM/modular-security#core-concepts). * For more information on the available module types and their respective metadata, please visit the ISM docs outlined in this section, e.g. [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM). # Hyperlane AVS Source: https://docs.hyperlane.xyz/docs/protocol/ISM/economic-security/hyperlane-avs Hyperlane's AVS module for EigenLayer This guide will help you understand the Hyperlane's AVS (Actively Validated Service) module built atop EigenLayer, the Ethereum restaking protocol. Hyperlane currently employs a Proof of Authority model for security, in which a trusted group of validators is chosen to maintain [security](/docs/protocol/ISM/standard-ISMs/multisig-ISM). However, if any validator signs erroneously or with malicious intent, there are no repercussions, as these validators have no economic stake. This is the gap that the AVS module is designed to address. ```mermaid theme={null} flowchart TB subgraph Ethereum Staker Operator EL[EigenLayer] H_AVS[Hyperlane AVS] CH1[Challenger1] CH2[Challenger2] CH3[Challenger3] Operator -- "(de)register()" --> H_AVS Staker -- "deposit(operator)" --> EL H_AVS <-..-> EL CH1 -. "handleChallenge(operator)" .-> H_AVS CH2 -. "handleChallenge(operator)" .-> H_AVS CH3 -. "handleChallenge(operator)" .-> H_AVS style H_AVS fill: #FF0099 style EL fill: #1a0c6d style CH1 fill: #006400 style CH2 fill: #006400 style CH3 fill: #006400 end ``` The AVS module uniquely enables [economic security](/docs/protocol/ISM/economic-security/overview) within the Hyperlane protocol with minimum cost to bootstrap a new validator network for each chain it supports. This is achieved by leveraging the shared pool of stake that can secure outbound messages from and between rollups. The main stakeholders in this process are: * **Operators** - EigenLayer operators who opt into the Hyperlane AVS service and start validating outbound messages from the chain(s) specified * **Stakers** - EigenLayer stakers who delegate their stake to the operators to secure the network * **Applications** - Applications leveraging Hyperlane seeking to economically secure their messages across chains Slashing and reward payments are not enabled yet for EigenLayer. In addition to the AVS, signatures & validation must be set up in an [Interchain Security Module (ISM)](/docs/protocol/ISM/modular-security). ### Architecture ```mermaid theme={null} classDiagram namespace Contracts { class AVSDirectory { avsOperatorStatus: address => OperatorAVSRegistrationStatus registerOperatorToAVS(operator, signature) deregisterOperatorFromAVS() } class ECDSAStakeRegistry { quorum: (IStrategy[], multiplier) registerOperatorWithSignature(operator, signature) updateQuorumConfig(quorum, operators[]) } class IServiceManager { <> registerOperatorToAVS(operator,signature) deregisterOperatorFromAVS(operator) } class HyperlaneServiceManager { enrolledChallengers: address => IRemoteChallenger enrollIntoChallengers(IRemoteChallenger[]) startUnenrollment(IRemoteChallenger[]) completeUnenrollment(address[]) } class IRemoteChallenger { <> challengeDelayBlocks() handleChallenge(avsSigningKeyAddress) } class ISlasher { <> freezeOperator(operator) } class IStrategy { <> deposit(token,amt) withdraw(token,amt) } class StrategyManager { depositIntoStrategy(strategy, token, amt) } } ECDSAStakeRegistry--|>IServiceManager ECDSAStakeRegistry--|>IStrategy HyperlaneServiceManager--|>ECDSAStakeRegistry HyperlaneServiceManager--|>IRemoteChallenger HyperlaneServiceManager--|>ISlasher HyperlaneServiceManager--|>AVSDirectory StrategyManager--|>IStrategy IServiceManager<..HyperlaneServiceManager ``` The above class diagram describes the architecture of the current AVS module contracts. Crucially, it describes the *"metaAVS"* design pattern which we support with the `IRemoteChallenger` interface. ### `IRemoteChallenger` Operators on Hyperlane have the flexibility to operate on their chosen chain(s), making the AVS module adaptable to any chain or challenger. However, this flexibility may result in the absence of a universally accepted 'canonical' source of truth for slashing on the Mainnet. This is due to the fact that fraud can only be proven on the origin chain, and so there needs to be a way to transmit that information to the chain on which the stake lives. Embracing the ethos of permissionless interoperability, we believe that application developers should have the ability to define their own source of truth and establish guarantees for their application's economic security. This includes the ability to program challenge conditions and slashing windows. To enable this level of customization, we have introduced the `IRemoteChallenger` interface. The `handleChallenge` function will only be invoked if `ism.verify()` successfully executes on the L1 originating from the chain where the fraudulent signature was detected. As mentioned above, it's critical to set up robust security measures for this underlying ISM. ```solidity theme={null} interface IRemoteChallenger { /// @notice Returns the number of blocks that must be mined before a challenge can be handled /// @return The number of blocks that must be mined before a challenge can be handled function challengeDelayBlocks() external view returns (uint256); /// @notice Handles a challenge for an operator /// @param operator The address of the operator function handleChallenge(address operator) external; } ``` This configuration should be immutable and accessible for any AVS operator to view and opt into. The `handleChallenge` function explicitly encodes how you expect the challenge from the source chain (say Arbitrum) is delivered to Ethereum Mainnet where the AVS contracts and the `IRemoteChallenger` live. For Arbitrum, it can be the rollup's native bridge and for another L1, it can be a committee-based solution. Our interface is challenger implementation agnostic to allow for flexibility in this design area. This allows for us to reuse the existing hook-ISMs setup by calling `handleChallenge()` once `ism.verify()` is successful on the L1. A reasonable `challengeDelayBlocks` would be slightly longer than a week in the case of using a rollup's native bridge. As an operator, you are expected to review the different `IRemoteChallenger` contracts and assess their risk and rewards. If interested, you can enroll into one or multiple challengers directly from the `HyperlaneServiceManager` contract. The IRemoteChallenger implementations are not yet live in production. ### Workflow for registering Prerequisite: operator has to be registered as an EigenLayer Operator (through their CLI) ```mermaid theme={null} sequenceDiagram box Ethereum L1 actor Operator participant ECDSAStakeRegistry participant HSM participant AVSDirectory end Operator->>ECDSAStakeRegistry: registerOperatorWithSignature(operator,operatorSignature) ECDSAStakeRegistry->>HSM: registerOperatorToAVS(operator,operatorSignature) HSM->>AVSDirectory: registerOperatorToAVS(operator,operatorSignature) Operator->>HSM: enrollForChallengers(challenger[]) ``` Operators need to enroll into specific challengers to allow for economic security with permissionless slashing. As an operator, you can inspect every remote challenger and choose for yourself which ones you want to opt into depending on risk. This also means there is no centralized permissioning or whitelisting that would be the bottleneck for adding challengers for different rollup stacks. The operators will be able to unenroll after the unenrollment delay blocks has passed. ### Workflow for deregistering ```mermaid theme={null} sequenceDiagram box Ethereum L1 actor Operator participant HSM participant IRemoteChallenger participant ECDSAStakeRegistry participant AVSDirectory end Operator->>HSM: startUnenrollment(challenger[]) Note over Operator,HSM: Operator waits for delay period Operator->>ECDSAStakeRegistry: deregisterOperatorWithSignature(operator) ECDSAStakeRegistry->>HSM: deregisterOperatorToAVS(operator) Operator->>HSM: completeUnenrollment(challenger[]) HSM->>IRemoteChallenger: challengeDelayBlocks() HSM->>AVSDirectory: deregisterOperatorToAVS(operator) ``` Operators can only deregister themselves after unenrolling from all challengers they are enrolled in, each of which can have its own delay period. This is to ensure that the operator is not able to withdraw their stake before the challenge period has passed for any of the challengers. ### Workflow for staking ```mermaid theme={null} sequenceDiagram box Ethereum L1 actor Staker participant DelegationManager participant StrategyManager participant Strategy1 end Staker->>DelegationManager: delegateTo(operator,approverSignatureAndExpiry) Staker->>StrategyManager: depositIntoStrategy(strategy,token,amt) StrategyManager->>Strategy1: token.transferFrom(sender, strategy, amount) StrategyManager->>DelegationManager: increaseDelegatedShares ``` In EigenLayer's design, staker funds are safeguarded as they are not made accessible to the AVS until slashing is activated. This ensures that no funds are at risk prematurely. Additionally, this design does not allow users to selectively opt into the Hyperlane AVS alone, as staking is managed through the StrategyManager and directed towards a specific operator. ### Workflow for slashing ```mermaid theme={null} sequenceDiagram box Origin Chain actor Watcher participant NativeChallenger end box Ethereum L1 participant IRemoteChallenger participant HSM participant Slasher end Watcher->>NativeChallenger: challenge(address, bytes32,bytes32) NativeChallenger->>IRemoteChallenger: "postChallenge(operator)" via nativeBridge IRemoteChallenger->>HSM: handleChallenge(operator) HSM-->>HSM: checkIfEnrolled(operator) HSM->>Slasher: freezeOperator(operator) ``` The slashing mechanism is designed to be permissionless and flexible. The `IRemoteChallenger` interface allows for different implementations of the slashing mechanism. As an example, the `postChallenge` function is called by the native challenger on the origin chain, which then calls the `handleChallenge` function on the `HyperlaneServiceManager` contract. The `HyperlaneServiceManager` contract then checks if the operator is enrolled in the challenger and calls the `freezeOperator` function on the `Slasher` contract to freeze the operator's stake. Both the challenger and slasher contracts are not yet live in production. This sequence diagram may change based on the final implementation. ### Contract deployment #### Ethereum | Name | Proxy | Implementation | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | [ECDSAStakeRegistry](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/f0df1a4cd1a9a6ec2e01b106941a2d4e42e5ba18/solidity/contracts/avs/ECDSAStakeRegistry.sol) | [0x272CF0BB70D3B4f79414E0823B426d2EaFd48910](https://etherscan.io/address/0x272CF0BB70D3B4f79414E0823B426d2EaFd48910) | [0xa11b1a385287b5167ecca6a38f63abeab981d589](https://etherscan.io/address/0xa11b1a385287b5167ecca6a38f63abeab981d589) | | [HyperlaneServiceManager](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/f0df1a4cd1a9a6ec2e01b106941a2d4e42e5ba18/solidity/contracts/avs/HyperlaneServiceManager.sol) | [0xe8E59c6C8B56F2c178f63BCFC4ce5e5e2359c8fc](https://etherscan.io/address/0xe8E59c6C8B56F2c178f63BCFC4ce5e5e2359c8fc) | [0x3127e69517ec2268dd5745c97194d387a4fc0c45](https://etherscan.io/address/0x3127e69517ec2268dd5745c97194d387a4fc0c45) | #### Holesky | Name | Proxy | Implementation | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | [ECDSAStakeRegistry](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/f0df1a4cd1a9a6ec2e01b106941a2d4e42e5ba18/solidity/contracts/avs/ECDSAStakeRegistry.sol) | [0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72](https://holesky.etherscan.io/address/0xFfa913705484C9BAea32Ffe9945BeA099A1DFF72) | [0x628bc518ed1e0e8c6cbcd574eba0ee29e7f6943e](https://holesky.etherscan.io/address/0x628bc518ed1e0e8c6cbcd574eba0ee29e7f6943e) | | [HyperlaneServiceManager](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/f0df1a4cd1a9a6ec2e01b106941a2d4e42e5ba18/solidity/contracts/avs/HyperlaneServiceManager.sol) | [0xc76E477437065093D353b7d56c81ff54D167B0Ab](https://holesky.etherscan.io/address/0xc76E477437065093D353b7d56c81ff54D167B0Ab) | [0xa3ab7e6ce24e6293bd5320a53329ef2f4de73fca](https://holesky.etherscan.io/address/0xa3ab7e6ce24e6293bd5320a53329ef2f4de73fca) | # Overview Source: https://docs.hyperlane.xyz/docs/protocol/ISM/economic-security/overview How Hyperlane ensures economic security Hyperlane is committed to making fraud costly. Staking and slashing are coming soon and are not yet implemented. This page is shown for informational purposes only. Details may change as the design matures. Staking and slashing allow economic security to be added to ISMs that rely on validator signatures, including [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM) and Optimistic ISM. Hyperlane validators can optionally participate in Hyperlane's staking protocol. Later, if these validators attempt to falsify or censor interchain messages, their stake, and any stake delegated to them, can be slashed. [Interchain Security Modules](/docs/protocol/ISM/modular-security) that depend on signatures from these validators benefit from the additional economic security provided by staking and slashing. ### Verifiable fraud proofs Unlike many other interchain communication protocols, Hyperlane's slashing protocol uses **verifiable fraud proofs**. This means that the Hyperlane protocol is able to verify whether or not a validator signed a fraudulent checkpoint without any participation from trusted parties. This is possible because the stake put up by validators lives on the **same chain** as the state (i.e. the Mailbox merkle root) that they're attesting to. The slashing smart contract can compare the validator signature with the latest root, and do some complicated merkle tree manipulation to confirm whether or not the checkpoint signed by the validator was fraudulent. In many other interchain communication protocols, it is common for a validator's stake to live on a **different chain** than the chain from which an interchain message originated. What this means is that in order for a fraudulent validator to have their stake slashed, the same message passing protocol must relay a message to the chain where the stake lives. You can see the problem with this right? The same validator set where fraud occurred is the mechanism by which evidence of that fraud is delivered, what could go wrong? Hyperlane doesn't want to allow for that possibility, thus in Hyperlane validators must keep their bonded stake on the origin chain for which they are validating. This means fraud proofs are trustlessly verifiable. The record of fraud that is examined for slashing exists in the same environment as the stake to be slashed, leaving no room for error with the process of fraud proofs. # ISM Marketplace Source: https://docs.hyperlane.xyz/docs/protocol/ISM/ism-marketplace The ISM Marketplace is a registry of Interchain Security Modules (ISMs) that lets developers customize how their messages are verified. Application teams can choose ISMs based on their security, latency, and cost requirements (i.e., using stricter verification for high-value messages and lighter ISMs for routine transfers). The marketplace includes both standard ISMs from Abacus Works, and community-contributed ISMs developed by partner teams and community members. ### Standard ISMs Standard ISMs are developed and maintained by Abacus Works. | ISM Name | Type | Stage | Description | | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Aggregation ISM (Static)](/docs/protocol/ISM/standard-ISMs/aggregation-ISM) | Composition | In Production | Combines multiple ISMs together, requiring all or a k‑of‑n subset to agree for validation. | | [Aggregation ISM (Storage)](/docs/protocol/ISM/standard-ISMs/aggregation-ISM#customize) | Composition | In Production | Combines multiple ISMs together, requiring all or a k‑of‑n subset to agree for validation. The module set and threshold are stored in state and can be updated after deployment. | | [Routing ISM](/docs/protocol/ISM/standard-ISMs/routing-ISM) | Composition | In Production | Directs messages to different ISMs depending on the origin domain. | | Amount Routing ISM | Composition | In Production | Routes messages to different ISMs based on the amount of the transfer. | | [Fallback Routing ISM](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/routing/DefaultFallbackRoutingIsm.sol) | Composition | In Production | Provides a backup ISM path if the origin domain is not configured in the routing map. | | ICA Routing ISM | Composition | In Production | Routes messages through Interchain Accounts (ICA). | | [Pausable ISM](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/PausableIsm.sol) | Composition | In Production | Allows message flow to be paused in emergencies. | | Rate Limited ISM | Composition | In Production | Uses a token bucket rate limiter to throttle the amount that can be sent via HWR within a given time interval. Only applies to HWR applications/message encoding. | | [Merkle Root Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM#merklerootmultisigismmetadata) | Security | In Production | Verifies k‑of‑n signatures on a Merkle root and employs Merkle proofs of message IDs in this root. | | [Merkle Root Multisig ISM (Storage)](/docs/protocol/ISM/standard-ISMs/multisig-ISM#customize) | Security | In Production | Verifies k‑of‑n signatures on a Merkle root and employs Merkle proofs of message IDs in this root. The module set and threshold are stored in state and can be updated after deployment. | | [Message ID Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM#messageidmultisigismmetadata) | Security | In Production | Verifies k‑of‑n signatures on a message ID. The signatures are from the checkpoint struct and are shared across related ISMs. | | [Message ID Multisig ISM (Storage)](/docs/protocol/ISM/standard-ISMs/multisig-ISM#customize) | Security | In Production | Verifies k‑of‑n signatures on a message ID. The signatures are from the checkpoint struct and are shared across related ISMs. The module set and threshold are stored in state and can be updated after deployment. | | Weighted Merkle Root Multisig ISM | Security | In Development | A weighted voting system, extending Merkle Root multisig, where each signer’s influence is weighted by their stake. | | Weighted Message ID Multisig ISM | Security | In Development | A weighted voting system on top of Message ID multisig. | | [Offchain Lookup ISM](/docs/protocol/ISM/standard-ISMs/offchain-lookup-ISM) | Security | In Production | Functions as an abstraction for building verification logic that leverages external data sources for validation. | | [Chainlink CCIP ISM](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/hook/CCIPIsm.sol) | Security | In Production | Leverages Chainlink CCIP to validate messages. | | [Arbitrum L2 to L1 ISM](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/hook/ArbL2ToL1Ism.sol) | Security | In Development | Verifies cross-chain messages from Arbitrum L2 to Ethereum L1 using Arbitrum’s native proof system. | | [OP Stack ISM](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/hook/OPStackIsm.sol) | Security | In Production | Verifies cross-chain messages from OP Stack rollups using the OP Stack native security model. | | [Noop ISM / Test ISM](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/NoopIsm.sol) | Security | In Production | ISM for testing purposes. | | [Trusted Relayer ISM](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/TrustedRelayerIsm.sol) | Security | In Production | Relies on a trusted relayer to deliver the message on the Mailbox. | * Static variants are immutable in bytecode. * Storage variants keep module sets and thresholds mutable in state. ### Community ISMs Community ISMs are developed and maintained by contributors outside Abacus Works. | ISM Name | Type | Stage | | ------------------------ | -------- | -------------- | | Axelar ISM | Security | In Development | | Celestia ZK ISM | Security | In Development | | Noble ISM | Security | In Development | | Polygon zkEVM V2 ISM | Security | In Development | | Succinct Lightclient ISM | Security | In Development | | Timelock ISM | Security | In Development | | Wormhole ISM | Security | In Development | # ISM Overview Source: https://docs.hyperlane.xyz/docs/protocol/ISM/modular-security Hyperlane is secured by Interchain Security Modules (ISMs). ISMs are smart contracts that are responsible for verifying that interchain messages being delivered on the destination chain were on the origin chain. ```mermaid theme={null} flowchart LR subgraph Destination Chain ISM[InterchainSecurityModule] Recipient[Recipient] M_D[(Mailbox)] M_D -- "verify(metadata, message)" --> ISM ISM -. "interchainSecurityModule()" .- Recipient M_D -- "handle(origin, sender, body)" --> Recipient end ``` ## Core Concepts ### Default vs Custom ISM Developers can either use the [Mailbox's](/docs/protocol/core/mailbox) default ISM or specify their own application-specific ISM. Application-specific ISM can be: * **Configured**: Use pre-built ISMs with custom parameters * **Composed**: Combine multiple ISMs together like security "legos" * **Customized**: Create entirely new ISMs tailored to specific needs The "default ISM" refers to the pre-configured security module on the Mailbox contract (that is the Multisig ISM) which is used when applications don't specify their own custom ISM. #### Configure Hyperlane defines a set of [pre-built ISMs](#standard-isms). Developers can deploy any of these contracts "off-the-shelf" and configure them with their own parameters. For example, application developers that want increased sovereignty over interchain security could deploy a [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM) configured with validators sourced from their own community. #### Compose ISMs act as "security legos". Developers can mix and match different ISMs together to encode a security model that best fits their needs. For example, application developers that want additional security could deploy an [Aggregation ISM](/docs/protocol/ISM/standard-ISMs/aggregation-ISM) that requires verification by both a [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM) configured with validators from the Hyperlane community, **and** a Wormhole ISM that verifies that a quorum of the [Wormhole](https://wormhole.com/) validator set verified the message. #### Customize ISMs are fully customizable. Developers can write their own ISMs, tailoring them to the needs of their application. For example, application developers can build ISMs that adjust security models based on message content. High value and infrequent messages (e.g. governance) could be verified by a security model that prioritizes safety over latency and gas costs. Lower value and more frequent messages could be verified by a security model that prioritizes latency and gas costs over safety. Learn how to [Create your own ISM](/docs/protocol/ISM/custom-ISM) # Sequence Diagram Source: https://docs.hyperlane.xyz/docs/protocol/ISM/sequence-diagram When a message is sent between chains, it goes through a verification process to ensure its authenticity. This page explains how that process works. ## Overview The verification process involves three key components: 1. The **Mailbox contract** - The main entry point for message processing 2. The **ISM (Interchain Security Module)** - The security verification contract 3. The **Recipient contract** - The application that receives the message ## Sequence Diagram * If the recipient does not implement `ISpecifiesInterchainSecurityModule` or `recipient.interchainSecurityModule()` returns `address(0)`, the default ISM configured on the [Mailbox](/docs/protocol/core/mailbox) will be used to verify the message. * This is omitted from the sequence diagram for clarity. ```mermaid theme={null} sequenceDiagram participant Relayer participant Mailbox participant ISM participant Recipient Relayer-->>ISM: moduleType() ISM-->>Relayer: ISM type Relayer->>Mailbox: process(metadata, message) Mailbox-->>Recipient: interchainSecurityModule() Recipient-->>Mailbox: ISM address Mailbox->>ISM: verify(metadata, message) ISM-->>Mailbox: true Mailbox->>Recipient: handle(origin, sender, body) ``` ## How It Works 1. **Type Identification** * The Relayer calls `moduleType()` on the ISM to determine its category * Based on this type (e.g., `MULTISIG`, `ROUTING`, `AGGREGATION`), the Relayer knows what verification proof to collect * For Multisig ISMs, this means gathering cryptographic signatures from validators 2. **Message Submission** * The Relayer calls `Mailbox.process()` providing both: * The original message * The collected verification metadata 3. **Verification Process** * Mailbox queries the recipient contract via `interchainSecurityModule()` * If no ISM is specified, Mailbox uses the default ISM * Mailbox then forwards the message and metadata to the ISM's `verify()` function * The ISM executes its security logic (e.g., signature verification, threshold checking) 4. **Message Delivery** * Upon successful verification (when `verify()` returns `true`), Mailbox calls `recipient.handle()` * If verification fails, the transaction reverts and the message is rejected # Aggregation ISM Source: https://docs.hyperlane.xyz/docs/protocol/ISM/standard-ISMs/aggregation-ISM Developers can use an `AggregationISM` to combine security from multiple ISMs. Simply put, an `AggregationISM` requires that `m` of `n` ISMs verify a particular interchain message. Developers can configure, for each origin chain, a set of `n` ISMs, and the number of ISMs needed to verify a message. `AggregationISMs` can aggregate the security of any ISMs. For example, users can deploy a [Multisig ISM](./multisig-ISM) with their own validator set, and deploy an `AggregationISM` that aggregates that ISM with the Hyperlane default ISM. ## Interface `AggregationISMs` must implement the `IAggregationIsm` interface. ```solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; import {IInterchainSecurityModule} from "../IInterchainSecurityModule.sol"; interface IAggregationIsm is IInterchainSecurityModule { /** * @notice Returns the set of ISMs responsible for verifying _message * and the number of ISMs that must verify * @dev Can change based on the content of _message * @param _message Hyperlane formatted interchain message * @return modules The array of ISM addresses * @return threshold The number of modules needed to verify */ function modulesAndThreshold( bytes calldata _message ) external view returns (address[] memory modules, uint8 threshold); } ``` ## Configure The [Hyperlane monorepo](https://github.com/hyperlane-xyz/hyperlane-monorepo) contains an `AggregationISM` implementation that application developers can deploy off-the-shelf, specifying their desired configuration. Developers can configure, for each origin chain, a set of `n` ISMs, and the number of ISMs needed to verify a message. `AggregationISMs` can aggregate the security of any ISMs. For example, users can deploy a [Multisig ISM](./multisig-ISM) with their own validator set, and deploy an `AggregationISM` that aggregates that ISM with the Hyperlane default ISM. ## Customize The hyperlane-monorepo contains an abstract `AggregationISM` implementation that application developers can fork. Developers simply need to implement the `modulesAndThreshold()` function. By creating a custom implementation, application developers can tailor the security provided by a `AggregationISM` to the needs of their application. For example, a custom implementation could require that low value messages be verified by a [Multisig ISM](./multisig-ISM), and require that high value messages *also* be verified by a Wormhole ISM. # Multisig ISM Source: https://docs.hyperlane.xyz/docs/protocol/ISM/standard-ISMs/multisig-ISM The `MultisigISM` is one of the most commonly used ISM types. These ISMs verify that `m` of `n` [Validators](/docs/protocol/agents/validators) have attested to the validity of a particular interchain message. ## Multisig Module Types There are two types of `MultisigISM` modules: ```solidity theme={null} enum Types { ... MERKLE_ROOT_MULTISIG, MESSAGE_ID_MULTISIG, ... } ``` ### MerkleRootMultisigIsmMetadata **Type: `Types.MERKLE_ROOT_MULTISIG`** **Format of metadata:** | **Component** | **Length (bytes)** | **Description** | | -------------------------------------------- | ------------------ | ------------------------------------------------------- | | 1st component | 32 | Origin merkle tree address | | 2nd component | 4 | Index of message ID in merkle tree | | 3rd component | 32 | Signed checkpoint message ID | | 4th component | 1024 | Merkle proof | | 5th component | 4 | Signed checkpoint index (computed from proof and index) | | 6th component (len == threshold \* 65 bytes) | threshold \* 65 | Validator signatures | ### MessageIdMultisigIsmMetadata **Type: `Types.MESSAGE_ID_MULTISIG`** **Format of metadata:** | **Component** | **Length (bytes)** | **Description** | | -------------------------------------------- | ------------------ | -------------------------- | | 1st component | 32 | Origin merkle tree address | | 2nd component | 32 | Signed checkpoint root | | 3rd component | 4 | Signed checkpoint index | | 4th component (len == threshold \* 65 bytes) | threshold \* 65 | Validator signatures | ## Interface `MultisigISMs` must implement the `IMultisigIsm` interface. ```solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; import {IInterchainSecurityModule} from "../IInterchainSecurityModule.sol"; interface IMultisigIsm is IInterchainSecurityModule { /** * @notice Returns the set of validators responsible for verifying _message * and the number of signatures required * @dev Can change based on the content of _message * @param _message Hyperlane formatted interchain message * @return validators The array of validator addresses * @return threshold The number of validator signatures needed */ function validatorsAndThreshold( bytes calldata _message ) external view returns (address[] memory validators, uint8 threshold); } ``` ## Configure The hyperlane-monorepo contains [`MultisigISM` implementations](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/solidity/contracts/isms/multisig) (including a [legacy](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/multisig/LegacyMultisigIsm.sol) version and more gas-efficient [versions](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/multisig/StaticMultisigIsm.sol) deployable via factories) that application developers can deploy off-the-shelf, specifying their desired configuration. To configure a `MultisigISM` instance: 1. Developers define the set of `n` Validators on each origin chain. 2. A threshold is set, specifying the number (`m`) of Validator signatures required to confirm a message. Validator signatures are **not** specific to an ISM. In other words, developers can configure their `MultisigISM` to use **any** validator that's running on Hyperlane. ## Customize For more specific use cases, developers can fork the abstract `MultisigISM` implementation provided in the Hyperlane monorepo. The primary customization involves implementing the `validatorsAndThreshold()` function. Custom implementations allow developers to adjust the security model to meet the needs of their application. For example, a custom implementation could vary the number of signatures required, based on the content of the message being verified. # Offchain Lookup ISM Source: https://docs.hyperlane.xyz/docs/protocol/ISM/standard-ISMs/offchain-lookup-ISM Using a Offchain Lookup ISM provides developers with a lot of flexibility for verifying interchain messages. Ultimately, every other kind of ISM can be implemented as a Offchain Lookup ISM, so when building new types of ISM's moving forward it's encouraged to build Offchain Lookup ISM's as all the relayer integration work has already been done. One caveat to keep in mind for the Offchain Lookup ISM's is that they do introduce a dependency on an external (to the blockchain), but self hostable, API. If this is a hard blocker for your use case, you may want to consider other message verification techniques. Before building a Offchain Lookup ISM it's worth familiarizing yourself with the [CCIP Read—Secure offchain data retrieval](https://eips.ethereum.org/EIPS/eip-3668). The specification describes a generalized protocol that allows smart contracts on EVM compatible chains to query and consume offchain data. ## How it works A relayer will constantly listening to `Dispatch` events emitted from Hyperlane [Mailboxes](/docs/protocol/core/mailbox). When a message is sent and picked up by a relayer, the relayer will query the destination ISM for information on how to process the message and if delivery will be successful. The correct `moduleType` variable will need to be set on your ISM so that the relayer knows it's a Offchain Lookup ISM. To make sure this is configured correctly, you can inherit from the `AbstractCcipReadIsm` in `@hyperlane-xyz/core`. The relayer will then call the `getOffchainVerifyInfo(bytes)` function on the ISM with the contents of the message being delivered. This function should revert with the `OffchainLookup` error described in the [interface](#interface) section below. The relayer will query the endpoint specified in this revert message and pass the provided response and original message to the `process(bytes,bytes)` function of the destination `Mailbox`. ## Interface The Offchain Lookup ISM must implement the `ICcipReadIsm` interface and should extend the `AbstractCcipReadIsm`, a convenience contract that sets the `moduleType` correctly. ```solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; import {IInterchainSecurityModule} from "../IInterchainSecurityModule.sol"; interface ICcipReadIsm is IInterchainSecurityModule { /// @dev https://eips.ethereum.org/EIPS/eip-3668 /// @param sender the address of the contract making the call, usually address(this) /// @param urls the URLs to query for offchain data /// @param callData context needed for offchain service to service request /// @param callbackFunction function selector to call with offchain information /// @param extraData additional passthrough information to call callbackFunction with error OffchainLookup( address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData ); /** * @notice Reverts with the data needed to query information offchain * and be submitted via the origin mailbox * @dev See https://eips.ethereum.org/EIPS/eip-3668 for more information * @param _message data that will help construct the offchain query */ function getOffchainVerifyInfo(bytes calldata _message) external view; } ``` ## Configure A great example for reference while developing Offchain Lookup ISM's exists as the [ChainlinkISM](https://github.com/AlexBHarley/permissionless-chainlink-feeds). The `ChainlinkISM` is initialized with a set of Chainlink oracles and verifies the price feed data provided has been signed over by some subset of the signers. ### API As per CCIP Read, the offchain API will need to return JSON data with the form, ```json theme={null} { "data": "..." } ``` The relayer will pass this `data` property as the `metadata` parameter to `Mailbox.process(bytes metadata, bytes message)`. Note that in the case of the Chainlink ISM, where the receiver of the data also acts as the verifying ISM, `data` is just the raw transaction sent to submit price feed data with associated signatures. The `message` property is somewhat redundant. ### Contract When setting up the ISM, the `getOffchainVerifyInfo` and `verify` functions are the important ones to specify. * `getOffchainVerifyInfo` function should revert with an `OffchainLookup` error that instructs the relayer to query the given API endpoint. The `OffchainLookup` error allows for an array of API endpoints to be provided, so you can enforce any level of redundancy you'd like * `verify` must take the provided `metadata` and assert its legitimacy. Again the [ChainlinkISM implementation](https://github.com/AlexBHarley/permissionless-chainlink-feeds/blob/main/apps/contracts/contracts/ChainlinkAggregator.sol#L114) can be a useful reference point when developing this logic for your own ISM. Below is the scaffold of what a Offchain Lookup ISM could look like, where the ISM is also the receiver of the message, as per the Chainlink ISM. ```solidity theme={null} pragma solidity ^0.8.13; import {AbstractCcipReadIsm} from "@hyperlane-xyz/core/contracts/isms/ccip-read/AbstractCcipReadIsm.sol"; import {IInterchainSecurityModule, ISpecifiesInterchainSecurityModule} from "@hyperlane-xyz/core/contracts/interfaces/IInterchainSecurityModule.sol"; import {IMailbox} from "@hyperlane-xyz/core/contracts/interfaces/IMailbox.sol"; import {Message} from "@hyperlane-xyz/core/contracts/libs/Message.sol"; contract MyCcipReadIsm is AbstractCcipReadIsm, ISpecifiesInterchainSecurityModule { using Message for bytes; IMailbox mailbox; ... /** * No-op, everything happens in the verify function */ function handle(uint32, bytes32, bytes calldata _report) public {} /** * @param _metadata ABI encoded module metadata * @param _message Formatted Hyperlane message (see Message.sol). */ function verify( bytes calldata _metadata, bytes calldata _message ) external returns (bool) { ... } function interchainSecurityModule() external view returns (IInterchainSecurityModule) { return IInterchainSecurityModule(address(this)); } function getOffchainVerifyInfo( bytes calldata _message ) external view override { revert OffchainLookup( address(this), offchainUrls, _message, MyCcipReadIsm.process.selector, _message ); } /** * Provided for full CCIP Read specification compatibility. Relayers * will call the Mailbox directly regardless of the selector specified * in the `OffchainLookup` error */ function process( bytes calldata _metadata, bytes calldata _message ) external { mailbox.process(_metadata, _message); } } ``` # Rate Limited ISM Source: https://docs.hyperlane.xyz/docs/protocol/ISM/standard-ISMs/rate-limited-ISM Add configurable transfer volume caps to Hyperlane Warp Routes The `RateLimitedIsm` is an ISM for warp routes that caps the token volume transferable to a destination chain within a configurable window. It pairs with a [`RateLimitedHook`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/hooks/warp-route/RateLimitedHook.sol) on the origin side, giving warp route deployers bidirectional control over transfer throughput. ## How it works Both contracts inherit from [`RateLimited`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/libs/RateLimited.sol), which implements a token bucket algorithm: * The bucket starts full at deployment (`filledLevel = maxCapacity`). * It refills continuously at `refillRate = maxCapacity / DURATION` tokens per second. * Each transfer consumes capacity equal to the token amount in the message. * If a transfer would exceed the current available capacity, it reverts with `RateLimitExceeded`. * After a full `DURATION` of inactivity the bucket is fully restored. ```solidity theme={null} uint256 public constant DURATION = 1 days; // 86400 seconds ``` ``` maxCapacity = refillRate × DURATION currentLevel ≈ previousLevel + (elapsed × refillRate) ``` The refill window is `DURATION`, set to 1 day. The capacity — `maxCapacity`, expressed in the token's base unit (e.g. `1_000_000e6` for 1M USDC) — is set at deployment and can be updated by the warp route owner at any time. ## Contracts | Contract | Chain side | Role | | ------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | ---------------------------------------------- | | [`RateLimitedHook`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/hooks/warp-route/RateLimitedHook.sol) | Origin | Enforces the limit at dispatch time (outbound) | | [`RateLimitedIsm`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/warp-route/RateLimitedIsm.sol) | Destination | Enforces the limit at delivery time (inbound) | Either contract can be deployed independently or together. Deploying both provides defense in depth: transfers are blocked on the origin before they are relayed, and again on the destination before funds are released. ### RateLimitedIsm The `verify()` function: 1. Requires the message recipient matches the configured `recipient` address (`onlyRecipient`). 2. Requires the message has not already been validated — tracked via `messageValidated[messageId]` (replay protection). 3. Confirms the message was delivered by the Mailbox (`_isDelivered`). 4. Extracts the token amount and calls `_validateAndConsumeFilledLevel`. ```solidity theme={null} function verify( bytes calldata, bytes calldata _message ) external onlyRecipient(_message) validateMessageOnce(_message) returns (bool) { require(_isDelivered(_message.id()), "InvalidDeliveredMessage"); uint256 newAmount = _message.body().amount(); _validateAndConsumeFilledLevel(newAmount); return true; } ``` ### RateLimitedHook The `_postDispatch()` function: 1. Requires the message sender matches the configured `sender` address (`onlySender`). 2. Requires the message has not already been processed (replay protection). 3. Confirms this is the most recently dispatched message (`_isLatestDispatched`). 4. Extracts the token amount and calls `_validateAndConsumeFilledLevel`. ```solidity theme={null} function _postDispatch( bytes calldata, bytes calldata _message ) internal override onlySender(_message) validateMessageOnce(_message) { require(_isLatestDispatched(_message.id()), "InvalidDispatchedMessage"); uint256 newAmount = _message.body().amount(); _validateAndConsumeFilledLevel(newAmount); } ``` ## Properties ### Blast radius containment Rate limits directly bound the maximum loss from a compromised bridge. If an attacker finds an exploit in the token contract or a validator key is leaked, they can drain at most `maxCapacity` tokens before the bucket empties and all transfers revert with `RateLimitExceeded`. This gives warp route owners time to detect the incident and pause or upgrade the route before a full treasury loss. ### Replay protection Both contracts maintain a `messageValidated[messageId]` mapping. A message that has already consumed capacity cannot be re-submitted, preventing double-spend attacks via message replay. ### Recipient and sender binding `RateLimitedIsm` is constructed with a fixed `recipient` address and rejects any message bound for a different contract. `RateLimitedHook` is constructed with a fixed `sender` address and rejects messages from unauthorized callers. This prevents the contracts from being used to validate or throttle transfers for unintended warp routes. ### Owner-controlled capacity `setRefillRate(uint256 _capacity)` is `onlyOwner`, allowing warp route owners to adjust the cap without redeploying: ```solidity theme={null} // SDK enforces capacity >= DURATION (86400) and rounds down to nearest multiple // e.g. 86401 → refillRate = 1 → effective maxCapacity = 86400 (1 unit lost) ism.setRefillRate(newCapacity); // new refillRate = newCapacity / DURATION ``` ### Aggregation ISM compatibility `RateLimitedIsm` can be nested inside an `AggregationIsm` to layer rate limiting on top of other security checks — for example, requiring both a `MultisigIsm` and a `RateLimitedIsm` to pass before a message is delivered. This requires relayer version [`agents-v2.2.0`](https://github.com/hyperlane-xyz/hyperlane-monorepo/releases/tag/agents-v2.2.0) or later. For defense in depth, pair `RateLimitedIsm` with a [`PausableIsm`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/PausableIsm.sol) inside an `AggregationIsm`. The rate limit caps the damage during an active exploit while the owner detects the incident and pauses the route to fully close it. ## SDK configuration The TypeScript SDK and CLI support `IsmType.RATE_LIMITED`, enabling warp route configs to specify a `RateLimitedIsm` directly. The SDK type string is `'rateLimitedIsm'`. See [`typescript/sdk/src/ism/types.ts`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/typescript/sdk/src/ism/types.ts). The config schema accepts: | Field | Type | Required | Notes | | ------------- | ------------------ | -------- | ---------------------------------------------------------------------------- | | `type` | `'rateLimitedIsm'` | Yes | — | | `maxCapacity` | `string` (bigint) | Yes | Must be ≥ 86400; rounded down to nearest multiple of 86400 | | `recipient` | address | No | Defaults to the warp route address | | `owner` | address | No | Defaults to the deployer; receives `onlyOwner` rights (e.g. `setRefillRate`) | Example warp route ISM config: ```yaml theme={null} interchainSecurityModule: type: rateLimitedIsm maxCapacity: "1000000000000" # 1M USDC (6 decimals) per day ``` ## Deployment ```solidity theme={null} // Destination chain — ISM RateLimitedIsm ism = new RateLimitedIsm( mailbox, // Mailbox address on destination 1_000_000e6, // maxCapacity in token base units warpRouteAddress ); // Origin chain — Hook (optional, for bidirectional enforcement) RateLimitedHook hook = new RateLimitedHook( mailbox, // Mailbox address on origin 1_000_000e6, // maxCapacity in token base units warpRouteAddress ); ``` # Routing ISM Source: https://docs.hyperlane.xyz/docs/protocol/ISM/standard-ISMs/routing-ISM Developers can use a `RoutingISM` to delegate message verification to a different ISM. This allows developers to change security models based on message content or application context. This ISM simply switches security models depending on the origin chain of the message. A simple use case for this is to use different [Multisig ISM](./multisig-ISM) validator sets for each chain. Eventually, you could imagine a `DomainRoutingIsm` routing to different light-client-based ISMs, depending on the type of consensus protocol used on the origin chain. ## Interface `RoutingISMs` must implement the `IRoutingIsm` interface. ```solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; import {IInterchainSecurityModule} from "../IInterchainSecurityModule.sol"; interface IRoutingIsm is IInterchainSecurityModule { /** * @notice Returns the ISM responsible for verifying _message * @dev Can change based on the content of _message * @param _message Hyperlane formatted interchain message * @return module The ISM to use to verify _message */ function route( bytes calldata _message ) external view returns (IInterchainSecurityModule module); } ``` ## Configure The hyperlane-monorepo contains a `RoutingISM` implementation, `DomainRoutingIsm` and `DefaultFallbackRoutingIsm`, that application developers can deploy off-the-shelf, specifying their desired configuration. ## Customize The hyperlane-monorepo contains an abstract `RoutingISM` implementation that application developers can fork. Developers simply need to implement the `route()` function. By creating a custom implementation, application developers can tailor the security provided by a `RoutingISM` to the needs of their application. For example, a custom implementation could change security models based on the contents of the message or the state of the application receiving the message. # Overview Source: https://docs.hyperlane.xyz/docs/protocol/agents/overview The Hyperlane protocol decouples the transport layer from the security layer of cross-chain message passing. To run a deployment, it relies on offchain agents that observe onchain activity and carry out either the transport or security aspects of the protocol. These agents are implemented in Rust and distributed as Docker images and binaries. 1. [Relayers](/docs/protocol/agents/relayer) fulfill the message transport requirement of the protocol. They aggregate off-chain security metadata for the [`IInterchainSecurityModule` interface](/docs/protocol/ISM/modular-security#core-concepts) and deliver messages to their recipients. 2. [Validators](/docs/protocol/agents/validators) fulfill the security requirement of the protocol, as part of the [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM) or the [Hyperlane AVS](/docs/protocol/ISM/economic-security/hyperlane-avs), by attesting to the validity of [Mailbox](/docs/protocol/core/mailbox) messages and making their signatures available to a relayer. # Relayer Source: https://docs.hyperlane.xyz/docs/protocol/agents/relayer The relayer runs the transport layer of the Hyperlane protocol by delivering messages from origin to destination chains. Depending on the [Interchain Security Module (ISM)](/docs/protocol/ISM/modular-security) specified by the recipient, metadata may be required to prove the security of the message, such as Validator signatures for the [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM), merkle proofs, zero-knowledge proofs, and more. So before attempting to deliver, the relayer gathers any ISM-specific metadata. The relayer will periodically retry metadata gathering and message submission. This is important to improve resilience against disruptions, such as: no gas payment made to pay for delivery, insufficient relayer balance, temporary spikes in transaction fees on the destination, Validator downtime. ### Relayer Incentives Message senders are charged for delivery on the origin chain, and it is the relayer operator's responsibility to rebalance revenue to destination chain accounts so delivery transaction fees can always be paid for. The relayer does not receive direct token incentives from the protocol, but operators can configure their fee structure for providing their critical service. For more information, check out [Interchain Gas Payments (IGPs)](/docs/protocol/core/interchain-gas-payment). ### Operating a Relayer Relayers can easily configure the messages that they wish to process. Currently, the relayer will support: 1. A sender / recipient whitelist. 2. A sender / recipient blacklist. 3. The ability to accept [payments on the origin chain](../../reference/messaging/send#quote-dispatch) for processing a message on the destination chain. While permissionless to run, it's up to the message sender to pick which relayer to pay for delivery. [Mailbox](/docs/protocol/core/mailbox) integrations usually default to always paying the same relayer, but message senders can opt out of this. For convenience, Hyperlane will run an open source and configurable relayer agent, implemented as a Rust binary. If you'd like to run your own relayer, we've open sourced the [binary here](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/rust/main/agents/relayer). Running your own relayer involves deploying an [IGP contract](/docs/protocol/core/interchain-gas-payment) and maintaining token exchange rates and gas prices inside of it to accurately charge message delivery fees. Want to run a relayer? Follow the [Relayer](/docs/operate/relayer/run-relayer) guide. ## In more detail The relayer is comprised of two main tasks: an Indexer for each origin, and a Submitter for each destination. High-level Relayer Architecture ### The Indexer Both new and historic messages are indexed by querying [Mailbox](/docs/protocol/core/mailbox) contract events using RPCs. [Gas payments](/docs/protocol/core/interchain-gas-payment) are also indexed to confirm senders paid for delivery, and certain ISMs use additional origin chain data. This is the case with the Multisig ISM, which relies on the Merkle Tree Hook contract to inform the Relayer about which Validator signature corresponds to which message. There is a standalone indexing task spawned for every event type (Messages, IGP, Merkle Tree insertion). The indexer writes to a local database (RocksDB) as a means of caching, as well as communicating with the Submitter task - the latter periodically polls the database to check if new messages were dispatched. The relayer prioritizes new messages over old ones, under the assumption that old ones are more likely to have been delivered. This means that when (re)started, two pointers are created: a forward one and a backward one, both initialized to the blockchain tip and using the monotonically increasing `nonce` field of messages to iterate. A similar approach is used to index the other events, but some lack a sequence number and can be missed if incorrect RPC responses are received - which happens very often. As such, the message indexing task sends transaction IDs where it found events to the other indexing tasks, guaranteeing no Hyperlane event is missed as long as it occurred within the same transaction as the `Mailbox.dispatch()` call. ### The Submitter Messages go through four stages as part of the Submitter, which are spawned as independent tasks described below.
Submitter Task Description
Message Processor Polls the local database to check if there are any undelivered messages and pushes them to the Prepare step's queue.
Prepare Task Pops messages from its queue, ensures gas was paid, fetches any metadata and simulates the message delivery transaction. If the simulation succeeds, the message is pushed to the Submit step's queue. Otherwise, the message is pushed back to the Prepare queue.
Submit Task Pops messages from its queue, and sends the delivery transaction onchain. Deliveries are batched whenever possible. If there is no error broadcasting the transaction, the message is pushed to the Confirm step's queue. Otherwise, the message is pushed back to the Prepare queue.
Confirm Task Awaits finality; if a chain reorg occurs, or the delivery transaction reverts, the message is pushed back to the Prepare queue.
Messages are delivered to their recipient by calling `Mailbox.process()` on the destination chain with the aforementioned metadata. The retry count of a message determines its next delivery attempt according to an exponential backoff strategy. Currently, there is no fixed maximum number of retries after which the relayer will cease to attempt processing a message. However, this is not a guarantee of indefinite retries, and operators should not rely on this as a service level agreement (SLA). #### Retry Strategy If a delivery attempt is unsuccessful, the relayer retries the delivery using an adaptive backoff strategy. This strategy is optimized to support ISMs with longer finality or processing times and ensures retries continue over a long enough period to recover from temporary issues. | Retry # Range | Delay Between Retries | | ------------- | ------------------------------------------------------------ | | 1 | 5 seconds | | 2 | 10 seconds | | 3 | 30 seconds | | 4 | 1 minute | | 5–24 | 3 minutes | | 25–39 | Starts at 5 min, increases linearly (adds 1.5 min per retry) | | 40–44 | 30 minutes | | 45–49 | 1 hour | | 50+ | Gradually increases to several hours and eventually days | You can view the implementation [here](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/1d8ada64736b09d9878d2a11568c04d522f515b8/rust/main/agents/relayer/src/msg/pending_message.rs#L733). *Note: These values are approximate and subject to change.* # Validators Source: https://docs.hyperlane.xyz/docs/protocol/agents/validators Validators run as part of the [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM) or the [Economic Security Module](/docs/protocol/ISM/economic-security/overview), fulfilling the security layer of the Hyperlane protocol. If using a different ISM, validators are not required. They are responsible for attesting to messages by signing a merkle root (also referred to as a checkpoint) when new dispatches happen in the [Mailbox](/docs/protocol/core/mailbox). Signatures must be made available for anyone (typically the Relayer) to fetch and submit alongside the message to the destination chain. Unlike many other protocols, Hyperlane does **not** have an enshrined validator set. Anyone is free to run their own validator, as long as the receiver contract specifies a [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM) that includes their validator. Validator checkpoints are public. This ensures the transport layer is permissionless, since anyone can fetch the signatures and call `Mailbox.process()` to deliver the message. The Relayer merely provides a convenience service for message senders. It's important that the Validator only signs finalized checkpoints to avoid compromising the safety of the protocol. Signing messages that get reorged out leads to slashing in the economic security module. The Validator agent connects to a single chain to check for new messages. If validating multiple chains, multiple instances of this agent must be run. Hyperlane is developing the validator as a binary implemented in Rust that can be easily run by anyone. Operationally, validators need to run this binary and have access to an RPC provider or node for the chain that they are validating for. We hope that the majority of Hyperlane validators will come from each chain's existing node operator community. Want to run a validator? Follow the [validators guide](../../operate/validators/run-validators). ## In more detail The Validator agent uses two key types: one for signing transactions on the blockchain it is validating, and another for signing checkpoints on the Ethereum-compatible ECDSA curve. Since checkpoints are public, when a Validator first starts operating it must announce its checkpoint location via an onchain `announce` transaction. This is the only transaction ever submitted by the Validator agent; the blockchain-specific key is otherwise not used at all. There is also the option of manually announcing a new Validator to avoid configuring the blockchain-specific key. Validators can be announced by anyone. For messages using a [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM#interface), validators read the current merkle root by calling `MerkleTreeHook.latestCheckpoint()`. Validators use the `MerkleTreeHook.latestCheckpoint()` function to determine when new transactions need to be indexed. This polling mechanism ensures validators can start signing new messages without the need to backfill the entire tree. ### Multisig ISM Prerequisites To validate messages from an origin chain, the Validator's checkpoint signing key must be registered in the [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM#interface) specified by the destination chain recipient. This can only be done when the ISM contract is deployed, but this is easily done by sending a `deploy(validatorAddresses, threshold)` transaction on any implementation of [StaticThresholdAddressSetFactory](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/be4617b18ba638e0ef5a5326614bc4f8c58d25f9/solidity/contracts/libs/StaticAddressSetFactory.sol#L10). ### AVS Operator Prerequisites To run a Validator for the EigenLayer AVS and provide [economic security](/docs/protocol/ISM/economic-security/overview), the Validator must register as an AVS operator. See more details in the [AVS Operator Guide](/docs/operate/guides/avs-operator-guide). ## Architecture The validator is comprised of two main tasks: an Indexer for the origin chain, and a Checkpoint Submitter to publish signed merkle roots. ### The Indexer The only event type indexed by the Validator is `InsertedIntoTree` from the Merkle Tree Hook [contract](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/be4617b18ba638e0ef5a5326614bc4f8c58d25f9/solidity/contracts/hooks/MerkleTreeHook.sol#L32) that the [Mailbox](/docs/protocol/core/mailbox) calls whenever a new message is dispatched. This happens over RPC, and the agent builds an in-memory merkle tree based on the merkle insertion events, which are also cached to a local RocksDB database for fast startup. Whenever a new message is dispatched, the Checkpoint Submitter generates a checkpoint from the in-memory tree and adds it to a queue for processing. ### The Checkpoint Submitter The checkpoint submitter uses the ECDSA key to sign checkpoints and publish them to highly-available storage. The schema of a checkpoint is ```rust theme={null} pub struct Checkpoint { /// The merkle tree hook address pub merkle_tree_hook_address: H256, /// The mailbox / merkle tree hook domain pub mailbox_domain: u32, /// The checkpointed root pub root: H256, /// The index of the checkpoint pub index: u32, } ``` Checkpoint storage that is currently supported by the agent implementation is AWS S3 and Google Cloud Storage. The Azure Blob Storage contribution is still [in progress](https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/2242). ### Liveness implications Depending on the threshold configured in the Multisig ISM, Validator downtime can halt liveness of the protocol. The submitter prioritizes new checkpoints over old ones, so that the Relayer can fetch metadata for newer messages first, which are more likely to not have been delivered yet. ### Default ISM Validators The number of validators depend on the Interchain Security Module (ISM) configuration. The Default ISM uses a specific validator set, you can view the Validator details such as threshold, operator and addresses [here](/docs/reference/addresses/validators/mainnet-default-ism-validators). # Dispatch Fees Source: https://docs.hyperlane.xyz/docs/protocol/core/fees Understanding origin and interchain fees for Hyperlane cross-chain transfers ## Fee Estimation When sending a cross-chain message with Hyperlane GMP, two fees are paid: 1. **Origin Fee** – transaction fee on the origin chain (charged by the blockchain) 2. [**Interchain Fee**](/docs/protocol/core/interchain-gas-payment) – charged by relayer to cover destination chain transaction fees This fee structure ensures that: 1. The user has enough funds to pay for the origin transaction 2. The cross-chain message will have enough gas to execute on the destination chain and pay for the message delivery 3. The total cost of the transfer is transparent to the user before execution #### Fee Token Considerations When sending cross-chain messages, the fee tokens vary by origin chain type and IGP: 1. **EVM Chains** * Uses native gas token (e.g., ETH) for both origin and interchain fees 2. **Sealevel (Solana) Chains** * Uses native gas token (e.g., SOL) for both origin and interchain fees 3. **Cosmos Chains** * Supports custom tokens; fees are specified using the `denom` parameter on an IGP * Fees are specified using the `denom` parameter Read more about transfer fees and calculations: * [Interchain Gas Payment](/docs/protocol/core/interchain-gas-payment) - Handling gas payments between chains and relayer fees * [Post Dispatch Hooks](/docs/protocol/core/post-dispatch-hooks-overview) - Framework for executing actions after message dispatch ## Warp Route Fees When using Warp Routes to bridge tokens, there may be additional application fees denominated in the token being bridged. See [Warp Route Fees](/docs/applications/warp-routes/interface) for more details # Interchain Gas Payments Source: https://docs.hyperlane.xyz/docs/protocol/core/interchain-gas-payment How to pay the Relayer for cross-chain message delivery using Hyperlane's InterchainGasPaymaster Successful interchain messages require two transactions; one on the origin chain to send the message, and one on the destination chain to deliver the message. For convenience, Hyperlane provides an onchain interface on the origin chain that allows message senders to pay [fees](#interchain-gas-payment-calculation) to the [Relayer](/docs/protocol/agents/relayer) to deliver a message on the destination chain. This payment is called an **interchain gas payment**. ```mermaid theme={null} flowchart LR subgraph Origin Chain Sender M_O[(Mailbox)] IGP[InterchainGasPaymaster] Sender -- "dispatch(...)
{value}" --> M_O M_O -- "postDispatch(..., gasLimit)
{value}" --> IGP end Relayer((Relayer)) M_O -. "indexing" .-> Relayer IGP -. "value" .- Relayer subgraph Destination Chain M_D[(Mailbox)] M_D -- "handle(...)" --> Recipient end Relayer -- "process{gasLimit}(...)" --> M_D ``` ## Interchain Gas Payment Process To [deliver a message](/docs/reference/messaging/send), a transaction must be included on the destination chain that calls the Mailbox `process` function with the encoded message and ISM metadata. ```mermaid theme={null} flowchart LR subgraph Origin Chain Sender M_O[(Mailbox)] IGP[InterchainGasPaymaster] Sender -- "dispatch(...)
{value}" --> M_O M_O -- "postDispatch(..., gasLimit)
{value}" --> IGP end Relayer((Relayer)) M_O -. "indexing" .-> Relayer IGP -. "value" .- Relayer ``` For convenience, a [Relayer](docs/operate/relayer/run-relayer) watches for dispatched messages and will submit process transactions on behalf of the message sender if they receive sufficient payment on the origin chain. This is the *interchain gas payment*. ```mermaid theme={null} flowchart LR Relayer((Relayer)) subgraph Destination Chain M_D[(Mailbox)] M_D -- "handle(...)" --> Recipient end Relayer -- "process{gasLimit}(...)" --> M_D ``` Because messages can trigger arbitrary code execution, the Relayer must meter the [`handle` call](/docs/reference/messaging/receive#handle) with a `gasLimit` to charge appropriately at message dispatch time. ## InterchainGasPaymasters Interchain gas payments are facilitated by `InterchainGasPaymaster` (IGP) smart contracts. These contracts expose the [InterchainGasPaymaster interface](/docs/reference/hooks/interchain-gas), which allow message senders to pay the Relayer with native tokens on the origin chain to cover the costs of delivering a message on the destination chain. Each `InterchainGasPaymaster` contract corresponds to exactly one Relayer. You can find addresses of the Abacus Works' Relayer under [addresses](/docs/reference/addresses/deployments/interchainGasPaymaster). ### Interchain Gas Payment Calculation The interchain gas payment is calculated as follows: $$ destinationTxCost = destinationGasPrice * gasLimit $$ $$ exchangeRate = \frac{originGasTokenPrice}{destinationGasTokenPrice} $$ $$ originFee = exchangeRate * destinationTxCost $$ The `gasLimit` and the `exchangeRate` are configured by the message sender and the Relayer, respectively. ## Trust Assumptions Interchain gas payments are based on a social contract between the message sender and Relayer. In other words, a Relayer may receive interchain gas payments without delivering the corresponding messages. Therefore, when making interchain gas payments, it is recommended to use an IGP contract that is associated with a known and reputable Relayer. An honest Relayer implementation will honor any successful gas payments made to its IGP, no matter how many tokens were actually paid. By keeping [gas oracles](/docs/reference/hooks/interchain-gas) up to date, the Relayer can ensure that gas payments succeed if and only if a "fair" price was paid. There are no trust assumptions with respect to Relayers in the Hyperlane protocol, and under no circumstances will a malicious Relayer be able to censor or falsify messages. The worst thing that a Relayer can do is accept payments without delivering a message. ## Learn More * For details on gas limit calculations, benchmarking recommendations, gas oracles, and destination gas configuration, refer to [Interchain Gas Payment Details](/docs/reference/hooks/interchain-gas). * For Relayer setups and implementation guidance, see the [Relayer](docs/operate/relayer/run-relayer) section. # Mailbox Source: https://docs.hyperlane.xyz/docs/protocol/core/mailbox Core smart contract interface for sending and receiving cross-chain messages in Hyperlane The Hyperlane `Mailbox` smart contracts expose an on-chain API for sending and receiving interchain messages. There is a `Mailbox` contract deployed on every chain Hyperlane supports. The network of `Mailboxes` facilitates the connective tissue between blockchains that developers leverage to create interchain applications, and add interchain functionality to their existing applications. ```mermaid theme={null} flowchart LR subgraph Origin Chain Sender M_O[(Mailbox)] Sender -- "dispatch(destination, recipient, body)" --> M_O end subgraph Destination Chain Recipient[Recipient] M_D[(Mailbox)] M_D -- "handle(origin, sender, body)" --> Recipient end M_O -. "relay" .-> M_D ``` * To [**send**](/docs/reference/messaging/send) interchain messages, call the `dispatch` function. * To [**receive**](/docs/reference/messaging/receive) interchain messages, implement the `handle` function. ## Interface The [`IMailbox`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/interfaces/IMailbox.sol) interface exposes two state-mutating functions; `dispatch()` and `process()`, which are used to send and receive messages, respectively. ```solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; import {IInterchainSecurityModule} from "./IInterchainSecurityModule.sol"; import {IPostDispatchHook} from "./hooks/IPostDispatchHook.sol"; interface IMailbox { // ============ Events ============ /** * @notice Emitted when a new message is dispatched via Hyperlane * @param sender The address that dispatched the message * @param destination The destination domain of the message * @param recipient The message recipient address on `destination` * @param message Raw bytes of message */ event Dispatch( address indexed sender, uint32 indexed destination, bytes32 indexed recipient, bytes message ); /** * @notice Emitted when a new message is dispatched via Hyperlane * @param messageId The unique message identifier */ event DispatchId(bytes32 indexed messageId); /** * @notice Emitted when a Hyperlane message is processed * @param messageId The unique message identifier */ event ProcessId(bytes32 indexed messageId); /** * @notice Emitted when a Hyperlane message is delivered * @param origin The origin domain of the message * @param sender The message sender address on `origin` * @param recipient The address that handled the message */ event Process( uint32 indexed origin, bytes32 indexed sender, address indexed recipient ); function localDomain() external view returns (uint32); function delivered(bytes32 messageId) external view returns (bool); function defaultIsm() external view returns (IInterchainSecurityModule); function defaultHook() external view returns (IPostDispatchHook); function requiredHook() external view returns (IPostDispatchHook); function latestDispatchedId() external view returns (bytes32); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody ) external view returns (uint256 fee); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata body, bytes calldata defaultHookMetadata ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody, bytes calldata defaultHookMetadata ) external view returns (uint256 fee); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata body, bytes calldata customHookMetadata, IPostDispatchHook customHook ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody, bytes calldata customHookMetadata, IPostDispatchHook customHook ) external view returns (uint256 fee); function process( bytes calldata metadata, bytes calldata message ) external payable; function recipientIsm( address recipient ) external view returns (IInterchainSecurityModule module); } ``` ### Message Headers The Mailbox prepends message bodies with a header containing the following fields: | **Field** | **Description** | | ------------- | -------------------------------------------------------------- | | `version` | The version of the Mailbox contract | | `nonce` | A unique identifier for each message sent from a given Mailbox | | `origin` | The domain of the origin chain | | `sender` | The address of the sender on the origin chain | | `destination` | The domain of the destination chain | | `recipient` | The address of the recipient on the destination chain | See the [`Message` library](/docs/reference/messaging/send) for more information on the message encoding. ### Uniqueness The `nonce` is a monotonically increasing integer for each message sent from a given Mailbox. It is incremented each time a message is dispatched to serve as a separator for otherwise identical messages. ```solidity Solidity theme={null} function delivered(bytes32 messageId) external view returns (bool); ``` The `messageId` is a globally unique message identifier, returned from the `dispatch` call, computed as the `keccak256` hash of the message (with headers). ### Replay Protection The Mailbox maintains a mapping of already delivered `messageId` values to prevent replay attacks. If a message is received with a `messageId` that has already been delivered, the message is rejected. ## Dispatch To send interchain messages, developers call `Mailbox.dispatch()`. This function takes as parameters the message contents, the destination chain ID, and the recipient address. Each message get inserted as a leaf into an [incremental merkle tree](https://medium.com/@josephdelong/ethereum-2-0-deposit-merkle-tree-13ec8404ca4f) stored by the `Mailbox`. Hyperlane's proof of stake protocol uses this merkle tree to verify fraud proofs. ## Process To deliver interchain messages, the [relayer](/docs/protocol/agents/relayer) calls `Mailbox.process()`. This function takes as parameters the message to deliver as well as arbitrary metadata that can be specified by the relayer. The `Mailbox` will pass the message and metadata to the recipient's interchain security module for verification. If the ISM successfully verifies the message, the `Mailbox` delivers the message to the recipient by calling `recipient.handle()`. See [`Message.sol`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/libs/Message.sol) for more details on Hyperlane message encoding # Post-Dispatch Hooks Overview Source: https://docs.hyperlane.xyz/docs/protocol/core/post-dispatch-hooks-overview Configure additional origin chain behavior for messages dispatched via the Mailbox using post-dispatch hooks Post-dispatch hooks allow developers to configure additional origin chain behavior with message content dispatched via the Mailbox. ```mermaid theme={null} flowchart TB subgraph Origin Sender M_O[(Mailbox)] Hook[IPostDispatchHook] Sender -- "dispatch(..., metadata, hook)
{value}" --> M_O M_O -- "postDispatch(message, metadata)
{value}" --> Hook end ``` This allows developers to integrate third party/native bridges, make additional chain commitments, or require custom fees all while maintaining a consistent single-call Mailbox interface. ```solidity Solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; /*@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ HYPERLANE @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@*/ interface IPostDispatchHook { enum Types { UNUSED, ROUTING, AGGREGATION, MERKLE_TREE, INTERCHAIN_GAS_PAYMASTER, FALLBACK_ROUTING, ID_AUTH_ISM, PAUSABLE, PROTOCOL_FEE, LAYER_ZERO_V1, RATE_LIMITED, ARB_L2_TO_L1, OP_L2_TO_L1 } /** * @notice Returns an enum that represents the type of hook */ function hookType() external view returns (uint8); /** * @notice Returns whether the hook supports metadata * @param metadata metadata * @return Whether the hook supports metadata */ function supportsMetadata( bytes calldata metadata ) external view returns (bool); /** * @notice Post action after a message is dispatched via the Mailbox * @param metadata The metadata required for the hook * @param message The message passed from the Mailbox.dispatch() call */ function postDispatch( bytes calldata metadata, bytes calldata message ) external payable; /** * @notice Compute the payment required by the postDispatch call * @param metadata The metadata required for the hook * @param message The message passed from the Mailbox.dispatch() call * @return Quoted payment for the postDispatch call */ function quoteDispatch( bytes calldata metadata, bytes calldata message ) external view returns (uint256); } ``` ## Post Dispatch In addition to the `message` dispatched via the Mailbox, the `postDispatch` function receives a `metadata` parameter. The `metadata` parameter is passed from the `dispatch` call through the Mailbox unmodified. This allows developers to pass any context they wish through to the hook. ```solidity Solidity theme={null} function postDispatch( bytes calldata metadata, bytes calldata message ) external payable; ``` If the `postDispatch` function receives insufficient payment, it may revert. Post-Dispatch Hooks may be replayable. Developers creating custom hooks should implement safe checks to prevent this behavior. [Here](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/b69bc23239ecfc8f8a6277bb0f9bc248cffea234/solidity/contracts/hooks/warp-route/RateLimitedHook.sol#L16) is an example implementation. ### Quote Dispatch (Fees) Fees are often charged in `postDispatch` to cover costs such as destination chain transaction submission and security provisioning. To receive a quote for a corresponding `postDispatch` call, you can query the `quoteDispatch` function. ```solidity Solidity theme={null} function quoteDispatch( bytes calldata metadata, bytes calldata message ) external view returns (uint256); ``` The Mailbox has a `quoteDispatch` function that returns the aggregate fee required for a `dispatch` call to be successful. ```mermaid theme={null} flowchart TB subgraph Origin Sender M_O[(Mailbox)] R_H[RequiredHook] Hook[Hook] Sender -- "quoteDispatch(..., metadata, hook)" --> M_O M_O -- "required = quoteDispatch(message, metadata)" --> R_H M_O -- "fee = hook.quoteDispatch(message, metadata)" --> Hook M_O -- "required + fee" --> Sender end ``` Move to implementing a hook guide [here.](/docs/protocol/ISM/custom-ISM) ### Overriding default Hook Metadata To override the default metadata, there is a `dispatch` overload that takes an optional `metadata` parameter. Hooks currently expect metadata to be formatted with the [`StandardHookMetadata` library](/docs/reference/developer-tools/libraries/hookmetadata). ```solidity Solidity theme={null} function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata body, bytes calldata defaultHookMetadata ) external payable returns (bytes32 messageId); ``` The custom `metadata` will be passed to the required hook's `quoteDispatch` and `postDispatch` functions, before being passed to the default hook's `postDispatch` function. ```mermaid theme={null} flowchart LR subgraph Origin Chain Sender M_O[(Mailbox)] R_H[RequiredHook] D_H[DefaultHook] Sender -- "dispatch(..., metadata){value}" --> M_O M_O -. "fee = quoteDispatch(...)" .- R_H M_O -- "postDispatch(metadata, ...)
{fee}" --> R_H M_O -. "postDispatch(metadata, ...)
{value - fee}" ..-> D_H end ``` #### Examples Checkout the: [`StandardHookMetadata` Library](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/b69bc23239ecfc8f8a6277bb0f9bc248cffea234/solidity/contracts/hooks/libs/StandardHookMetadata.sol) ```solidity Solidity theme={null} // send message from originChain to destinationChain TestRecipient IMailbox mailbox = IMailbox("mailboxAddress"); mailbox.dispatch{value: msg.value}( destinationDomain, "paddedRecipient", // Convert recipient address to padded bytes32 format bytes("messageBody"), StandardHookMetadata.overrideGasLimit(200000) ); ``` ### Custom hook and metadata After implementing the above interfaces, you can override default hook along the hook metadata by using the overloaded `dispatch` call in our mailbox: ```solidity Solidity theme={null} function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata body, bytes calldata customHookMetadata, IPostDispatchHook customHook ) external payable returns (bytes32 messageId); ``` #### Examples ```solidity Example theme={null} // send message from originChain to destinationChain TestRecipient IMailbox mailbox = IMailbox("mailboxAddress"); IPostDispatchHook merkleTree = IPostDispatchHook("merkleTreeHookAddress"); mailbox.dispatch( destinationDomain, "paddedRecipient", // Convert recipient address to padded bytes32 format bytes("messageBody"), "0x", // empty metadata merkleTree ); ``` # Protocol Overview Source: https://docs.hyperlane.xyz/docs/protocol/protocol-overview An overview of Hyperlane's cross-chain messaging protocol and core components Hyperlane is the first [permissionless interoperability](/docs/get-started-building) layer that allows smart contract developers to send arbitrary data between blockchains. Developers can use Hyperlane to move tokens, execute function calls, and many other things that allow for the creation of interchain applications, apps that can be accessed by users on any blockchain. Users interface with the Hyperlane protocol via [Mailbox](/docs/protocol/core/mailbox) smart contracts, which provide an on-chain messaging interface to send and receive interchain messages. Hyperlane takes a modular approach to security, allowing applications to configure and choose from a selection of [Interchain Security Modules](/docs/protocol/ISM/modular-security) (ISMs). Applications may specify an ISM to customize the security model that secures their integration with the Hyperlane messaging interface. ```mermaid theme={null} flowchart TB subgraph Origin Sender M_O[(Mailbox)] Sender -- "1.dispatch(destination,
recipient, body)" --> M_O end M_O -. "2.emit dispatch(sender,
destination, recipient,
body)" .-> Relayer subgraph Destination Recipient M_D[(Mailbox)] ISM[InterchainSecurityModule] M_D -. "4.interchainSecurityModule()" .-> Recipient M_D -- "5.verify(metadata,
message)" --> ISM M_D -- "6.handle(origin, sender,
body)" --> Recipient end Relayer((Relayer)) -- "3.process(metadata,
message)" --> M_D style Sender fill:#efab17 style Recipient fill:#efab17 ``` # InterchainAccountRouter Source: https://docs.hyperlane.xyz/docs/reference/addresses/deployments/interchainAccountRouter InterchainAccountRouter deployments across Mainnet and Testnet ## Mainnet | Chain | Domain ID | Chain ID | Address | Explorer | | --------------------- | ---------- | ---------- | -------------------------------------------- | -------------------------------------------------------------------------------------------- | | ADI Chain | 36900 | 36900 | `0x6c5012B7eDfE317Be53D13Fc730a460f4810e234` | [explorer.adichain](https://explorer.adichain) | | Ancient8 | 888888888 | 888888888 | `0x23C6D8145DDb71a24965AAAdf4CA4B095b4eC85F` | [scan.ancient8.gg](https://scan.ancient8.gg) | | ApeChain | 33139 | 33139 | `0xb347c2cbfc32e0bdf365183635352e0C38c97147` | [apescan.io](https://apescan.io) | | AppChain | 466 | 466 | `0x24f89395e932961C27167F42DB928Ec92047B695` | [explorer.appchain.xyz](https://explorer.appchain.xyz) | | Arbitrum | 42161 | 42161 | `0xF90A3d406C6F8321fe118861A357F4D7107760D7` | [arbiscan.io](https://arbiscan.io) | | Arcadia | 4278608 | 4278608 | `0x87ED6926abc9E38b9C7C19f835B41943b622663c` | [explorer.arcadia.khalani.network](https://explorer.arcadia.khalani.network) | | Artela | 11820 | 11820 | `0x3A220676CFD4e21726cbF20E8F5df4F138364f69` | [artscan.artela.network](https://artscan.artela.network) | | Astar | 592 | 592 | `0xC3d9e724c6Bf3c4456EB8572Be05AA52f8acC9Ae` | [astar.blockscout.com](https://astar.blockscout.com) | | Avalanche | 43114 | 43114 | `0x2c58687fFfCD5b7043a5bF256B196216a98a6587` | [snowtrace.io](https://snowtrace.io) | | Base | 8453 | 8453 | `0x44647Cd983E80558793780f9a0c7C2aa9F384D07` | [basescan.org](https://basescan.org) | | Berachain | 80094 | 80094 | `0x84Fcd67D2B723416e2aFDd61484BD19bd9C32f27` | [beratrail.io](https://beratrail.io) | | Bitlayer | 200901 | 200901 | `0xE0208ddBe76c703eb3Cd758a76e2c8c1Ff9472fD` | [www.btrscan.com](https://www.btrscan.com) | | Blast | 81457 | 81457 | `0x7d58D7F052792e54eeEe91B2467c2A17a163227e` | [blastscan.io](https://blastscan.io) | | BOB | 60808 | 60808 | `0xA6f0A37DFDe9C2c8F46F010989C47d9edB3a9FA8` | [explorer.gobob.xyz](https://explorer.gobob.xyz) | | Boba Mainnet | 288 | 288 | `0x625324ebE9Fe13fEDD8ac3761F153b90aa35B404` | [bobascan.com](https://bobascan.com) | | Botanix | 3637 | 3637 | `0x21b5a2fA1f53e94cF4871201aeD30C6ad5E405f2` | [botanixscan.io](https://botanixscan.io) | | Binance Smart Chain | 56 | 56 | `0xf453B589F0166b90e050691EAc281C01a8959897` | [bscscan.com](https://bscscan.com) | | CarrChain | 7667 | 7667 | `0xBCD18636e5876DFd7AAb5F2B2a5Eb5ca168BA1d8` | [carrscan.io](https://carrscan.io) | | Celo | 42220 | 42220 | `0x1eA7aC243c398671194B7e2C51d76d1a1D312953` | [celoscan.io](https://celoscan.io) | | Chiliz | 1000088888 | 88888 | `0x246BBe3983C22553362A42aa4B06320E2fB4E880` | [chiliscan.com](https://chiliscan.com) | | Citrea | 4114 | 4114 | `0x33AA12b4e8E79cA551Ca9D1F2eC7d2cE02129dd4` | [explorer.mainnet.citrea.xyz](https://explorer.mainnet.citrea.xyz) | | Core | 1116 | 1116 | `0xB8736c87da7DEc750fA0226e3bdE1Ac35B88f43d` | [scan.coredao.org](https://scan.coredao.org) | | Coti | 2632500 | 2632500 | `0x7D5a79539d7B1c9aE5e54d18EEE188840f1Fe4CC` | [mainnet.cotiscan.io](https://mainnet.cotiscan.io) | | Cyber | 7560 | 7560 | `0x1B947F6246ACe28abAf073FF11c098F31ce4f899` | [cyberscan.co](https://cyberscan.co) | | Eden | 714 | 714 | `0xF7af65596A16740b16CF755F3A43206C96285da0` | N/A | | Electroneum | 52014 | 52014 | `0x9fE454AA2B01fc7A2a777AE561bc58Ce560CD5a9` | [blockexplorer.electroneum.com](https://blockexplorer.electroneum.com) | | Endurance | 648 | 648 | `0xB5CA647Fd7b28cb8Ec80144f2C6BAEE2Dfc12E03` | [explorer-endurance.fusionist.io](https://explorer-endurance.fusionist.io) | | ENI | 173 | 173 | `0x40Ca4155c0334F7e0F6d7F80536B59EF8831c9fb` | [scan.eniac.network](https://scan.eniac.network) | | Ethereum | 1 | 1 | `0xC00b94c115742f711a6F9EA90373c33e9B72A4A9` | [etherscan.io](https://etherscan.io) | | Everclear | 25327 | 25327 | `0x6FD739221F53F8dc1565F3aF830Cb687cfe5932D` | [scan.everclear.org](https://scan.everclear.org) | | Flare | 14 | 14 | `0xC1272CCea251c85b7D11eDeD1204a88DEde90f46` | [flare-explorer.flare.network](https://flare-explorer.flare.network) | | EVM on Flow | 1000000747 | 747 | `0x1D43Eb638ABF43B4147B7985402a4FfbDd89D4ac` | [evm.flowscan.io](https://evm.flowscan.io) | | Fluence | 9999999 | 9999999 | `0x1504Dff2ab3196a41FC0565E41B64247dc405022` | [blockscout.mainnet.fluence.dev](https://blockscout.mainnet.fluence.dev) | | Fluent | 25363 | 25363 | `0xA697222b77cDe62A8C47E627d5A1c49A87018236` | [fluentscan.xyz](https://fluentscan.xyz) | | Fraxtal | 252 | 252 | `0xD59a200cCEc5b3b1bF544dD7439De452D718f594` | [fraxscan.com](https://fraxscan.com) | | Fuse | 122 | 122 | `0xc57fe3d144434d0aBaF8D3698E3103a4ddFD777A` | [explorer.fuse.io](https://explorer.fuse.io) | | Galactica | 613419 | 613419 | `0x1fbcCdc677c10671eE50b46C61F0f7d135112450` | [explorer.galactica.com](https://explorer.galactica.com) | | Gnosis | 100 | 100 | `0xef0Adeb4103A7A1AcE86371867202f2171126362` | [gnosisscan.io](https://gnosisscan.io) | | Gravity Alpha Mainnet | 1625 | 1625 | `0x335593971F655220a760837b64fbeABd09dE6dD9` | [explorer.gravity.xyz](https://explorer.gravity.xyz) | | Hashkey | 177 | 177 | `0xD79A14EA21db52F130A57Ea6e2af55949B00086E` | [explorer.hsk.xyz](https://explorer.hsk.xyz) | | Hemi Network | 43111 | 43111 | `0x1604d2D3DaFba7D302F86BD7e79B3931414E4625` | [explorer.hemi.xyz](https://explorer.hemi.xyz) | | HyperEVM | 999 | 999 | `0x1CF975C9bF2DF76c43a14405066007f8393142E9` | [www.hyperscan.com](https://www.hyperscan.com) | | Igra | 38833 | 38833 | `0x58CA3F0D65FFd40727cF6Eb2f323151853Ad3D44` | [explorer.igralabs.com](https://explorer.igralabs.com) | | Immutable zkEVM | 1000013371 | 13371 | `0xE2cBbc708411eAf2DfbaA31DaA531d4FF089d7b0` | [explorer.immutable.com](https://explorer.immutable.com) | | Incentiv | 24101 | 24101 | `0xBCD18636e5876DFd7AAb5F2B2a5Eb5ca168BA1d8` | [explorer.incentiv.io](http://explorer.incentiv.io) | | Ink | 57073 | 57073 | `0x55Ba00F1Bac2a47e0A73584d7c900087642F9aE3` | [explorer.inkonchain.com](https://explorer.inkonchain.com) | | Kaia | 8217 | 8217 | `0xcfe6dBaD47c3B8cf4fecbb28B53Df4617F8538A7` | [kaiascope.com](https://kaiascope.com) | | Katana | 747474 | 747474 | `0xbF2D3b1a37D54ce86d0e1455884dA875a97C87a8` | [explorer.katanarpc.com](https://explorer.katanarpc.com) | | Kiichain | 1783 | 1783 | `0xA697222b77cDe62A8C47E627d5A1c49A87018236` | [mainnet.explorer.kiichain.io](https://mainnet.explorer.kiichain.io) | | Krown | 1983 | 1983 | `0xf50e2f7ff2D367fac0B90Be2564A096168801b2d` | N/A | | LazAI | 52924 | 52924 | `0x946E9f4540E032a9fAc038AE58187eFcad9DE952` | [explorer.mainnet.lazai.network](https://explorer.mainnet.lazai.network) | | Linea | 59144 | 59144 | `0xBfC8DCEf3eFabC064f5afff4Ac875a82D2Dc9E55` | [lineascan.build](https://lineascan.build) | | Lisk | 1135 | 1135 | `0xE59592a179c4f436d5d2e4caA6e2750beA4E3166` | [blockscout.lisk.com](https://blockscout.lisk.com) | | Lit Chain | 175200 | 175200 | `0x0DbB60c348DF645c295Fd0ce26F87bB850710185` | [lit-chain-explorer.litprotocol.com](https://lit-chain-explorer.litprotocol.com) | | LUKSO | 42 | 42 | `0x7e0956bfEE5C4dEAd8Ced283C934299998100362` | [explorer.execution.mainnet.lukso.network](https://explorer.execution.mainnet.lukso.network) | | Lumia Prism | 1000073017 | 994873017 | `0x3C330D4A2e2b8443AFaB8E326E64ab4251B7Eae0` | [explorer.lumia.org](https://explorer.lumia.org) | | Manta Pacific | 169 | 169 | `0x620ffeEB3359649dbE48278d3Cffd00CC36976EA` | [pacific-explorer.manta.network](https://pacific-explorer.manta.network) | | Mantle | 5000 | 5000 | `0x31e81982E98F5D321F839E82789b628AedB15751` | [explorer.mantle.xyz](https://explorer.mantle.xyz) | | MANTRA | 5888 | 5888 | `0x0DbB60c348DF645c295Fd0ce26F87bB850710185` | [blockscout.mantrascan.io](https://blockscout.mantrascan.io) | | Matchain | 698 | 698 | `0xcb98BD947B58445Fc4815f10285F44De42129918` | [matchscan.io](https://matchscan.io) | | MegaETH | 4326 | 4326 | `0xD233433AeC23F8382DAd87D808F60557Ea35399f` | [megaeth.blockscout.com](https://megaeth.blockscout.com) | | Metal L2 | 1000001750 | 1750 | `0x0b2d429acccAA411b867d57703F88Ed208eC35E4` | [explorer.metall2.com](https://explorer.metall2.com) | | Metis Andromeda | 1088 | 1088 | `0x04Bd82Ba84a165BE5D555549ebB9890Bb327336E` | [andromeda-explorer.metis.io](https://andromeda-explorer.metis.io) | | Miraclechain | 92278 | 92278 | `0x38D361861d321B8B05de200c61B8F18740Daf4D8` | [explorer.miracleplay.io](https://explorer.miracleplay.io) | | Mitosis | 124816 | 124816 | `0x1A41a365A693b6A7aED1a46316097d290f569F22` | [mitoscan.io](https://mitoscan.io) | | Moca Chain | 2288 | 2288 | `0xA697222b77cDe62A8C47E627d5A1c49A87018236` | [moca-mainnet.cloud.blockscout.com](https://moca-mainnet.cloud.blockscout.com) | | Mode | 34443 | 34443 | `0x860ec58b115930EcbC53EDb8585C1B16AFFF3c50` | [explorer.mode.network](https://explorer.mode.network) | | Molten | 360 | 360 | `0xCf42106b85fC72c43Ac4976f20fA2aD7D9592c31` | [molten.calderaexplorer.xyz](https://molten.calderaexplorer.xyz) | | Monad | 143 | 143 | `0x8452363d5c78bf95538614441Dc8B465e03A89ca` | [mainnet-beta.monvision.io](https://mainnet-beta.monvision.io) | | Morph | 2818 | 2818 | `0x36E437699E3658396Bf6229ddDaE54884cf28779` | [explorer.morphl2.io](https://explorer.morphl2.io) | | Nibiru | 6900 | 6900 | `0xd5e0859Cf2e9C790bE6ec4499A39d75Cb84836Dc` | [nibiscan.io](https://nibiscan.io) | | Ontology | 58 | 58 | `0xbCA8CF652c9a0b714C4369B3Fe9863d0C892b65b` | [explorer.ont.io](https://explorer.ont.io) | | Oort | 970 | 970 | `0x6c3b61e60Ff510E35Ba51D25bb2E0F90B0307E7D` | [mainnet-scan.oortech.com](https://mainnet-scan.oortech.com) | | opBNB | 204 | 204 | `0x8847A94861C299e6AD408923A604dEe057baB5dC` | [opbnb.bscscan.com](https://opbnb.bscscan.com) | | Optimism | 10 | 10 | `0x3E343D07D024E657ECF1f8Ae8bb7a12f08652E75` | [optimistic.etherscan.io](https://optimistic.etherscan.io) | | Orderly L2 | 291 | 291 | `0x9121E58Cb02890cEEF1a21EF4B80420eC2b8B61C` | [explorer.orderly.network](https://explorer.orderly.network) | | Peaq | 3338 | 3338 | `0xdcA646C56E7768DD11654956adE24bfFf9Ba4893` | [peaq.subscan.io](https://peaq.subscan.io) | | Plasma | 9745 | 9745 | `0x9fE454AA2B01fc7A2a777AE561bc58Ce560CD5a9` | [plasmascan.to](https://plasmascan.to) | | Plume | 98866 | 98866 | `0xd9Cc2e652A162bb93173d1c44d46cd2c0bbDA59D` | [explorer.plume.org](https://explorer.plume.org) | | Polygon | 137 | 137 | `0xd8B641FEb587844854aeC97544ccEA426DFF04a3` | [polygonscan.com](https://polygonscan.com) | | Polynomial | 1000008008 | 8008 | `0x1B947F6246ACe28abAf073FF11c098F31ce4f899` | [polynomialscan.io](https://polynomialscan.io) | | Prom | 227 | 227 | `0xd5D8c2d9A3F4974E89396928FEb7829d9C5e0788` | [prom-blockscout.eu-north-2.gateway.fm](https://prom-blockscout.eu-north-2.gateway.fm) | | PulseChain | 369 | 369 | `0x7823Ce52c254F71321a70b2b87EcC63a516008a1` | [scan.pulsechain.box](https://scan.pulsechain.box) | | RARI Chain | 1000012617 | 1380012617 | `0xecA217aB573506eaB6E51CDD1c3a84B626CDf7b4` | [mainnet.explorer.rarichain.org](https://mainnet.explorer.rarichain.org) | | Reactive Mainnet | 1597 | 1597 | `0x2A532fc8cF9a72142eA8753a0d2AB68098C19585` | [reactscan.net](https://reactscan.net) | | Redstone | 690 | 690 | `0x27e88AeB8EA4B159d81df06355Ea3d20bEB1de38` | [explorer.redstone.xyz](https://explorer.redstone.xyz) | | Ronin | 2020 | 2020 | `0xd6b12ecC223b483427ea66B029b4EEfcC1af86DC` | [app.roninchain.com](https://app.roninchain.com) | | Sei | 1329 | 1329 | `0xA70482D7359816809988AC4053d83F0C8C98D292` | [seitrace.com](https://seitrace.com) | | Shibarium | 109 | 109 | `0xa4fc7C90a4D4ae2A11637D04A6c5286E00B4bAA0` | [shibariumscan.io](https://shibariumscan.io) | | Somnia | 5031 | 5031 | `0x8EC2D100Bc36D80e5C5EF9479Ae5b3eC636a0B46` | [explorer.somnia.network](https://explorer.somnia.network) | | Soneium | 1868 | 1868 | `0xc08C1451979e9958458dA3387E92c9Feb1571f9C` | [soneium.blockscout.com](https://soneium.blockscout.com) | | Sonic | 146 | 146 | `0xEfad3f079048bE2765b6bCfAa3E9d99e9A2C3Df6` | [sonicscan.org](https://sonicscan.org) | | Stable | 988 | 988 | `0xF9aE87E9ACE51aa16AED25Ca38F17D258aECb73f` | [stablescan.xyz](https://stablescan.xyz) | | Subtensor | 964 | 964 | `0x9097869cb719335f45A069D41dEFAFA2858af676` | [evm.taostats.io](https://evm.taostats.io) | | Superseed | 5330 | 5330 | `0x3CA0e8AEfC14F962B13B40c6c4b9CEE3e4927Ae3` | [explorer.superseed.xyz](https://explorer.superseed.xyz) | | Swell | 1923 | 1923 | `0x95Fb6Ca1BBF441386b119ad097edcAca3b1C35B7` | [explorer.swellnetwork.io](https://explorer.swellnetwork.io) | | TAC | 239 | 239 | `0x829AcBc15a66F6B32a189CFB6451B2Ee583706BA` | [explorer.tac.build](https://explorer.tac.build) | | Taiko | 167000 | 167000 | `0xEE47aD8f6582CDcBF4B8581A1c3482E72E4DeaBf` | [taikoscan.io](https://taikoscan.io) | | Tempo | 4217 | 4217 | `0xEB92D3f697F0d7DCbC025912e671d2A979FBFf78` | [explore.tempo.xyz](https://explore.tempo.xyz) | | Torus | 21000 | 21000 | `0xCCceDFFAA987F47D0D3A26430c3d3f3270fE6369` | [blockscout.torus.network](https://blockscout.torus.network) | | Tron | 728126428 | 728126428 | `0x68Cf65eFE8EccFBE30ab0Ca0ecB043C81E395Fc5` | [tronscan.org](https://tronscan.org/#) | | Unichain | 130 | 130 | `0x43320f6B410322Bf5ca326a0DeAaa6a2FC5A021B` | [uniscan.xyz](https://uniscan.xyz) | | Vana | 1480 | 1480 | `0x3adf8f4219BdCcd4B727B9dD67E277C58799b57C` | [vanascan.io](https://vanascan.io) | | World Chain | 480 | 480 | `0xd55bFDfb3486fE49a0b2E2Af324453452329051F` | [worldscan.org](https://worldscan.org) | | Xai | 660279 | 660279 | `0xA8aB763aB8ab133236afc7b31aFC606F268048f5` | [explorer.xai-chain.net](https://explorer.xai-chain.net) | | XLayer | 196 | 196 | `0x39d3c2Cf646447ee302178EDBe5a15E13B6F33aC` | [www.oklink.com](https://www.oklink.com/xlayer) | | XRPL EVM | 1440000 | 1440000 | `0xe6fC77B08b457A29747682aB1dBfb32AF4A1A999` | [explorer.xrplevm.org](https://explorer.xrplevm.org) | | 0G | 16661 | 16661 | `0x23cc88CF424d48fDB05b4f0A8Ff6099aa4D56D8e` | [chainscan.0g.ai](https://chainscan.0g.ai) | | ZetaChain | 7000 | 7000 | `0x6783dC9f1Bf88DC554c8716c4C42C5bf640dDcc8` | [explorer.zetachain.com](https://explorer.zetachain.com) | | Zircuit | 48900 | 48900 | `0xf20414268e76d0e943533aFa1F2b99DBfb4e0F71` | [explorer.zircuit.com](https://explorer.zircuit.com) | | Zora | 7777777 | 7777777 | `0x9e6B1022bE9BBF5aFd152483DAD9b88911bC8611` | [explorer.zora.energy](https://explorer.zora.energy) | ## Testnet | Chain | Domain ID | Chain ID | Address | Explorer | | ----- | --------- | -------- | ------- | -------- | # InterchainGasPaymaster Source: https://docs.hyperlane.xyz/docs/reference/addresses/deployments/interchainGasPaymaster InterchainGasPaymaster deployments across Mainnet and Testnet ## Mainnet | Chain | Domain ID | Chain ID | Address | Explorer | | --------------------- | ---------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | Abstract | 2741 | 2741 | `0x874AaCa847B365592B2b9dB7235517c5F3a5c689` | [abscan.org](https://abscan.org) | | ADI Chain | 36900 | 36900 | `0x284226F651eb5cbd696365BC27d333028FCc5D54` | [explorer.adichain](https://explorer.adichain) | | Aleo | 1634493807 | 0 | `hyp_hook_manager.aleo/aleo194tz0jmyq8rd9htvnqppqw4jqerk2p2zd8plzn3sxl06wcgsm5pq9fka74` | [explorer.provable.com](https://explorer.provable.com) | | Ancient8 | 888888888 | 888888888 | `0x8F1E22d309baa69D398a03cc88E9b46037e988AA` | [scan.ancient8.gg](https://scan.ancient8.gg) | | ApeChain | 33139 | 33139 | `0x18B0688990720103dB63559a3563f7E8d0f63EDb` | [apescan.io](https://apescan.io) | | AppChain | 466 | 466 | `0x28291a7062afA569104bEd52F7AcCA3dD2FafD11` | [explorer.appchain.xyz](https://explorer.appchain.xyz) | | Arbitrum | 42161 | 42161 | `0x3b6044acd6767f017e99318AA6Ef93b7B06A5a22` | [arbiscan.io](https://arbiscan.io) | | Arcadia | 4278608 | 4278608 | `0x30a539E2E2d09FB4e68661B1EDD70D266211602a` | [explorer.arcadia.khalani.network](https://explorer.arcadia.khalani.network) | | Artela | 11820 | 11820 | `0xc2466492C451E1AE49d8C874bB9f89293Aaad59b` | [artscan.artela.network](https://artscan.artela.network) | | Astar | 592 | 592 | `0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd` | [astar.blockscout.com](https://astar.blockscout.com) | | Avalanche | 43114 | 43114 | `0x95519ba800BBd0d34eeAE026fEc620AD978176C0` | [snowtrace.io](https://snowtrace.io) | | Base | 8453 | 8453 | `0xc3F23848Ed2e04C0c6d41bd7804fa8f89F940B94` | [basescan.org](https://basescan.org) | | Berachain | 80094 | 80094 | `0x7Ce3a48cd9FD80004d95b088760bD05bA86C1f7b` | [beratrail.io](https://beratrail.io) | | Bitlayer | 200901 | 200901 | `0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd` | [www.btrscan.com](https://www.btrscan.com) | | Blast | 81457 | 81457 | `0xB3fCcD379ad66CED0c91028520C64226611A48c9` | [blastscan.io](https://blastscan.io) | | BOB | 60808 | 60808 | `0x62B7592C1B6D1E43f4630B8e37f4377097840C05` | [explorer.gobob.xyz](https://explorer.gobob.xyz) | | Boba Mainnet | 288 | 288 | `0x9534122Aae7978dB8f5f10dF4432233c53e820A1` | [bobascan.com](https://bobascan.com) | | Botanix | 3637 | 3637 | `0x23cc88CF424d48fDB05b4f0A8Ff6099aa4D56D8e` | [botanixscan.io](https://botanixscan.io) | | Binance Smart Chain | 56 | 56 | `0x78E25e7f84416e69b9339B0A6336EB6EFfF6b451` | [bscscan.com](https://bscscan.com) | | CarrChain | 7667 | 7667 | `0x75719C858e0c73e07128F95B2C466d142490e933` | [carrscan.io](https://carrscan.io) | | Celestia | 1128614981 | celestia | `0x726f757465725f706f73745f6469737061746368000000040000000000000001` | [celenium.io](https://celenium.io) | | Celo | 42220 | 42220 | `0x571f1435613381208477ac5d6974310d88AC7cB7` | [celoscan.io](https://celoscan.io) | | Chiliz | 1000088888 | 88888 | `0x561BcA8D862536CD9C88f332C1A1Da0fC8F96e40` | [chiliscan.com](https://chiliscan.com) | | Citrea | 4114 | 4114 | `0xe93f2f409ad8B5000431D234472973fe848dcBEC` | [explorer.mainnet.citrea.xyz](https://explorer.mainnet.citrea.xyz) | | Core | 1116 | 1116 | `0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd` | [scan.coredao.org](https://scan.coredao.org) | | Coti | 2632500 | 2632500 | `0x8452363d5c78bf95538614441Dc8B465e03A89ca` | [mainnet.cotiscan.io](https://mainnet.cotiscan.io) | | Cyber | 7560 | 7560 | `0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF` | [cyberscan.co](https://cyberscan.co) | | Eclipse | 1408864445 | 1408864445 | `ABb3i11z7wKoGCfeRQNQbVYWjAm7jG7HzZnDLV4RKRbK` | [eclipsescan.xyz](https://eclipsescan.xyz) | | Eden | 714 | 714 | `0xF59557dfacDc5a1cb8A36Af43aA4819a6A891e88` | N/A | | Electroneum | 52014 | 52014 | `0x1A41a365A693b6A7aED1a46316097d290f569F22` | [blockexplorer.electroneum.com](https://blockexplorer.electroneum.com) | | Endurance | 648 | 648 | `0xB30EAB08aa87138D57168D0e236850A530f49921` | [explorer-endurance.fusionist.io](https://explorer-endurance.fusionist.io) | | ENI | 173 | 173 | `0x2ed6030D204745aC0Cd6be8301C3a63bf14D97Cc` | [scan.eniac.network](https://scan.eniac.network) | | Ethereum | 1 | 1 | `0x9e6B1022bE9BBF5aFd152483DAD9b88911bC8611` | [etherscan.io](https://etherscan.io) | | Everclear | 25327 | 25327 | `0xb58257cc81E47EC72fD38aE16297048de23163b4` | [scan.everclear.org](https://scan.everclear.org) | | Flare | 14 | 14 | `0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd` | [flare-explorer.flare.network](https://flare-explorer.flare.network) | | EVM on Flow | 1000000747 | 747 | `0x6AA10748a036a49Cb290C0e12B77319b76792D5E` | [evm.flowscan.io](https://evm.flowscan.io) | | Fluence | 9999999 | 9999999 | `0x0DbB60c348DF645c295Fd0ce26F87bB850710185` | [blockscout.mainnet.fluence.dev](https://blockscout.mainnet.fluence.dev) | | Fluent | 25363 | 25363 | `0xA28344Ac1Fc47C1dc212E178540dD0F3e7a781A6` | [fluentscan.xyz](https://fluentscan.xyz) | | Fraxtal | 252 | 252 | `0x2Fca7f6eC3d4A0408900f2BB30004d4616eE985E` | [fraxscan.com](https://fraxscan.com) | | Fuse | 122 | 122 | `0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed` | [explorer.fuse.io](https://explorer.fuse.io) | | Galactica | 613419 | 613419 | `0xD233433AeC23F8382DAd87D808F60557Ea35399f` | [explorer.galactica.com](https://explorer.galactica.com) | | Gnosis | 100 | 100 | `0xDd260B99d302f0A3fF885728c086f729c06f227f` | [gnosisscan.io](https://gnosisscan.io) | | Gravity Alpha Mainnet | 1625 | 1625 | `0xf3dFf6747E7FC74B431C943961054B7BF6309d8a` | [explorer.gravity.xyz](https://explorer.gravity.xyz) | | Hashkey | 177 | 177 | `0x8452363d5c78bf95538614441Dc8B465e03A89ca` | [explorer.hsk.xyz](https://explorer.hsk.xyz) | | Hemi Network | 43111 | 43111 | `0xc2466492C451E1AE49d8C874bB9f89293Aaad59b` | [explorer.hemi.xyz](https://explorer.hemi.xyz) | | HyperEVM | 999 | 999 | `0xEa2Bcee14eA30bbBe3018E5E7829F963230F71C3` | [www.hyperscan.com](https://www.hyperscan.com) | | Igra | 38833 | 38833 | `0x5244d3359065C883BDfeEEff5329DE38c0Bd227e` | [explorer.igralabs.com](https://explorer.igralabs.com) | | Immutable zkEVM | 1000013371 | 13371 | `0xc6835e52C1b976F1ebC71Bc8919738E02849FdA9` | [explorer.immutable.com](https://explorer.immutable.com) | | Incentiv | 24101 | 24101 | `0x75719C858e0c73e07128F95B2C466d142490e933` | [explorer.incentiv.io](http://explorer.incentiv.io) | | Ink | 57073 | 57073 | `0xc0C2dB448fC2c84213394Fcb93a3C467e50ECa9E` | [explorer.inkonchain.com](https://explorer.inkonchain.com) | | Kaia | 8217 | 8217 | `0x145566181A18E23bB6a8A3eC6D87765542A7F754` | [kaiascope.com](https://kaiascope.com) | | Katana | 747474 | 747474 | `0x23cc88CF424d48fDB05b4f0A8Ff6099aa4D56D8e` | [explorer.katanarpc.com](https://explorer.katanarpc.com) | | Kiichain | 1783 | 1783 | `0xA28344Ac1Fc47C1dc212E178540dD0F3e7a781A6` | [mainnet.explorer.kiichain.io](https://mainnet.explorer.kiichain.io) | | Krown | 1983 | 1983 | `0x5CBD4c5f9CD55747285652f815Cc7b9A2Ef6c586` | N/A | | LazAI | 52924 | 52924 | `0xF6CC9B10c607afB777380bF71F272E4D7037C3A9` | [explorer.mainnet.lazai.network](https://explorer.mainnet.lazai.network) | | Linea | 59144 | 59144 | `0x8105a095368f1a184CceA86cCe21318B5Ee5BE28` | [lineascan.build](https://lineascan.build) | | Lisk | 1135 | 1135 | `0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF` | [blockscout.lisk.com](https://blockscout.lisk.com) | | Lit Chain | 175200 | 175200 | `0x9fE454AA2B01fc7A2a777AE561bc58Ce560CD5a9` | [lit-chain-explorer.litprotocol.com](https://lit-chain-explorer.litprotocol.com) | | LUKSO | 42 | 42 | `0x441a01Fca2eD731C0Fc4633998332f9FEDB17575` | [explorer.execution.mainnet.lukso.network](https://explorer.execution.mainnet.lukso.network) | | Lumia Prism | 1000073017 | 994873017 | `0xb7C9307fE90B9AB093c6D3EdeE3259f5378D5f03` | [explorer.lumia.org](https://explorer.lumia.org) | | Manta Pacific | 169 | 169 | `0x0D63128D887159d63De29497dfa45AFc7C699AE4` | [pacific-explorer.manta.network](https://pacific-explorer.manta.network) | | Mantle | 5000 | 5000 | `0x8105a095368f1a184CceA86cCe21318B5Ee5BE28` | [explorer.mantle.xyz](https://explorer.mantle.xyz) | | MANTRA | 5888 | 5888 | `0x9fE454AA2B01fc7A2a777AE561bc58Ce560CD5a9` | [blockscout.mantrascan.io](https://blockscout.mantrascan.io) | | Matchain | 698 | 698 | `0x9629c28990F11c31735765A6FD59E1E1bC197DbD` | [matchscan.io](https://matchscan.io) | | MegaETH | 4326 | 4326 | `0x0DbB60c348DF645c295Fd0ce26F87bB850710185` | [megaeth.blockscout.com](https://megaeth.blockscout.com) | | Metal L2 | 1000001750 | 1750 | `0x2b79328DA089E89A9E9c08732b56dd31F01011Db` | [explorer.metall2.com](https://explorer.metall2.com) | | Metis Andromeda | 1088 | 1088 | `0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF` | [andromeda-explorer.metis.io](https://andromeda-explorer.metis.io) | | MilkyWay | 1835625579 | milkyway | `0x726f757465725f706f73745f6469737061746368000000040000000000000000` | N/A | | Miraclechain | 92278 | 92278 | `0xD233433AeC23F8382DAd87D808F60557Ea35399f` | [explorer.miracleplay.io](https://explorer.miracleplay.io) | | Mitosis | 124816 | 124816 | `0xf4035357EB3e3B48E498FA6e1207892f615A2c2f` | [mitoscan.io](https://mitoscan.io) | | Moca Chain | 2288 | 2288 | `0xA28344Ac1Fc47C1dc212E178540dD0F3e7a781A6` | [moca-mainnet.cloud.blockscout.com](https://moca-mainnet.cloud.blockscout.com) | | Mode | 34443 | 34443 | `0x931dFCc8c1141D6F532FD023bd87DAe0080c835d` | [explorer.mode.network](https://explorer.mode.network) | | Molten | 360 | 360 | `0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd` | [molten.calderaexplorer.xyz](https://molten.calderaexplorer.xyz) | | Monad | 143 | 143 | `0x75719C858e0c73e07128F95B2C466d142490e933` | [mainnet-beta.monvision.io](https://mainnet-beta.monvision.io) | | Morph | 2818 | 2818 | `0x145566181A18E23bB6a8A3eC6D87765542A7F754` | [explorer.morphl2.io](https://explorer.morphl2.io) | | Nibiru | 6900 | 6900 | `0x5887BDA66EC9e854b0da6BFFe423511e69d327DC` | [nibiscan.io](https://nibiscan.io) | | Ontology | 58 | 58 | `0x11EF91d17c5ad3330DbCa709a8841743d3Af6819` | [explorer.ont.io](https://explorer.ont.io) | | Oort | 970 | 970 | `0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86` | [mainnet-scan.oortech.com](https://mainnet-scan.oortech.com) | | opBNB | 204 | 204 | `0xE911e75CECe0eF01df3ceD96BCd362941AE474D4` | [opbnb.bscscan.com](https://opbnb.bscscan.com) | | Optimism | 10 | 10 | `0xD8A76C4D91fCbB7Cc8eA795DFDF870E48368995C` | [optimistic.etherscan.io](https://optimistic.etherscan.io) | | Orderly L2 | 291 | 291 | `0x145566181A18E23bB6a8A3eC6D87765542A7F754` | [explorer.orderly.network](https://explorer.orderly.network) | | Paradex | 514051890 | 0x505249564154455f534e5f50415241434c4541525f4d41494e4e4554 | `0x0000000000000000000000000000000000000000000000000000000000000000` | [voyager.prod.paradex.trade](https://voyager.prod.paradex.trade) | | Peaq | 3338 | 3338 | `0x0DbB60c348DF645c295Fd0ce26F87bB850710185` | [peaq.subscan.io](https://peaq.subscan.io) | | Plasma | 9745 | 9745 | `0x1A41a365A693b6A7aED1a46316097d290f569F22` | [plasmascan.to](https://plasmascan.to) | | Plume | 98866 | 98866 | `0xc261Bd2BD995d3D0026e918cBFD44b0Cc5416a57` | [explorer.plume.org](https://explorer.plume.org) | | Polygon | 137 | 137 | `0x0071740Bf129b05C4684abfbBeD248D80971cce2` | [polygonscan.com](https://polygonscan.com) | | Polynomial | 1000008008 | 8008 | `0x2f536FB7a37bd817Af644072a904Ddc02Dae429f` | [polynomialscan.io](https://polynomialscan.io) | | Prom | 227 | 227 | `0x282629Af1A2f9b8e2c5Cbc54C35C7989f21950c6` | [prom-blockscout.eu-north-2.gateway.fm](https://prom-blockscout.eu-north-2.gateway.fm) | | PulseChain | 369 | 369 | `0xc996F4D7d7F39189921A08F3DaAf1b9ff0b20006` | [scan.pulsechain.box](https://scan.pulsechain.box) | | Radix | 1633970780 | 1 | `component_rdx1cznxpn5m3kutzr6jrhgnvv0x7uhcs0rf8fl2w59hkclm6m7axzlqgu` | [dashboard.radixdlt.com](https://dashboard.radixdlt.com) | | RARI Chain | 1000012617 | 1380012617 | `0xDDE46032Baf4da13fDD79BF9dfbaA2749615C409` | [mainnet.explorer.rarichain.org](https://mainnet.explorer.rarichain.org) | | Reactive Mainnet | 1597 | 1597 | `0xE911e75CECe0eF01df3ceD96BCd362941AE474D4` | [reactscan.net](https://reactscan.net) | | Redstone | 690 | 690 | `0x2Fa570E83009eaEef3a1cbd496a9a30F05266634` | [explorer.redstone.xyz](https://explorer.redstone.xyz) | | Ronin | 2020 | 2020 | `0x5cD695ADCB156589cde501822C314bFD74398cA1` | [app.roninchain.com](https://app.roninchain.com) | | Sei | 1329 | 1329 | `0xFC62DeF1f08793aBf0E67f69257c6be258194F72` | [seitrace.com](https://seitrace.com) | | Shibarium | 109 | 109 | `0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd` | [shibariumscan.io](https://shibariumscan.io) | | Solana | 1399811149 | 1399811149 | `JAvHW21tYXE9dtdG83DReqU2b4LUexFuCbtJT5tF8X6M` | [solscan.io](https://solscan.io) | | Solaxy | 1936682104 | 1936682104 | `3SDcBbfZUF9ykR3yudYN198ja3KJSq17Q3rKw7JKfJR6` | [explorer.solaxy.io](https://explorer.solaxy.io) | | Somnia | 5031 | 5031 | `0xdBa3b98DC83fec149c8C8F6617700b9e45937a2b` | [explorer.somnia.network](https://explorer.somnia.network) | | Soneium | 1868 | 1868 | `0xDf178647caB5e0222F4B53C57274FD2A03BEaed6` | [soneium.blockscout.com](https://soneium.blockscout.com) | | Sonic | 146 | 146 | `0xDf178647caB5e0222F4B53C57274FD2A03BEaed6` | [sonicscan.org](https://sonicscan.org) | | Sonic SVM | 507150715 | 507150715 | `Bxof4ZpgLtoHoxBq6AGDCJUtVxUoE9LXkx8iizkDGQPz` | [explorer.sonic.game](https://explorer.sonic.game/?cluster=custom\&customUrl=https%3A%2F%2Fapi.mainnet-alpha.sonic.game) | | SOON | 50075007 | 50075007 | `Dsem8R6mkrpNoNb6CRUEjEZRP2hKRC24thyCkVr8cNYZ` | [explorer.soo.network](https://explorer.soo.network) | | Sophon | 50104 | 50104 | `0x73a82061Cd258d02BEa145fe183120456e718c2A` | [explorer.sophon.xyz](https://explorer.sophon.xyz) | | Stable | 988 | 988 | `0x89Ebf977E83087959aD78e5372F4AF15DcdC8143` | [stablescan.xyz](https://stablescan.xyz) | | Starknet | 358974494 | 0x534e5f4d41494e | `0x0000000000000000000000000000000000000000000000000000000000000000` | [voyager.online](https://voyager.online) | | Subtensor | 964 | 964 | `0x8d7E604460E1133ebB91513a6D1024f3A3ca17F9` | [evm.taostats.io](https://evm.taostats.io) | | Superseed | 5330 | 5330 | `0x9534122Aae7978dB8f5f10dF4432233c53e820A1` | [explorer.superseed.xyz](https://explorer.superseed.xyz) | | Swell | 1923 | 1923 | `0x25EAC2007b0D40E3f0AF112FD346412321038719` | [explorer.swellnetwork.io](https://explorer.swellnetwork.io) | | TAC | 239 | 239 | `0x466b330C2e360c0214A9Da2428415298f720883E` | [explorer.tac.build](https://explorer.tac.build) | | Taiko | 167000 | 167000 | `0x273Bc6b01D9E88c064b6E5e409BdF998246AEF42` | [taikoscan.io](https://taikoscan.io) | | Tempo | 4217 | 4217 | `0x062b6D6A47c7888d0799fada3E86f9218F638035` | [explore.tempo.xyz](https://explore.tempo.xyz) | | Torus | 21000 | 21000 | `0x3cECBa60A580dE20CC57D87528953a00f4ED99EA` | [blockscout.torus.network](https://blockscout.torus.network) | | Tron | 728126428 | 728126428 | `0x0F54c23a02A5Eb2C77eF7e91222F9173Ec7110F8` | [tronscan.org](https://tronscan.org/#) | | Unichain | 130 | 130 | `0x9534122Aae7978dB8f5f10dF4432233c53e820A1` | [uniscan.xyz](https://uniscan.xyz) | | Vana | 1480 | 1480 | `0x9534122Aae7978dB8f5f10dF4432233c53e820A1` | [vanascan.io](https://vanascan.io) | | Viction | 88 | 88 | `0x0D63128D887159d63De29497dfa45AFc7C699AE4` | [www.vicscan.xyz](https://www.vicscan.xyz) | | World Chain | 480 | 480 | `0x7E27456a839BFF31CA642c060a2b68414Cb6e503` | [worldscan.org](https://worldscan.org) | | Xai | 660279 | 660279 | `0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF` | [explorer.xai-chain.net](https://explorer.xai-chain.net) | | XLayer | 196 | 196 | `0x7E27456a839BFF31CA642c060a2b68414Cb6e503` | [www.oklink.com](https://www.oklink.com/xlayer) | | XRPL EVM | 1440000 | 1440000 | `0xD233433AeC23F8382DAd87D808F60557Ea35399f` | [explorer.xrplevm.org](https://explorer.xrplevm.org) | | 0G | 16661 | 16661 | `0x7B8AA8f23Ab6B0757eC6FC71894211376D9335b0` | [chainscan.0g.ai](https://chainscan.0g.ai) | | ZetaChain | 7000 | 7000 | `0x931dFCc8c1141D6F532FD023bd87DAe0080c835d` | [explorer.zetachain.com](https://explorer.zetachain.com) | | Zircuit | 48900 | 48900 | `0x03cF708E42C89623bd83B281A56935cB562b9258` | [explorer.zircuit.com](https://explorer.zircuit.com) | | zkSync | 324 | 324 | `0xf44AdA86a1f765A938d404699B8070Dd47bD2431` | [explorer.zksync.io](https://explorer.zksync.io) | | Zora | 7777777 | 7777777 | `0x18B0688990720103dB63559a3563f7E8d0f63EDb` | [explorer.zora.energy](https://explorer.zora.energy) | ## Testnet | Chain | Domain ID | Chain ID | Address | Explorer | | ----------------------- | ---------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | Aleo Testnet | 1617853565 | 1 | `test_hyp_hook_manager.aleo/aleo175xvd3uqmswt9ckt2d4drnxrqu8gzuzz3u3cjlt3cxhru74d2qqsnf5t46` | [testnet.explorer.provable.com](https://testnet.explorer.provable.com) | | Arbitrum Sepolia | 421614 | 421614 | `0xc756cFc1b7d0d4646589EDf10eD54b201237F5e8` | [sepolia.arbiscan.io](https://sepolia.arbiscan.io) | | Base Sepolia | 84532 | 84532 | `0x28B02B97a850872C4D33C3E024fab6499ad96564` | [sepolia.basescan.org](https://sepolia.basescan.org) | | BSC Testnet | 97 | 97 | `0x0dD20e410bdB95404f71c5a4e7Fa67B892A5f949` | [testnet.bscscan.com](https://testnet.bscscan.com) | | Celestia Testnet | 1297040200 | mocha-4 | `0x726f757465725f706f73745f6469737061746368000000040000000000000001` | N/A | | Celo Sepolia | 11142220 | 11142220 | `0xB2A79c5e63A3e949e4b3982052958E3eEbD3AA83` | [celo-sepolia.blockscout.com](https://celo-sepolia.blockscout.com) | | Coti Testnet | 7082400 | 7082400 | `0xA9425D5cBcD2c83EB2a5BF453EAA18968db3ef77` | [testnet.cotiscan.io](https://testnet.cotiscan.io) | | Fuji | 43113 | 43113 | `0x6895d3916B94b386fAA6ec9276756e16dAe7480E` | [testnet.snowtrace.io](https://testnet.snowtrace.io) | | Hyperliquid EVM Testnet | 998 | 998 | `0x11918DC33E067C5DA83EEF58E50F856398b8Df4C` | [explorer.hyperlend.finance](https://explorer.hyperlend.finance) | | Incentiv Testnet v2 | 28802 | 28802 | `0xFfA20C4c8e3b2A2C1220134684FEe23EEB8872d0` | [explorer-testnet.incentiv.io](https://explorer-testnet.incentiv.io) | | Mode Testnet | 919 | 919 | `0xB261C52241E133f957630AeeFEd48a82963AC33e` | [testnet.modescan.io](https://testnet.modescan.io) | | Optimism Sepolia | 11155420 | 11155420 | `0x28B02B97a850872C4D33C3E024fab6499ad96564` | [sepolia-optimistic.etherscan.io](https://sepolia-optimistic.etherscan.io) | | Paradex Sepolia | 12263410 | 0x505249564154455f534e5f504f54435f5345504f4c4941 | `0x0000000000000000000000000000000000000000000000000000000000000000` | [voyager.testnet.paradex.trade](https://voyager.testnet.paradex.trade) | | Polygon Amoy | 80002 | 80002 | `0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C` | [amoy.polygonscan.com](https://amoy.polygonscan.com) | | Radix Stokenet | 1280787160 | 2 | `component_tdx_2_1cpxu7z3y32wdyp48kc7vpwy62t6m4wu03c7capemnclcwn9y6cxvkc` | [stokenet-dashboard.radixdlt.com](https://stokenet-dashboard.radixdlt.com) | | Sepolia | 11155111 | 11155111 | `0x6f2756380FD49228ae25Aa7F2817993cB74Ecc56` | [sepolia.etherscan.io](https://sepolia.etherscan.io) | | Solana Testnet | 1399811150 | 1399811150 | `9SQVtTNsbipdMzumhzi6X8GwojiSMwBfqAhS7FgyTcqy` | [explorer.solana.com](https://explorer.solana.com?cluster=testnet) | | Somnia Testnet | 50312 | 50312 | `0x919Af376D02751bFCaD9CBAD6bad0c3089dAE33f` | [shannon-explorer.somnia.network](https://shannon-explorer.somnia.network) | | Sonic SVM Testnet | 15153042 | 15153042 | `FSy4hQ92ZTPJVG2UmiWiymoogpwEDBcucKnLzLnbrBDt` | [explorer.sonic.game](https://explorer.sonic.game/?cluster=testnet.v1) | | Sonic Testnet | 64165 | 64165 | `0xa3AB7E6cE24E6293bD5320A53329Ef2f4DE73fCA` | [testnet.soniclabs.com](https://testnet.soniclabs.com) | | Starknet Sepolia | 23448591 | 0x534e5f5345504f4c4941 | `0x0000000000000000000000000000000000000000000000000000000000000000` | [sepolia.voyager.online](https://sepolia.voyager.online) | | SUAVE Toliman Testnet | 33626250 | 33626250 | `0xA2cf52064c921C11adCd83588CbEa08cc3bfF5d8` | [explorer.toliman.suave.flashbots.net](https://explorer.toliman.suave.flashbots.net) | | Tron Testnet | 346621343 | 2494104990 | `0xd4b6D4354173C4E0f7a98030321E7C0772D4F294` | [shasta.tronscan.org](https://shasta.tronscan.org/#) | # Mailbox Source: https://docs.hyperlane.xyz/docs/reference/addresses/deployments/mailbox Mailbox deployments across Mainnet and Testnet ## Mainnet | Chain | Domain ID | Chain ID | Address | Explorer | | --------------------- | ---------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | Abstract | 2741 | 2741 | `0x9BbDf86b272d224323136E15594fdCe487F40ce7` | [abscan.org](https://abscan.org) | | ADI Chain | 36900 | 36900 | `0xaad207a0Fd7a4e3C927Ccc78ac8134baF586B852` | [explorer.adichain](https://explorer.adichain) | | Aleo | 1634493807 | 0 | `hyp_mailbox.aleo/aleo1u9rclq7at704j7xth037apm056t36qnyam9r3v6sewvqlvnew58qph0gk7` | [explorer.provable.com](https://explorer.provable.com) | | Ancient8 | 888888888 | 888888888 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [scan.ancient8.gg](https://scan.ancient8.gg) | | ApeChain | 33139 | 33139 | `0x7f50C5776722630a0024fAE05fDe8b47571D7B39` | [apescan.io](https://apescan.io) | | AppChain | 466 | 466 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.appchain.xyz](https://explorer.appchain.xyz) | | Arbitrum | 42161 | 42161 | `0x979Ca5202784112f4738403dBec5D0F3B9daabB9` | [arbiscan.io](https://arbiscan.io) | | Arcadia | 4278608 | 4278608 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.arcadia.khalani.network](https://explorer.arcadia.khalani.network) | | Artela | 11820 | 11820 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [artscan.artela.network](https://artscan.artela.network) | | Astar | 592 | 592 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [astar.blockscout.com](https://astar.blockscout.com) | | Avalanche | 43114 | 43114 | `0xFf06aFcaABaDDd1fb08371f9ccA15D73D51FeBD6` | [snowtrace.io](https://snowtrace.io) | | Base | 8453 | 8453 | `0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D` | [basescan.org](https://basescan.org) | | Berachain | 80094 | 80094 | `0x7f50C5776722630a0024fAE05fDe8b47571D7B39` | [beratrail.io](https://beratrail.io) | | Bitlayer | 200901 | 200901 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [www.btrscan.com](https://www.btrscan.com) | | Blast | 81457 | 81457 | `0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7` | [blastscan.io](https://blastscan.io) | | BOB | 60808 | 60808 | `0x8358D8291e3bEDb04804975eEa0fe9fe0fAfB147` | [explorer.gobob.xyz](https://explorer.gobob.xyz) | | Boba Mainnet | 288 | 288 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [bobascan.com](https://bobascan.com) | | Botanix | 3637 | 3637 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [botanixscan.io](https://botanixscan.io) | | Binance Smart Chain | 56 | 56 | `0x2971b9Aec44bE4eb673DF1B88cDB57b96eefe8a4` | [bscscan.com](https://bscscan.com) | | CarrChain | 7667 | 7667 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [carrscan.io](https://carrscan.io) | | Celestia | 1128614981 | celestia | `0x68797065726c616e650000000000000000000000000000000000000000000000` | [celenium.io](https://celenium.io) | | Celo | 42220 | 42220 | `0x50da3B3907A08a24fe4999F4Dcf337E8dC7954bb` | [celoscan.io](https://celoscan.io) | | Chiliz | 1000088888 | 88888 | `0x248aDe14C0489E20C9a7Fea5F86DBfC3702208eF` | [chiliscan.com](https://chiliscan.com) | | Citrea | 4114 | 4114 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.mainnet.citrea.xyz](https://explorer.mainnet.citrea.xyz) | | Core | 1116 | 1116 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [scan.coredao.org](https://scan.coredao.org) | | Coti | 2632500 | 2632500 | `0x398633D19f4371e1DB5a8EFE90468eB70B1176AA` | [mainnet.cotiscan.io](https://mainnet.cotiscan.io) | | Cyber | 7560 | 7560 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [cyberscan.co](https://cyberscan.co) | | Eclipse | 1408864445 | 1408864445 | `EitxJuv2iBjsg2d7jVy2LDC1e2zBrx4GB5Y9h2Ko3A9Y` | [eclipsescan.xyz](https://eclipsescan.xyz) | | Eden | 714 | 714 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | N/A | | Electroneum | 52014 | 52014 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [blockexplorer.electroneum.com](https://blockexplorer.electroneum.com) | | Endurance | 648 | 648 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer-endurance.fusionist.io](https://explorer-endurance.fusionist.io) | | ENI | 173 | 173 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [scan.eniac.network](https://scan.eniac.network) | | Ethereum | 1 | 1 | `0xc005dc82818d67AF737725bD4bf75435d065D239` | [etherscan.io](https://etherscan.io) | | Everclear | 25327 | 25327 | `0x7f50C5776722630a0024fAE05fDe8b47571D7B39` | [scan.everclear.org](https://scan.everclear.org) | | Flare | 14 | 14 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [flare-explorer.flare.network](https://flare-explorer.flare.network) | | EVM on Flow | 1000000747 | 747 | `0xd9Cc2e652A162bb93173d1c44d46cd2c0bbDA59D` | [evm.flowscan.io](https://evm.flowscan.io) | | Fluence | 9999999 | 9999999 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [blockscout.mainnet.fluence.dev](https://blockscout.mainnet.fluence.dev) | | Fluent | 25363 | 25363 | `0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7` | [fluentscan.xyz](https://fluentscan.xyz) | | Fraxtal | 252 | 252 | `0x2f9DB5616fa3fAd1aB06cB2C906830BA63d135e3` | [fraxscan.com](https://fraxscan.com) | | Fuse | 122 | 122 | `0x3071D4DA6020C956Fe15Bfd0a9Ca8D4574f16696` | [explorer.fuse.io](https://explorer.fuse.io) | | Galactica | 613419 | 613419 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.galactica.com](https://explorer.galactica.com) | | Gnosis | 100 | 100 | `0xaD09d78f4c6b9dA2Ae82b1D34107802d380Bb74f` | [gnosisscan.io](https://gnosisscan.io) | | Gravity Alpha Mainnet | 1625 | 1625 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.gravity.xyz](https://explorer.gravity.xyz) | | Hashkey | 177 | 177 | `0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7` | [explorer.hsk.xyz](https://explorer.hsk.xyz) | | Hemi Network | 43111 | 43111 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.hemi.xyz](https://explorer.hemi.xyz) | | HyperEVM | 999 | 999 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [www.hyperscan.com](https://www.hyperscan.com) | | Igra | 38833 | 38833 | `0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7` | [explorer.igralabs.com](https://explorer.igralabs.com) | | Immutable zkEVM | 1000013371 | 13371 | `0x1c6f404800bA49Ed581af734eA0d25c0c7d017B2` | [explorer.immutable.com](https://explorer.immutable.com) | | Incentiv | 24101 | 24101 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.incentiv.io](http://explorer.incentiv.io) | | Ink | 57073 | 57073 | `0x7f50C5776722630a0024fAE05fDe8b47571D7B39` | [explorer.inkonchain.com](https://explorer.inkonchain.com) | | Kaia | 8217 | 8217 | `0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7` | [kaiascope.com](https://kaiascope.com) | | Katana | 747474 | 747474 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.katanarpc.com](https://explorer.katanarpc.com) | | Kiichain | 1783 | 1783 | `0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7` | [mainnet.explorer.kiichain.io](https://mainnet.explorer.kiichain.io) | | Krown | 1983 | 1983 | `0x4B44e4305B42405382b7BeC717F64D0552a9D9Fe` | N/A | | LazAI | 52924 | 52924 | `0xCB5C99F908410add8241b558299fe9aadC06bA99` | [explorer.mainnet.lazai.network](https://explorer.mainnet.lazai.network) | | Linea | 59144 | 59144 | `0x02d16BC51af6BfD153d67CA61754cF912E82C4d9` | [lineascan.build](https://lineascan.build) | | Lisk | 1135 | 1135 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [blockscout.lisk.com](https://blockscout.lisk.com) | | Lit Chain | 175200 | 175200 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [lit-chain-explorer.litprotocol.com](https://lit-chain-explorer.litprotocol.com) | | LUKSO | 42 | 42 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.execution.mainnet.lukso.network](https://explorer.execution.mainnet.lukso.network) | | Lumia Prism | 1000073017 | 994873017 | `0x0dF25A2d59F03F039b56E90EdC5B89679Ace28Bc` | [explorer.lumia.org](https://explorer.lumia.org) | | Manta Pacific | 169 | 169 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [pacific-explorer.manta.network](https://pacific-explorer.manta.network) | | Mantle | 5000 | 5000 | `0x398633D19f4371e1DB5a8EFE90468eB70B1176AA` | [explorer.mantle.xyz](https://explorer.mantle.xyz) | | MANTRA | 5888 | 5888 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [blockscout.mantrascan.io](https://blockscout.mantrascan.io) | | Matchain | 698 | 698 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [matchscan.io](https://matchscan.io) | | MegaETH | 4326 | 4326 | `0xE2ee936bEa8e42671c400aC96dE198E06F2bA2A6` | [megaeth.blockscout.com](https://megaeth.blockscout.com) | | Metal L2 | 1000001750 | 1750 | `0x730f8a4128Fa8c53C777B62Baa1abeF94cAd34a9` | [explorer.metall2.com](https://explorer.metall2.com) | | Metis Andromeda | 1088 | 1088 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [andromeda-explorer.metis.io](https://andromeda-explorer.metis.io) | | MilkyWay | 1835625579 | milkyway | `0x68797065726c616e650000000000000000000000000000000000000000000000` | N/A | | Miraclechain | 92278 | 92278 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.miracleplay.io](https://explorer.miracleplay.io) | | Mitosis | 124816 | 124816 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [mitoscan.io](https://mitoscan.io) | | Moca Chain | 2288 | 2288 | `0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7` | [moca-mainnet.cloud.blockscout.com](https://moca-mainnet.cloud.blockscout.com) | | Mode | 34443 | 34443 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.mode.network](https://explorer.mode.network) | | Molten | 360 | 360 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [molten.calderaexplorer.xyz](https://molten.calderaexplorer.xyz) | | Monad | 143 | 143 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [mainnet-beta.monvision.io](https://mainnet-beta.monvision.io) | | Morph | 2818 | 2818 | `0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7` | [explorer.morphl2.io](https://explorer.morphl2.io) | | Nibiru | 6900 | 6900 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [nibiscan.io](https://nibiscan.io) | | Ontology | 58 | 58 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.ont.io](https://explorer.ont.io) | | Oort | 970 | 970 | `0xb129828B9EDa48192D0B2db35D0E40dCF51B3594` | [mainnet-scan.oortech.com](https://mainnet-scan.oortech.com) | | opBNB | 204 | 204 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [opbnb.bscscan.com](https://opbnb.bscscan.com) | | Optimism | 10 | 10 | `0xd4C1905BB1D26BC93DAC913e13CaCC278CdCC80D` | [optimistic.etherscan.io](https://optimistic.etherscan.io) | | Orderly L2 | 291 | 291 | `0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7` | [explorer.orderly.network](https://explorer.orderly.network) | | Paradex | 514051890 | 0x505249564154455f534e5f50415241434c4541525f4d41494e4e4554 | `0x0375a37caebba07e57cb57690cfe681efcd0641b5cdb310622d776069528d2a8` | [voyager.prod.paradex.trade](https://voyager.prod.paradex.trade) | | Peaq | 3338 | 3338 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [peaq.subscan.io](https://peaq.subscan.io) | | Plasma | 9745 | 9745 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [plasmascan.to](https://plasmascan.to) | | Plume | 98866 | 98866 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.plume.org](https://explorer.plume.org) | | Polygon | 137 | 137 | `0x5d934f4e2f797775e53561bB72aca21ba36B96BB` | [polygonscan.com](https://polygonscan.com) | | Polynomial | 1000008008 | 8008 | `0x2f0E57527Bb37E5E064EF243fad56CCE6241906c` | [polynomialscan.io](https://polynomialscan.io) | | Prom | 227 | 227 | `0x5C02157068a52cEcfc98EDb6115DE6134EcB4764` | [prom-blockscout.eu-north-2.gateway.fm](https://prom-blockscout.eu-north-2.gateway.fm) | | PulseChain | 369 | 369 | `0x56176C7Fb66FdD70ef962Ae53a46A226c7F6a2Cc` | [scan.pulsechain.box](https://scan.pulsechain.box) | | Radix | 1633970780 | 1 | `component_rdx1cpcq2wcs8zmpjanjf5ek76y4wttdxswnyfcuhynz4zmhjfjxqfsg9z` | [dashboard.radixdlt.com](https://dashboard.radixdlt.com) | | RARI Chain | 1000012617 | 1380012617 | `0x65dCf8F6b3f6a0ECEdf3d0bdCB036AEa47A1d615` | [mainnet.explorer.rarichain.org](https://mainnet.explorer.rarichain.org) | | Reactive Mainnet | 1597 | 1597 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [reactscan.net](https://reactscan.net) | | Redstone | 690 | 690 | `0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D` | [explorer.redstone.xyz](https://explorer.redstone.xyz) | | Ronin | 2020 | 2020 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [app.roninchain.com](https://app.roninchain.com) | | Sei | 1329 | 1329 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [seitrace.com](https://seitrace.com) | | Shibarium | 109 | 109 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [shibariumscan.io](https://shibariumscan.io) | | Solana | 1399811149 | 1399811149 | `E588QtVUvresuXq2KoNEwAmoifCzYGpRBdHByN9KQMbi` | [solscan.io](https://solscan.io) | | Solaxy | 1936682104 | 1936682104 | `6VdnmP8MfYkPNMwyU2ZY9S3ickYyewF58LPC38y9FAVU` | [explorer.solaxy.io](https://explorer.solaxy.io) | | Somnia | 5031 | 5031 | `0xc5068BB6803ADbe5600DE5189fe27A4dAcE31170` | [explorer.somnia.network](https://explorer.somnia.network) | | Soneium | 1868 | 1868 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [soneium.blockscout.com](https://soneium.blockscout.com) | | Sonic | 146 | 146 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [sonicscan.org](https://sonicscan.org) | | Sonic SVM | 507150715 | 507150715 | `4MaM9GQZ753NhUcXH1pPsQwof1Mf3ZnjeNF4yx6S3p3N` | [explorer.sonic.game](https://explorer.sonic.game/?cluster=custom\&customUrl=https%3A%2F%2Fapi.mainnet-alpha.sonic.game) | | SOON | 50075007 | 50075007 | `Mj7GE6LZiJUZFTgabmNkFoY2o6JCEwCMKopSUUC3kqj` | [explorer.soo.network](https://explorer.soo.network) | | Sophon | 50104 | 50104 | `0x9BbDf86b272d224323136E15594fdCe487F40ce7` | [explorer.sophon.xyz](https://explorer.sophon.xyz) | | Stable | 988 | 988 | `0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7` | [stablescan.xyz](https://stablescan.xyz) | | Starknet | 358974494 | 0x534e5f4d41494e | `0x05520a179658bd81e19d4e41abce2bc397bab5af302dadea70d8918c3cbdcea8` | [voyager.online](https://voyager.online) | | Subtensor | 964 | 964 | `0xF767D698c510FE5E53b46BA6Fd1174F5271e390A` | [evm.taostats.io](https://evm.taostats.io) | | Superseed | 5330 | 5330 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.superseed.xyz](https://explorer.superseed.xyz) | | Swell | 1923 | 1923 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.swellnetwork.io](https://explorer.swellnetwork.io) | | TAC | 239 | 239 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.tac.build](https://explorer.tac.build) | | Taiko | 167000 | 167000 | `0x28EFBCadA00A7ed6772b3666F3898d276e88CAe3` | [taikoscan.io](https://taikoscan.io) | | Tempo | 4217 | 4217 | `0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7` | [explore.tempo.xyz](https://explore.tempo.xyz) | | Torus | 21000 | 21000 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [blockscout.torus.network](https://blockscout.torus.network) | | Tron | 728126428 | 728126428 | `0x6d5BeE57A58E282150c236ed8985550492a69788` | [tronscan.org](https://tronscan.org/#) | | Unichain | 130 | 130 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [uniscan.xyz](https://uniscan.xyz) | | Vana | 1480 | 1480 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [vanascan.io](https://vanascan.io) | | Viction | 88 | 88 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [www.vicscan.xyz](https://www.vicscan.xyz) | | World Chain | 480 | 480 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [worldscan.org](https://worldscan.org) | | Xai | 660279 | 660279 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.xai-chain.net](https://explorer.xai-chain.net) | | XLayer | 196 | 196 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [www.oklink.com](https://www.oklink.com/xlayer) | | XRPL EVM | 1440000 | 1440000 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.xrplevm.org](https://explorer.xrplevm.org) | | 0G | 16661 | 16661 | `0x8428a1a7E97Fc75Fb7Ba5c4aec31B55e52bbe9D6` | [chainscan.0g.ai](https://chainscan.0g.ai) | | ZetaChain | 7000 | 7000 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.zetachain.com](https://explorer.zetachain.com) | | Zircuit | 48900 | 48900 | `0xc2FbB9411186AB3b1a6AFCCA702D1a80B48b197c` | [explorer.zircuit.com](https://explorer.zircuit.com) | | zkSync | 324 | 324 | `0x6bD0A2214797Bc81e0b006F7B74d6221BcD8cb6E` | [explorer.zksync.io](https://explorer.zksync.io) | | Zora | 7777777 | 7777777 | `0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a` | [explorer.zora.energy](https://explorer.zora.energy) | ## Testnet | Chain | Domain ID | Chain ID | Address | Explorer | | ----------------------- | ---------- | ------------------------------------------------ | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | Aleo Testnet | 1617853565 | 1 | `test_hyp_mailbox.aleo/aleo1jps66qyy3mwhtdyrx4n7u3j5qnh8d7fdc4pwx3t0g9mwcs0xjuxqc3lsxu` | [testnet.explorer.provable.com](https://testnet.explorer.provable.com) | | Arbitrum Sepolia | 421614 | 421614 | `0x598facE78a4302f11E3de0bee1894Da0b2Cb71F8` | [sepolia.arbiscan.io](https://sepolia.arbiscan.io) | | Base Sepolia | 84532 | 84532 | `0x6966b0E55883d49BFB24539356a2f8A673E02039` | [sepolia.basescan.org](https://sepolia.basescan.org) | | BSC Testnet | 97 | 97 | `0xF9F6F5646F478d5ab4e20B0F910C92F1CCC9Cc6D` | [testnet.bscscan.com](https://testnet.bscscan.com) | | Celestia Testnet | 1297040200 | mocha-4 | `0x68797065726c616e650000000000000000000000000000000000000000000000` | N/A | | Celo Sepolia | 11142220 | 11142220 | `0xD0680F80F4f947968206806C2598Cbc5b6FE5b03` | [celo-sepolia.blockscout.com](https://celo-sepolia.blockscout.com) | | Coti Testnet | 7082400 | 7082400 | `0x7FE7EA170cf08A25C2ff315814D96D93C311E692` | [testnet.cotiscan.io](https://testnet.cotiscan.io) | | Fuji | 43113 | 43113 | `0x5b6CFf85442B851A8e6eaBd2A4E4507B5135B3B0` | [testnet.snowtrace.io](https://testnet.snowtrace.io) | | Hyperliquid EVM Testnet | 998 | 998 | `0x589C201a07c26b4725A4A829d772f24423da480B` | [explorer.hyperlend.finance](https://explorer.hyperlend.finance) | | Incentiv Testnet v2 | 28802 | 28802 | `0xB7697612fbfb4ad02a11dCa16e9711eCB6Da4ceA` | [explorer-testnet.incentiv.io](https://explorer-testnet.incentiv.io) | | Mode Testnet | 919 | 919 | `0x589C201a07c26b4725A4A829d772f24423da480B` | [testnet.modescan.io](https://testnet.modescan.io) | | Optimism Sepolia | 11155420 | 11155420 | `0x6966b0E55883d49BFB24539356a2f8A673E02039` | [sepolia-optimistic.etherscan.io](https://sepolia-optimistic.etherscan.io) | | Paradex Sepolia | 12263410 | 0x505249564154455f534e5f504f54435f5345504f4c4941 | `0x03dfd685b4e799f1a6a947285a4be355acbfc1715b1c7c11d249b8abd1a691d1` | [voyager.testnet.paradex.trade](https://voyager.testnet.paradex.trade) | | Polygon Amoy | 80002 | 80002 | `0x54148470292C24345fb828B003461a9444414517` | [amoy.polygonscan.com](https://amoy.polygonscan.com) | | Radix Stokenet | 1280787160 | 2 | `component_tdx_2_1czr6pvkk72u9ecs8y830d42c3qcshqsjypltdhxa3xyujlzeq5clm8` | [stokenet-dashboard.radixdlt.com](https://stokenet-dashboard.radixdlt.com) | | Sepolia | 11155111 | 11155111 | `0xfFAEF09B3cd11D9b20d1a19bECca54EEC2884766` | [sepolia.etherscan.io](https://sepolia.etherscan.io) | | Solana Testnet | 1399811150 | 1399811150 | `75HBBLae3ddeneJVrZeyrDfv6vb7SMC3aCpBucSXS5aR` | [explorer.solana.com](https://explorer.solana.com?cluster=testnet) | | Somnia Testnet | 50312 | 50312 | `0x7d498740A4572f2B5c6b0A1Ba9d1d9DbE207e89E` | [shannon-explorer.somnia.network](https://shannon-explorer.somnia.network) | | Sonic SVM Testnet | 15153042 | 15153042 | `6BaTtWPMpWdA6tHqdT2VbogC4XZ9QV5cNCYpBrx6WP7B` | [explorer.sonic.game](https://explorer.sonic.game/?cluster=testnet.v1) | | Sonic Testnet | 64165 | 64165 | `0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD` | [testnet.soniclabs.com](https://testnet.soniclabs.com) | | Starknet Sepolia | 23448591 | 0x534e5f5345504f4c4941 | `0x03c725cd6a4463e4a9258d29304bcca5e4f1bbccab078ffd69784f5193a6d792` | [sepolia.voyager.online](https://sepolia.voyager.online) | | SUAVE Toliman Testnet | 33626250 | 33626250 | `0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD` | [explorer.toliman.suave.flashbots.net](https://explorer.toliman.suave.flashbots.net) | | Tangle Testnet | 3799 | 3799 | `0x87100b0E64B3baBD43F3FCB26A6edc4395e2D9df` | [testnet-explorer.tangle.tools](https://testnet-explorer.tangle.tools) | | Tron Testnet | 346621343 | 2494104990 | `0xB50E9F9CB52543D754768dD67f1e6148ABd78B0B` | [shasta.tronscan.org](https://shasta.tronscan.org/#) | # MerkleTreeHook Source: https://docs.hyperlane.xyz/docs/reference/addresses/deployments/merkleTreeHook MerkleTreeHook deployments across Mainnet and Testnet ## Mainnet | Chain | Domain ID | Chain ID | Address | Explorer | | --------------------- | ---------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | Abstract | 2741 | 2741 | `0x11b69aB33AD8a550dcF9B4A041AA1121255F08A5` | [abscan.org](https://abscan.org) | | ADI Chain | 36900 | 36900 | `0x76F2cC245882ceFf209A61d75b9F0f1A3b7285fB` | [explorer.adichain](https://explorer.adichain) | | Aleo | 1634493807 | 0 | `hyp_hook_manager.aleo/aleo1yxevh9qgxehej46j7vueplwjcpfdfml2dje3ey4ukzknx7wzasgqnxgq82` | [explorer.provable.com](https://explorer.provable.com) | | Ancient8 | 888888888 | 888888888 | `0x811808Dd29ba8B0FC6C0ec0b5537035E59745162` | [scan.ancient8.gg](https://scan.ancient8.gg) | | ApeChain | 33139 | 33139 | `0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F` | [apescan.io](https://apescan.io) | | AppChain | 466 | 466 | `0xcd90D49b046772F710250b9119117169CB2e4D8b` | [explorer.appchain.xyz](https://explorer.appchain.xyz) | | Arbitrum | 42161 | 42161 | `0x748040afB89B8FdBb992799808215419d36A0930` | [arbiscan.io](https://arbiscan.io) | | Arcadia | 4278608 | 4278608 | `0x6e1B9f776bd415d7cC3C7458A5f0d801016918f8` | [explorer.arcadia.khalani.network](https://explorer.arcadia.khalani.network) | | Artela | 11820 | 11820 | `0x7B032cBB00AD7438E802A66D8b64761A06E5df22` | [artscan.artela.network](https://artscan.artela.network) | | Astar | 592 | 592 | `0x441a01Fca2eD731C0Fc4633998332f9FEDB17575` | [astar.blockscout.com](https://astar.blockscout.com) | | Avalanche | 43114 | 43114 | `0x84eea61D679F42D92145fA052C89900CBAccE95A` | [snowtrace.io](https://snowtrace.io) | | Base | 8453 | 8453 | `0x19dc38aeae620380430C200a6E990D5Af5480117` | [basescan.org](https://basescan.org) | | Berachain | 80094 | 80094 | `0x8F23872dAb3B166cef411EeB6C391Ff6Ce419532` | [beratrail.io](https://beratrail.io) | | Bitlayer | 200901 | 200901 | `0x441a01Fca2eD731C0Fc4633998332f9FEDB17575` | [www.btrscan.com](https://www.btrscan.com) | | Blast | 81457 | 81457 | `0xC9B8ea6230d6687a4b13fD3C0b8f0Ec607B26465` | [blastscan.io](https://blastscan.io) | | BOB | 60808 | 60808 | `0x781bE492F1232E66990d83a9D3AC3Ec26f56DAfB` | [explorer.gobob.xyz](https://explorer.gobob.xyz) | | Boba Mainnet | 288 | 288 | `0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47` | [bobascan.com](https://bobascan.com) | | Botanix | 3637 | 3637 | `0x2ed6030D204745aC0Cd6be8301C3a63bf14D97Cc` | [botanixscan.io](https://botanixscan.io) | | Binance Smart Chain | 56 | 56 | `0xFDb9Cd5f9daAA2E4474019405A328a88E7484f26` | [bscscan.com](https://bscscan.com) | | CarrChain | 7667 | 7667 | `0x7947b7Fe737B4bd1D3387153f32148974066E591` | [carrscan.io](https://carrscan.io) | | Celestia | 1128614981 | celestia | `0x726f757465725f706f73745f6469737061746368000000030000000000000000` | [celenium.io](https://celenium.io) | | Celo | 42220 | 42220 | `0x04dB778f05854f26E67e0a66b740BBbE9070D366` | [celoscan.io](https://celoscan.io) | | Chiliz | 1000088888 | 88888 | `0x9c2214467Daf9e2e1F45b36d08ce0b9C65BFeA88` | [chiliscan.com](https://chiliscan.com) | | Citrea | 4114 | 4114 | `0x40Ca4155c0334F7e0F6d7F80536B59EF8831c9fb` | [explorer.mainnet.citrea.xyz](https://explorer.mainnet.citrea.xyz) | | Core | 1116 | 1116 | `0x441a01Fca2eD731C0Fc4633998332f9FEDB17575` | [scan.coredao.org](https://scan.coredao.org) | | Coti | 2632500 | 2632500 | `0x6D48135b7584E8Bf828B6e23110Bc0Da4252704f` | [mainnet.cotiscan.io](https://mainnet.cotiscan.io) | | Cyber | 7560 | 7560 | `0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a` | [cyberscan.co](https://cyberscan.co) | | Eclipse | 1408864445 | 1408864445 | `EitxJuv2iBjsg2d7jVy2LDC1e2zBrx4GB5Y9h2Ko3A9Y` | [eclipsescan.xyz](https://eclipsescan.xyz) | | Eden | 714 | 714 | `0x14c3CEee8F431aE947364f43429a98EA89800238` | N/A | | Electroneum | 52014 | 52014 | `0xA7d42B7a7603bEb87f84a1f3D5C97a033DFd2Cc9` | [blockexplorer.electroneum.com](https://blockexplorer.electroneum.com) | | Endurance | 648 | 648 | `0xC831271c1fB212012811a91Dd43e5926C1020563` | [explorer-endurance.fusionist.io](https://explorer-endurance.fusionist.io) | | ENI | 173 | 173 | `0x0dc95Af5156fb0cC34a8c9BD646B748B9989A956` | [scan.eniac.network](https://scan.eniac.network) | | Ethereum | 1 | 1 | `0x48e6c30B97748d1e2e03bf3e9FbE3890ca5f8CCA` | [etherscan.io](https://etherscan.io) | | Everclear | 25327 | 25327 | `0xCC3D1659D50461d27a2F025dDb2c9B06B584B7e1` | [scan.everclear.org](https://scan.everclear.org) | | Flare | 14 | 14 | `0x441a01Fca2eD731C0Fc4633998332f9FEDB17575` | [flare-explorer.flare.network](https://flare-explorer.flare.network) | | EVM on Flow | 1000000747 | 747 | `0x2783D98CC073dbcDa90241C804d16982D3d75821` | [evm.flowscan.io](https://evm.flowscan.io) | | Fluence | 9999999 | 9999999 | `0x2FF6cf2651fec512D0618E33c9d1374aaCd8b310` | [blockscout.mainnet.fluence.dev](https://blockscout.mainnet.fluence.dev) | | Fluent | 25363 | 25363 | `0x0dc95Af5156fb0cC34a8c9BD646B748B9989A956` | [fluentscan.xyz](https://fluentscan.xyz) | | Fraxtal | 252 | 252 | `0x8358D8291e3bEDb04804975eEa0fe9fe0fAfB147` | [fraxscan.com](https://fraxscan.com) | | Fuse | 122 | 122 | `0xfBc08389224d23b79cb21cDc16c5d42F0ad0F57f` | [explorer.fuse.io](https://explorer.fuse.io) | | Galactica | 613419 | 613419 | `0x64F077915B41479901a23Aa798B30701589C5063` | [explorer.galactica.com](https://explorer.galactica.com) | | Gnosis | 100 | 100 | `0x2684C6F89E901987E1FdB7649dC5Be0c57C61645` | [gnosisscan.io](https://gnosisscan.io) | | Gravity Alpha Mainnet | 1625 | 1625 | `0x5090dF2FBDa7127c7aDa41f60B79F5c55D380Dd8` | [explorer.gravity.xyz](https://explorer.gravity.xyz) | | Hashkey | 177 | 177 | `0x5B7a808CaA2C3F1378B07cDd46eB8ccA52F67e3B` | [explorer.hsk.xyz](https://explorer.hsk.xyz) | | Hemi Network | 43111 | 43111 | `0x7B032cBB00AD7438E802A66D8b64761A06E5df22` | [explorer.hemi.xyz](https://explorer.hemi.xyz) | | HyperEVM | 999 | 999 | `0x3862A9B1aCd89245a59002C2a08658EC1d5690E3` | [www.hyperscan.com](https://www.hyperscan.com) | | Igra | 38833 | 38833 | `0x75719C858e0c73e07128F95B2C466d142490e933` | [explorer.igralabs.com](https://explorer.igralabs.com) | | Immutable zkEVM | 1000013371 | 13371 | `0xdAa1B65547fB969c9ff5678956AB2FF9771B883D` | [explorer.immutable.com](https://explorer.immutable.com) | | Incentiv | 24101 | 24101 | `0x7947b7Fe737B4bd1D3387153f32148974066E591` | [explorer.incentiv.io](http://explorer.incentiv.io) | | Ink | 57073 | 57073 | `0xA8A311B69f688c1D9928259D872C31ca0d473642` | [explorer.inkonchain.com](https://explorer.inkonchain.com) | | Kaia | 8217 | 8217 | `0x6963480b05EB58f4d624B014ab92e9aD4d21df6D` | [kaiascope.com](https://kaiascope.com) | | Katana | 747474 | 747474 | `0x2ed6030D204745aC0Cd6be8301C3a63bf14D97Cc` | [explorer.katanarpc.com](https://explorer.katanarpc.com) | | Kiichain | 1783 | 1783 | `0x0dc95Af5156fb0cC34a8c9BD646B748B9989A956` | [mainnet.explorer.kiichain.io](https://mainnet.explorer.kiichain.io) | | Krown | 1983 | 1983 | `0x5244d3359065C883BDfeEEff5329DE38c0Bd227e` | N/A | | LazAI | 52924 | 52924 | `0xBCD18636e5876DFd7AAb5F2B2a5Eb5ca168BA1d8` | [explorer.mainnet.lazai.network](https://explorer.mainnet.lazai.network) | | Linea | 59144 | 59144 | `0xC077A0Cc408173349b1c9870C667B40FE3C01dd7` | [lineascan.build](https://lineascan.build) | | Lisk | 1135 | 1135 | `0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a` | [blockscout.lisk.com](https://blockscout.lisk.com) | | Lit Chain | 175200 | 175200 | `0xC4F464C89184c7870858A8B12ca822daB6ed04F3` | [lit-chain-explorer.litprotocol.com](https://lit-chain-explorer.litprotocol.com) | | LUKSO | 42 | 42 | `0x062200d92dF6bB7bA89Ce4D6800110450f94784e` | [explorer.execution.mainnet.lukso.network](https://explorer.execution.mainnet.lukso.network) | | Lumia Prism | 1000073017 | 994873017 | `0xC88636fFdFAc7cb87b7A76310B7a62AF0A000595` | [explorer.lumia.org](https://explorer.lumia.org) | | Manta Pacific | 169 | 169 | `0x149db7afD694722747035d5AEC7007ccb6F8f112` | [pacific-explorer.manta.network](https://pacific-explorer.manta.network) | | Mantle | 5000 | 5000 | `0x5332D1AC0A626D265298c14ff681c0A8D28dB86d` | [explorer.mantle.xyz](https://explorer.mantle.xyz) | | MANTRA | 5888 | 5888 | `0xC4F464C89184c7870858A8B12ca822daB6ed04F3` | [blockscout.mantrascan.io](https://blockscout.mantrascan.io) | | Matchain | 698 | 698 | `0x021D2810a758c833080DEc2F1Fa8F571Aae97D45` | [matchscan.io](https://matchscan.io) | | MegaETH | 4326 | 4326 | `0x2FF6cf2651fec512D0618E33c9d1374aaCd8b310` | [megaeth.blockscout.com](https://megaeth.blockscout.com) | | Metal L2 | 1000001750 | 1750 | `0x9c64f327F0140DeBd430aab3E2F1d6cbcA921227` | [explorer.metall2.com](https://explorer.metall2.com) | | Metis Andromeda | 1088 | 1088 | `0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a` | [andromeda-explorer.metis.io](https://andromeda-explorer.metis.io) | | MilkyWay | 1835625579 | milkyway | `0x726f757465725f706f73745f6469737061746368000000030000000000000001` | N/A | | Miraclechain | 92278 | 92278 | `0x64F077915B41479901a23Aa798B30701589C5063` | [explorer.miracleplay.io](https://explorer.miracleplay.io) | | Mitosis | 124816 | 124816 | `0x1e4dE25C3b07c8DF66D4c193693d8B5f3b431d51` | [mitoscan.io](https://mitoscan.io) | | Moca Chain | 2288 | 2288 | `0x0dc95Af5156fb0cC34a8c9BD646B748B9989A956` | [moca-mainnet.cloud.blockscout.com](https://moca-mainnet.cloud.blockscout.com) | | Mode | 34443 | 34443 | `0xE2ee936bEa8e42671c400aC96dE198E06F2bA2A6` | [explorer.mode.network](https://explorer.mode.network) | | Molten | 360 | 360 | `0x441a01Fca2eD731C0Fc4633998332f9FEDB17575` | [molten.calderaexplorer.xyz](https://molten.calderaexplorer.xyz) | | Monad | 143 | 143 | `0x7947b7Fe737B4bd1D3387153f32148974066E591` | [mainnet-beta.monvision.io](https://mainnet-beta.monvision.io) | | Morph | 2818 | 2818 | `0x6963480b05EB58f4d624B014ab92e9aD4d21df6D` | [explorer.morphl2.io](https://explorer.morphl2.io) | | Nibiru | 6900 | 6900 | `0x72246331d057741008751AB3976a8297Ce7267Bc` | [nibiscan.io](https://nibiscan.io) | | Ontology | 58 | 58 | `0xb5668713E9BA8bC96f97D691663E70b54CE90b0A` | [explorer.ont.io](https://explorer.ont.io) | | Oort | 970 | 970 | `0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59` | [mainnet-scan.oortech.com](https://mainnet-scan.oortech.com) | | opBNB | 204 | 204 | `0xcDD89f19b2d00DCB9510BB3fBd5eCeCa761fe5Ab` | [opbnb.bscscan.com](https://opbnb.bscscan.com) | | Optimism | 10 | 10 | `0x68eE9bec9B4dbB61f69D9D293Ae26a5AACb2e28f` | [optimistic.etherscan.io](https://optimistic.etherscan.io) | | Orderly L2 | 291 | 291 | `0x6963480b05EB58f4d624B014ab92e9aD4d21df6D` | [explorer.orderly.network](https://explorer.orderly.network) | | Paradex | 514051890 | 0x505249564154455f534e5f50415241434c4541525f4d41494e4e4554 | `0x02e13cb85a987a79ca4dc3ee2d65e3ea52acaccfb678767f290b8c6eca1d09e4` | [voyager.prod.paradex.trade](https://voyager.prod.paradex.trade) | | Peaq | 3338 | 3338 | `0x2FF6cf2651fec512D0618E33c9d1374aaCd8b310` | [peaq.subscan.io](https://peaq.subscan.io) | | Plasma | 9745 | 9745 | `0xA7d42B7a7603bEb87f84a1f3D5C97a033DFd2Cc9` | [plasmascan.to](https://plasmascan.to) | | Plume | 98866 | 98866 | `0x25C87e735021F72d8728438C2130b02E3141f2cb` | [explorer.plume.org](https://explorer.plume.org) | | Polygon | 137 | 137 | `0x73FbD25c3e817DC4B4Cd9d00eff6D83dcde2DfF6` | [polygonscan.com](https://polygonscan.com) | | Polynomial | 1000008008 | 8008 | `0xC8E323036AAFB4B4201e7B640E79C4Db285A3FC8` | [polynomialscan.io](https://polynomialscan.io) | | Prom | 227 | 227 | `0xf147bBD944C610F86DaE6C7668497D22932C1E4A` | [prom-blockscout.eu-north-2.gateway.fm](https://prom-blockscout.eu-north-2.gateway.fm) | | PulseChain | 369 | 369 | `0x9DaC51dF95298453C7fb5b43233818CfA4604daC` | [scan.pulsechain.box](https://scan.pulsechain.box) | | Radix | 1633970780 | 1 | `component_rdx1cz4c0upfeezhr7nxft5x3dg7w4gmhddy62d5a730lurazwkk830r4g` | [dashboard.radixdlt.com](https://dashboard.radixdlt.com) | | RARI Chain | 1000012617 | 1380012617 | `0x8c794a781327b819416E7b67908f1D22397f1E67` | [mainnet.explorer.rarichain.org](https://mainnet.explorer.rarichain.org) | | Reactive Mainnet | 1597 | 1597 | `0xcDD89f19b2d00DCB9510BB3fBd5eCeCa761fe5Ab` | [reactscan.net](https://reactscan.net) | | Redstone | 690 | 690 | `0x8F1E22d309baa69D398a03cc88E9b46037e988AA` | [explorer.redstone.xyz](https://explorer.redstone.xyz) | | Ronin | 2020 | 2020 | `0xa377b8269e0A47cdd2fD5AAeAe860b45623c6d82` | [app.roninchain.com](https://app.roninchain.com) | | Sei | 1329 | 1329 | `0xca1b69fA4c4a7c7fD839bC50867c589592bcfe49` | [seitrace.com](https://seitrace.com) | | Shibarium | 109 | 109 | `0x441a01Fca2eD731C0Fc4633998332f9FEDB17575` | [shibariumscan.io](https://shibariumscan.io) | | Solana | 1399811149 | 1399811149 | `E588QtVUvresuXq2KoNEwAmoifCzYGpRBdHByN9KQMbi` | [solscan.io](https://solscan.io) | | Solaxy | 1936682104 | 1936682104 | `6VdnmP8MfYkPNMwyU2ZY9S3ickYyewF58LPC38y9FAVU` | [explorer.solaxy.io](https://explorer.solaxy.io) | | Somnia | 5031 | 5031 | `0x11EF91d17c5ad3330DbCa709a8841743d3Af6819` | [explorer.somnia.network](https://explorer.somnia.network) | | Soneium | 1868 | 1868 | `0xDc1508844B99C606E16C2Ae87f33c373edD4B0F6` | [soneium.blockscout.com](https://soneium.blockscout.com) | | Sonic | 146 | 146 | `0xDc1508844B99C606E16C2Ae87f33c373edD4B0F6` | [sonicscan.org](https://sonicscan.org) | | Sonic SVM | 507150715 | 507150715 | `4MaM9GQZ753NhUcXH1pPsQwof1Mf3ZnjeNF4yx6S3p3N` | [explorer.sonic.game](https://explorer.sonic.game/?cluster=custom\&customUrl=https%3A%2F%2Fapi.mainnet-alpha.sonic.game) | | SOON | 50075007 | 50075007 | `Mj7GE6LZiJUZFTgabmNkFoY2o6JCEwCMKopSUUC3kqj` | [explorer.soo.network](https://explorer.soo.network) | | Sophon | 50104 | 50104 | `0x697a90753B7dCf6512189c239E612fC12baaE500` | [explorer.sophon.xyz](https://explorer.sophon.xyz) | | Stable | 988 | 988 | `0x9fE454AA2B01fc7A2a777AE561bc58Ce560CD5a9` | [stablescan.xyz](https://stablescan.xyz) | | Starknet | 358974494 | 0x534e5f4d41494e | `0x03ef761dcfda2295d2f5e7b698df51d380162cbe1cfa5b1f48fba963808f51f1` | [voyager.online](https://voyager.online) | | Subtensor | 964 | 964 | `0xB2b0A80b2fa3fC9aB1564A4FaF013d4D6084B325` | [evm.taostats.io](https://evm.taostats.io) | | Superseed | 5330 | 5330 | `0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47` | [explorer.superseed.xyz](https://explorer.superseed.xyz) | | Swell | 1923 | 1923 | `0x5C02157068a52cEcfc98EDb6115DE6134EcB4764` | [explorer.swellnetwork.io](https://explorer.swellnetwork.io) | | TAC | 239 | 239 | `0x58CA3F0D65FFd40727cF6Eb2f323151853Ad3D44` | [explorer.tac.build](https://explorer.tac.build) | | Taiko | 167000 | 167000 | `0x6A55822cf11f9fcBc4c75BC2638AfE8Eb942cAdd` | [taikoscan.io](https://taikoscan.io) | | Tempo | 4217 | 4217 | `0x086c3947F71BE98A0bDf4AB7239955e7542b0CbA` | [explore.tempo.xyz](https://explore.tempo.xyz) | | Torus | 21000 | 21000 | `0x1c6f404800bA49Ed581af734eA0d25c0c7d017B2` | [blockscout.torus.network](https://blockscout.torus.network) | | Tron | 728126428 | 728126428 | `0xD0d6fe6f7a9C6CD1dd6D370267F2A650Cd1c08D4` | [tronscan.org](https://tronscan.org/#) | | Unichain | 130 | 130 | `0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47` | [uniscan.xyz](https://uniscan.xyz) | | Vana | 1480 | 1480 | `0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47` | [vanascan.io](https://vanascan.io) | | Viction | 88 | 88 | `0x149db7afD694722747035d5AEC7007ccb6F8f112` | [www.vicscan.xyz](https://www.vicscan.xyz) | | World Chain | 480 | 480 | `0x0054D19613f20dD72721A146ED408971a2CCA9BD` | [worldscan.org](https://worldscan.org) | | Xai | 660279 | 660279 | `0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a` | [explorer.xai-chain.net](https://explorer.xai-chain.net) | | XLayer | 196 | 196 | `0x0054D19613f20dD72721A146ED408971a2CCA9BD` | [www.oklink.com](https://www.oklink.com/xlayer) | | XRPL EVM | 1440000 | 1440000 | `0x64F077915B41479901a23Aa798B30701589C5063` | [explorer.xrplevm.org](https://explorer.xrplevm.org) | | 0G | 16661 | 16661 | `0x5887BDA66EC9e854b0da6BFFe423511e69d327DC` | [chainscan.0g.ai](https://chainscan.0g.ai) | | ZetaChain | 7000 | 7000 | `0xE2ee936bEa8e42671c400aC96dE198E06F2bA2A6` | [explorer.zetachain.com](https://explorer.zetachain.com) | | Zircuit | 48900 | 48900 | `0x4C97D35c668EE5194a13c8DE8Afc18cce40C9F28` | [explorer.zircuit.com](https://explorer.zircuit.com) | | zkSync | 324 | 324 | `0x823500D69D77A52212DC93f8836E9c08581487eE` | [explorer.zksync.io](https://explorer.zksync.io) | | Zora | 7777777 | 7777777 | `0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F` | [explorer.zora.energy](https://explorer.zora.energy) | ## Testnet | Chain | Domain ID | Chain ID | Address | Explorer | | ----------------------- | ---------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | Aleo Testnet | 1617853565 | 1 | `test_hyp_hook_manager.aleo/aleo1k45pt4auhdr27hlep9pg47w82nn7vzt2g8tmcxc4gpas25fdrugsapnyvh` | [testnet.explorer.provable.com](https://testnet.explorer.provable.com) | | Arbitrum Sepolia | 421614 | 421614 | `0xAD34A66Bf6dB18E858F6B686557075568c6E031C` | [sepolia.arbiscan.io](https://sepolia.arbiscan.io) | | Base Sepolia | 84532 | 84532 | `0x86fb9F1c124fB20ff130C41a79a432F770f67AFD` | [sepolia.basescan.org](https://sepolia.basescan.org) | | BSC Testnet | 97 | 97 | `0xc6cbF39A747f5E28d1bDc8D9dfDAb2960Abd5A8f` | [testnet.bscscan.com](https://testnet.bscscan.com) | | Celestia Testnet | 1297040200 | mocha-4 | `0x726f757465725f706f73745f6469737061746368000000030000000000000000` | N/A | | Celo Sepolia | 11142220 | 11142220 | `0x1b0d4c88288258D57998F0bdb30489007A42B834` | [celo-sepolia.blockscout.com](https://celo-sepolia.blockscout.com) | | Coti Testnet | 7082400 | 7082400 | `0x413c74F3D034dB54A1ecfFbd0Ad74Cb25E59f579` | [testnet.cotiscan.io](https://testnet.cotiscan.io) | | Fuji | 43113 | 43113 | `0x9ff6ac3dAf63103620BBf76136eA1AFf43c2F612` | [testnet.snowtrace.io](https://testnet.snowtrace.io) | | Hyperliquid EVM Testnet | 998 | 998 | `0x1b33611fCc073aB0737011d5512EF673Bff74962` | [explorer.hyperlend.finance](https://explorer.hyperlend.finance) | | Incentiv Testnet v2 | 28802 | 28802 | `0x7740342863717e26E3d5B828639834ADfce8a061` | [explorer-testnet.incentiv.io](https://explorer-testnet.incentiv.io) | | Mode Testnet | 919 | 919 | `0xf83416bA0491C8BC80Dad259Fc7C007bC57Bd766` | [testnet.modescan.io](https://testnet.modescan.io) | | Optimism Sepolia | 11155420 | 11155420 | `0x86fb9F1c124fB20ff130C41a79a432F770f67AFD` | [sepolia-optimistic.etherscan.io](https://sepolia-optimistic.etherscan.io) | | Paradex Sepolia | 12263410 | 0x505249564154455f534e5f504f54435f5345504f4c4941 | `0x03199cc7c5e3572eff65349a861e3618a91f335b3ec57693867b807fe3d0eb0d` | [voyager.testnet.paradex.trade](https://voyager.testnet.paradex.trade) | | Polygon Amoy | 80002 | 80002 | `0xddf4C3e791caCaFd26D7fb275549739B38ae6e75` | [amoy.polygonscan.com](https://amoy.polygonscan.com) | | Radix Stokenet | 1280787160 | 2 | `component_tdx_2_1cp6xk70fyx7e57g2p87tqcsd0lt8ldvajdl63ff4td8fpmhkk8hhfj` | [stokenet-dashboard.radixdlt.com](https://stokenet-dashboard.radixdlt.com) | | Sepolia | 11155111 | 11155111 | `0x4917a9746A7B6E0A57159cCb7F5a6744247f2d0d` | [sepolia.etherscan.io](https://sepolia.etherscan.io) | | Solana Testnet | 1399811150 | 1399811150 | `75HBBLae3ddeneJVrZeyrDfv6vb7SMC3aCpBucSXS5aR` | [explorer.solana.com](https://explorer.solana.com?cluster=testnet) | | Somnia Testnet | 50312 | 50312 | `0x7d811da36c48cfDc7C445F14252F102bF06E3Fd7` | [shannon-explorer.somnia.network](https://shannon-explorer.somnia.network) | | Sonic SVM Testnet | 15153042 | 15153042 | `6BaTtWPMpWdA6tHqdT2VbogC4XZ9QV5cNCYpBrx6WP7B` | [explorer.sonic.game](https://explorer.sonic.game/?cluster=testnet.v1) | | Sonic Testnet | 64165 | 64165 | `0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE` | [testnet.soniclabs.com](https://testnet.soniclabs.com) | | Starknet Sepolia | 23448591 | 0x534e5f5345504f4c4941 | `0x01eff3a364cb5ec3ebef9267d0cc3ebcb22cb983af981d7c128fc8bad30b6bc2` | [sepolia.voyager.online](https://sepolia.voyager.online) | | SUAVE Toliman Testnet | 33626250 | 33626250 | `0xD5eB5fa3f470eBBB93a4A58C644c87031268a04A` | [explorer.toliman.suave.flashbots.net](https://explorer.toliman.suave.flashbots.net) | | Tron Testnet | 346621343 | 2494104990 | `0xb61027dEe5d84d013A3f3979E1B54Eae189b7F7d` | [shasta.tronscan.org](https://shasta.tronscan.org/#) | # ProxyAdmin Source: https://docs.hyperlane.xyz/docs/reference/addresses/deployments/proxyAdmin ProxyAdmin deployments across Mainnet and Testnet ## Mainnet | Chain | Domain ID | Chain ID | Address | Explorer | | --------------------- | ---------- | ---------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | | Abstract | 2741 | 2741 | `0x038F9F4e93e88Af2C688da265222FdE80e455aA4` | [abscan.org](https://abscan.org) | | ADI Chain | 36900 | 36900 | `0x0be2Ae2f6D02a3e0e00ECB57D3E1fCbb7f8F38F4` | [explorer.adichain](https://explorer.adichain) | | Ancient8 | 888888888 | 888888888 | `0x0761b0827849abbf7b0cC09CE14e1C93D87f5004` | [scan.ancient8.gg](https://scan.ancient8.gg) | | ApeChain | 33139 | 33139 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [apescan.io](https://apescan.io) | | AppChain | 466 | 466 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.appchain.xyz](https://explorer.appchain.xyz) | | Arbitrum | 42161 | 42161 | `0x80Cebd56A65e46c474a1A101e89E76C4c51D179c` | [arbiscan.io](https://arbiscan.io) | | Arcadia | 4278608 | 4278608 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.arcadia.khalani.network](https://explorer.arcadia.khalani.network) | | Artela | 11820 | 11820 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [artscan.artela.network](https://artscan.artela.network) | | Astar | 592 | 592 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [astar.blockscout.com](https://astar.blockscout.com) | | Avalanche | 43114 | 43114 | `0xd7CF8c05fd81b8cA7CfF8E6C49B08a9D63265c9B` | [snowtrace.io](https://snowtrace.io) | | Base | 8453 | 8453 | `0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1` | [basescan.org](https://basescan.org) | | Berachain | 80094 | 80094 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [beratrail.io](https://beratrail.io) | | Bitlayer | 200901 | 200901 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [www.btrscan.com](https://www.btrscan.com) | | Blast | 81457 | 81457 | `0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D` | [blastscan.io](https://blastscan.io) | | BOB | 60808 | 60808 | `0x95878Fd41bC26f7045C0b98e381c22f010745A75` | [explorer.gobob.xyz](https://explorer.gobob.xyz) | | Boba Mainnet | 288 | 288 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [bobascan.com](https://bobascan.com) | | Botanix | 3637 | 3637 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [botanixscan.io](https://botanixscan.io) | | Binance Smart Chain | 56 | 56 | `0x65993Af9D0D3a64ec77590db7ba362D6eB78eF70` | [bscscan.com](https://bscscan.com) | | CarrChain | 7667 | 7667 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [carrscan.io](https://carrscan.io) | | Celo | 42220 | 42220 | `0x90f9a2E9eCe93516d65FdaB726a3c62F5960a1b9` | [celoscan.io](https://celoscan.io) | | Chiliz | 1000088888 | 88888 | `0x48C427782Bc1e9ecE406b3e277481b28ABcBdf03` | [chiliscan.com](https://chiliscan.com) | | Citrea | 4114 | 4114 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.mainnet.citrea.xyz](https://explorer.mainnet.citrea.xyz) | | Core | 1116 | 1116 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [scan.coredao.org](https://scan.coredao.org) | | Coti | 2632500 | 2632500 | `0xC343A7054838FE9F249D7E3Ec1Fa6f1D108694b8` | [mainnet.cotiscan.io](https://mainnet.cotiscan.io) | | Cyber | 7560 | 7560 | `0x0761b0827849abbf7b0cC09CE14e1C93D87f5004` | [cyberscan.co](https://cyberscan.co) | | Eden | 714 | 714 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | N/A | | Electroneum | 52014 | 52014 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [blockexplorer.electroneum.com](https://blockexplorer.electroneum.com) | | Endurance | 648 | 648 | `0x0761b0827849abbf7b0cC09CE14e1C93D87f5004` | [explorer-endurance.fusionist.io](https://explorer-endurance.fusionist.io) | | ENI | 173 | 173 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [scan.eniac.network](https://scan.eniac.network) | | Ethereum | 1 | 1 | `0x75EE15Ee1B4A75Fa3e2fDF5DF3253c25599cc659` | [etherscan.io](https://etherscan.io) | | Everclear | 25327 | 25327 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [scan.everclear.org](https://scan.everclear.org) | | Flare | 14 | 14 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [flare-explorer.flare.network](https://flare-explorer.flare.network) | | EVM on Flow | 1000000747 | 747 | `0x5dfcCe8da81B542426211C99fCCfeD647e9AA496` | [evm.flowscan.io](https://evm.flowscan.io) | | Fluence | 9999999 | 9999999 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [blockscout.mainnet.fluence.dev](https://blockscout.mainnet.fluence.dev) | | Fluent | 25363 | 25363 | `0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D` | [fluentscan.xyz](https://fluentscan.xyz) | | Fraxtal | 252 | 252 | `0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7` | [fraxscan.com](https://fraxscan.com) | | Fuse | 122 | 122 | `0x6A7398A6a0fB842725afa0A5F1641FC6C9FF89cf` | [explorer.fuse.io](https://explorer.fuse.io) | | Galactica | 613419 | 613419 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.galactica.com](https://explorer.galactica.com) | | Gnosis | 100 | 100 | `0x81a92A1a272cb09d7b4970b07548463dC7aE0cB7` | [gnosisscan.io](https://gnosisscan.io) | | Gravity Alpha Mainnet | 1625 | 1625 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.gravity.xyz](https://explorer.gravity.xyz) | | Hashkey | 177 | 177 | `0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D` | [explorer.hsk.xyz](https://explorer.hsk.xyz) | | Hemi Network | 43111 | 43111 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.hemi.xyz](https://explorer.hemi.xyz) | | HyperEVM | 999 | 999 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [www.hyperscan.com](https://www.hyperscan.com) | | Igra | 38833 | 38833 | `0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D` | [explorer.igralabs.com](https://explorer.igralabs.com) | | Immutable zkEVM | 1000013371 | 13371 | `0x2f0E57527Bb37E5E064EF243fad56CCE6241906c` | [explorer.immutable.com](https://explorer.immutable.com) | | Incentiv | 24101 | 24101 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.incentiv.io](http://explorer.incentiv.io) | | Ink | 57073 | 57073 | `0x3a464f746D23Ab22155710f44dB16dcA53e0775E` | [explorer.inkonchain.com](https://explorer.inkonchain.com) | | Kaia | 8217 | 8217 | `0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D` | [kaiascope.com](https://kaiascope.com) | | Katana | 747474 | 747474 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.katanarpc.com](https://explorer.katanarpc.com) | | Kiichain | 1783 | 1783 | `0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D` | [mainnet.explorer.kiichain.io](https://mainnet.explorer.kiichain.io) | | Krown | 1983 | 1983 | `0x81a92A1a272cb09d7b4970b07548463dC7aE0cB7` | N/A | | LazAI | 52924 | 52924 | `0x23ce76645EC601148fa451e751eeB75785b97A00` | [explorer.mainnet.lazai.network](https://explorer.mainnet.lazai.network) | | Linea | 59144 | 59144 | `0x7f50C5776722630a0024fAE05fDe8b47571D7B39` | [lineascan.build](https://lineascan.build) | | Lisk | 1135 | 1135 | `0x0761b0827849abbf7b0cC09CE14e1C93D87f5004` | [blockscout.lisk.com](https://blockscout.lisk.com) | | Lit Chain | 175200 | 175200 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [lit-chain-explorer.litprotocol.com](https://lit-chain-explorer.litprotocol.com) | | LUKSO | 42 | 42 | `0x0761b0827849abbf7b0cC09CE14e1C93D87f5004` | [explorer.execution.mainnet.lukso.network](https://explorer.execution.mainnet.lukso.network) | | Lumia Prism | 1000073017 | 994873017 | `0x200183De44bf765ECB73cD62A74010EaaBC43146` | [explorer.lumia.org](https://explorer.lumia.org) | | Manta Pacific | 169 | 169 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [pacific-explorer.manta.network](https://pacific-explorer.manta.network) | | Mantle | 5000 | 5000 | `0x14c3CEee8F431aE947364f43429a98EA89800238` | [explorer.mantle.xyz](https://explorer.mantle.xyz) | | MANTRA | 5888 | 5888 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [blockscout.mantrascan.io](https://blockscout.mantrascan.io) | | Matchain | 698 | 698 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [matchscan.io](https://matchscan.io) | | MegaETH | 4326 | 4326 | `0x61DDB465eEA5bc3708Cf8B53156aC91a77A2f029` | [megaeth.blockscout.com](https://megaeth.blockscout.com) | | Metal L2 | 1000001750 | 1750 | `0x7C012DCA02C42cfA3Fd7Da3B0ED7234B52AE68eF` | [explorer.metall2.com](https://explorer.metall2.com) | | Metis Andromeda | 1088 | 1088 | `0x0761b0827849abbf7b0cC09CE14e1C93D87f5004` | [andromeda-explorer.metis.io](https://andromeda-explorer.metis.io) | | Miraclechain | 92278 | 92278 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.miracleplay.io](https://explorer.miracleplay.io) | | Mitosis | 124816 | 124816 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [mitoscan.io](https://mitoscan.io) | | Moca Chain | 2288 | 2288 | `0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D` | [moca-mainnet.cloud.blockscout.com](https://moca-mainnet.cloud.blockscout.com) | | Mode | 34443 | 34443 | `0x0761b0827849abbf7b0cC09CE14e1C93D87f5004` | [explorer.mode.network](https://explorer.mode.network) | | Molten | 360 | 360 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [molten.calderaexplorer.xyz](https://molten.calderaexplorer.xyz) | | Monad | 143 | 143 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [mainnet-beta.monvision.io](https://mainnet-beta.monvision.io) | | Morph | 2818 | 2818 | `0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D` | [explorer.morphl2.io](https://explorer.morphl2.io) | | Nibiru | 6900 | 6900 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [nibiscan.io](https://nibiscan.io) | | Ontology | 58 | 58 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.ont.io](https://explorer.ont.io) | | Oort | 970 | 970 | `0x148CF67B8A242c1360bb2C93fCe203EC4d4f9B56` | [mainnet-scan.oortech.com](https://mainnet-scan.oortech.com) | | opBNB | 204 | 204 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [opbnb.bscscan.com](https://opbnb.bscscan.com) | | Optimism | 10 | 10 | `0xE047cb95FB3b7117989e911c6afb34771183fC35` | [optimistic.etherscan.io](https://optimistic.etherscan.io) | | Orderly L2 | 291 | 291 | `0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D` | [explorer.orderly.network](https://explorer.orderly.network) | | Paradex | 514051890 | 0x505249564154455f534e5f50415241434c4541525f4d41494e4e4554 | `0x0000000000000000000000000000000000000000000000000000000000000000` | [voyager.prod.paradex.trade](https://voyager.prod.paradex.trade) | | Peaq | 3338 | 3338 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [peaq.subscan.io](https://peaq.subscan.io) | | Plasma | 9745 | 9745 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [plasmascan.to](https://plasmascan.to) | | Plume | 98866 | 98866 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.plume.org](https://explorer.plume.org) | | Polygon | 137 | 137 | `0xC4F7590C5d30BE959225dC75640657954A86b980` | [polygonscan.com](https://polygonscan.com) | | Polynomial | 1000008008 | 8008 | `0x5bdADEAD721Eb4C4038fF7c989E3C7BbBA302435` | [polynomialscan.io](https://polynomialscan.io) | | Prom | 227 | 227 | `0x9534122Aae7978dB8f5f10dF4432233c53e820A1` | [prom-blockscout.eu-north-2.gateway.fm](https://prom-blockscout.eu-north-2.gateway.fm) | | PulseChain | 369 | 369 | `0xEe3147deeDFC0c6DDD7c65D4e9ff9a48632BE645` | [scan.pulsechain.box](https://scan.pulsechain.box) | | RARI Chain | 1000012617 | 1380012617 | `0x4Ee9dEBB3046139661b51E17bdfD54Fd63211de7` | [mainnet.explorer.rarichain.org](https://mainnet.explorer.rarichain.org) | | Reactive Mainnet | 1597 | 1597 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [reactscan.net](https://reactscan.net) | | Redstone | 690 | 690 | `0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1` | [explorer.redstone.xyz](https://explorer.redstone.xyz) | | Ronin | 2020 | 2020 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [app.roninchain.com](https://app.roninchain.com) | | Sei | 1329 | 1329 | `0x0761b0827849abbf7b0cC09CE14e1C93D87f5004` | [seitrace.com](https://seitrace.com) | | Shibarium | 109 | 109 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [shibariumscan.io](https://shibariumscan.io) | | Somnia | 5031 | 5031 | `0x3E12271EbD523d0886D0D51A4FF8D8e046CF2E1D` | [explorer.somnia.network](https://explorer.somnia.network) | | Soneium | 1868 | 1868 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [soneium.blockscout.com](https://soneium.blockscout.com) | | Sonic | 146 | 146 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [sonicscan.org](https://sonicscan.org) | | Sophon | 50104 | 50104 | `0x038F9F4e93e88Af2C688da265222FdE80e455aA4` | [explorer.sophon.xyz](https://explorer.sophon.xyz) | | Stable | 988 | 988 | `0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D` | [stablescan.xyz](https://stablescan.xyz) | | Starknet | 358974494 | 0x534e5f4d41494e | `0x0000000000000000000000000000000000000000000000000000000000000000` | [voyager.online](https://voyager.online) | | Subtensor | 964 | 964 | `0x82825C0884558C9c5A94B545e7563c95aBA49197` | [evm.taostats.io](https://evm.taostats.io) | | Superseed | 5330 | 5330 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.superseed.xyz](https://explorer.superseed.xyz) | | Swell | 1923 | 1923 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.swellnetwork.io](https://explorer.swellnetwork.io) | | TAC | 239 | 239 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.tac.build](https://explorer.tac.build) | | Taiko | 167000 | 167000 | `0x398633D19f4371e1DB5a8EFE90468eB70B1176AA` | [taikoscan.io](https://taikoscan.io) | | Tempo | 4217 | 4217 | `0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D` | [explore.tempo.xyz](https://explore.tempo.xyz) | | Torus | 21000 | 21000 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [blockscout.torus.network](https://blockscout.torus.network) | | Tron | 728126428 | 728126428 | `0x1a3C9CC2E160fA605Cdf7befDe0cc21e89F3Ca07` | [tronscan.org](https://tronscan.org/#) | | Unichain | 130 | 130 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [uniscan.xyz](https://uniscan.xyz) | | Vana | 1480 | 1480 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [vanascan.io](https://vanascan.io) | | Viction | 88 | 88 | `0x0761b0827849abbf7b0cC09CE14e1C93D87f5004` | [www.vicscan.xyz](https://www.vicscan.xyz) | | World Chain | 480 | 480 | `0x0761b0827849abbf7b0cC09CE14e1C93D87f5004` | [worldscan.org](https://worldscan.org) | | Xai | 660279 | 660279 | `0x0761b0827849abbf7b0cC09CE14e1C93D87f5004` | [explorer.xai-chain.net](https://explorer.xai-chain.net) | | XLayer | 196 | 196 | `0x0761b0827849abbf7b0cC09CE14e1C93D87f5004` | [www.oklink.com](https://www.oklink.com/xlayer) | | XRPL EVM | 1440000 | 1440000 | `0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7` | [explorer.xrplevm.org](https://explorer.xrplevm.org) | | 0G | 16661 | 16661 | `0x02d16BC51af6BfD153d67CA61754cF912E82C4d9` | [chainscan.0g.ai](https://chainscan.0g.ai) | | ZetaChain | 7000 | 7000 | `0x0761b0827849abbf7b0cC09CE14e1C93D87f5004` | [explorer.zetachain.com](https://explorer.zetachain.com) | | Zircuit | 48900 | 48900 | `0xA5580D7Af50F3FD869EbEA51e352e2656F8DD5C2` | [explorer.zircuit.com](https://explorer.zircuit.com) | | zkSync | 324 | 324 | `0xD01274DC164D32F8595bE707F221375E68cE300C` | [explorer.zksync.io](https://explorer.zksync.io) | | Zora | 7777777 | 7777777 | `0x632b4F32d65F7b25B37a27C57dD510f8e4a58Bf9` | [explorer.zora.energy](https://explorer.zora.energy) | ## Testnet | Chain | Domain ID | Chain ID | Address | Explorer | | ----------------------- | --------- | ---------- | -------------------------------------------- | ------------------------------------------------------------------------------------ | | Arbitrum Sepolia | 421614 | 421614 | `0x666a24F62f7A97BA33c151776Eb3D9441a059eB8` | [sepolia.arbiscan.io](https://sepolia.arbiscan.io) | | Base Sepolia | 84532 | 84532 | `0x44b764045BfDC68517e10e783E69B376cef196B2` | [sepolia.basescan.org](https://sepolia.basescan.org) | | BSC Testnet | 97 | 97 | `0xb12282d2E838Aa5f2A4F9Ee5f624a77b7199A078` | [testnet.bscscan.com](https://testnet.bscscan.com) | | Celo Sepolia | 11142220 | 11142220 | `0x267B6B6eAf6790faE5D5E9070F28a9cE64CbF279` | [celo-sepolia.blockscout.com](https://celo-sepolia.blockscout.com) | | Coti Testnet | 7082400 | 7082400 | `0x833Dad7FF66884389D5F0cEcba446ffaa7d2837e` | [testnet.cotiscan.io](https://testnet.cotiscan.io) | | Fuji | 43113 | 43113 | `0x378dA02f7dC3c23A8B5ecE32b8056CdF01e8d477` | [testnet.snowtrace.io](https://testnet.snowtrace.io) | | Hyperliquid EVM Testnet | 998 | 998 | `0x6966b0E55883d49BFB24539356a2f8A673E02039` | [explorer.hyperlend.finance](https://explorer.hyperlend.finance) | | Incentiv Testnet v2 | 28802 | 28802 | `0xD221ffdAa65518BF56c8623e04eA0380CE1BfaE2` | [explorer-testnet.incentiv.io](https://explorer-testnet.incentiv.io) | | Mode Testnet | 919 | 919 | `0x6966b0E55883d49BFB24539356a2f8A673E02039` | [testnet.modescan.io](https://testnet.modescan.io) | | Optimism Sepolia | 11155420 | 11155420 | `0x44b764045BfDC68517e10e783E69B376cef196B2` | [sepolia-optimistic.etherscan.io](https://sepolia-optimistic.etherscan.io) | | Polygon Amoy | 80002 | 80002 | `0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2` | [amoy.polygonscan.com](https://amoy.polygonscan.com) | | Sepolia | 11155111 | 11155111 | `0x97Bbc6bBaFa5Ce3b2FA966c121Af63bD09e940f8` | [sepolia.etherscan.io](https://sepolia.etherscan.io) | | Somnia Testnet | 50312 | 50312 | `0xD3d062a5dcBA85ae863618d4c264d2358300c283` | [shannon-explorer.somnia.network](https://shannon-explorer.somnia.network) | | Sonic Testnet | 64165 | 64165 | `0x54148470292C24345fb828B003461a9444414517` | [testnet.soniclabs.com](https://testnet.soniclabs.com) | | SUAVE Toliman Testnet | 33626250 | 33626250 | `0x54148470292C24345fb828B003461a9444414517` | [explorer.toliman.suave.flashbots.net](https://explorer.toliman.suave.flashbots.net) | | Tangle Testnet | 3799 | 3799 | `0xF19B75ea28F0f97d3bd267d35F2a8D30A667967C` | [testnet-explorer.tangle.tools](https://testnet-explorer.tangle.tools) | | Tron Testnet | 346621343 | 2494104990 | `0xBb17318f23C0124937592263aCC58E4CED668D36` | [shasta.tronscan.org](https://shasta.tronscan.org/#) | # StorageGasOracle Source: https://docs.hyperlane.xyz/docs/reference/addresses/deployments/storageGasOracle StorageGasOracle deployments across Mainnet and Testnet ## Mainnet | Chain | Domain ID | Chain ID | Address | Explorer | | --------------------- | ---------- | ---------- | -------------------------------------------- | -------------------------------------------------------------------------------------------- | | Abstract | 2741 | 2741 | `0x1cE4d0E16570C362feef85Ce2713555fCbd3dBC7` | [abscan.org](https://abscan.org) | | ADI Chain | 36900 | 36900 | `0x5244d3359065C883BDfeEEff5329DE38c0Bd227e` | [explorer.adichain](https://explorer.adichain) | | Ancient8 | 888888888 | 888888888 | `0x59Bf7c7b458375b1A7c453aE70EaCb376E65CDAF` | [scan.ancient8.gg](https://scan.ancient8.gg) | | ApeChain | 33139 | 33139 | `0xF1854214392864c628A16930E73B699f7a51b3EE` | [apescan.io](https://apescan.io) | | AppChain | 466 | 466 | `0xA376b27212D608324808923Add679A2c9FAFe9Da` | [explorer.appchain.xyz](https://explorer.appchain.xyz) | | Arbitrum | 42161 | 42161 | `0xD3805207b65d99C075ceA938Fa7c0587026a5DF5` | [arbiscan.io](https://arbiscan.io) | | Arcadia | 4278608 | 4278608 | `0x3862A9B1aCd89245a59002C2a08658EC1d5690E3` | [explorer.arcadia.khalani.network](https://explorer.arcadia.khalani.network) | | Artela | 11820 | 11820 | `0x60515f328B2c55Df63f456D9D839a0082892dEf8` | [artscan.artela.network](https://artscan.artela.network) | | Astar | 592 | 592 | `0xA38D1D7F217A52A27b0e6BF50E0a9ddAD05798C0` | [astar.blockscout.com](https://astar.blockscout.com) | | Avalanche | 43114 | 43114 | `0x175821F30AdCAA4bbB72Ce98eF76C2E0De2C3f21` | [snowtrace.io](https://snowtrace.io) | | Base | 8453 | 8453 | `0xBF12ef4B9f307463D3FB59c3604F294dDCe287E2` | [basescan.org](https://basescan.org) | | Berachain | 80094 | 80094 | `0xb201817dFdd822B75Fa9b595457E6Ee466a7C187` | [beratrail.io](https://beratrail.io) | | Bitlayer | 200901 | 200901 | `0xA38D1D7F217A52A27b0e6BF50E0a9ddAD05798C0` | [www.btrscan.com](https://www.btrscan.com) | | Blast | 81457 | 81457 | `0xBDa330Ea8F3005C421C8088e638fBB64fA71b9e0` | [blastscan.io](https://blastscan.io) | | BOB | 60808 | 60808 | `0x2Fca7f6eC3d4A0408900f2BB30004d4616eE985E` | [explorer.gobob.xyz](https://explorer.gobob.xyz) | | Boba Mainnet | 288 | 288 | `0xbb0AE51BCa526cF313b6a95BfaB020794af6C394` | [bobascan.com](https://bobascan.com) | | Botanix | 3637 | 3637 | `0xA9Adb480F10547f10202173a49b7F52116304476` | [botanixscan.io](https://botanixscan.io) | | Binance Smart Chain | 56 | 56 | `0x91d23D603d60445411C06e6443d81395593B7940` | [bscscan.com](https://bscscan.com) | | CarrChain | 7667 | 7667 | `0xC4F464C89184c7870858A8B12ca822daB6ed04F3` | [carrscan.io](https://carrscan.io) | | Celo | 42220 | 42220 | `0xD9A9966E7dA9a7f0032bF449FB12696a638E673C` | [celoscan.io](https://celoscan.io) | | Chiliz | 1000088888 | 88888 | `0x87ED6926abc9E38b9C7C19f835B41943b622663c` | [chiliscan.com](https://chiliscan.com) | | Citrea | 4114 | 4114 | `0x466b330C2e360c0214A9Da2428415298f720883E` | [explorer.mainnet.citrea.xyz](https://explorer.mainnet.citrea.xyz) | | Core | 1116 | 1116 | `0xA38D1D7F217A52A27b0e6BF50E0a9ddAD05798C0` | [scan.coredao.org](https://scan.coredao.org) | | Coti | 2632500 | 2632500 | `0x5244d3359065C883BDfeEEff5329DE38c0Bd227e` | [mainnet.cotiscan.io](https://mainnet.cotiscan.io) | | Cyber | 7560 | 7560 | `0x7b2e996742fA42d223652A344252B725D1bC428C` | [cyberscan.co](https://cyberscan.co) | | Eden | 714 | 714 | `0x4B44e4305B42405382b7BeC717F64D0552a9D9Fe` | N/A | | Electroneum | 52014 | 52014 | `0xcDD89f19b2d00DCB9510BB3fBd5eCeCa761fe5Ab` | [blockexplorer.electroneum.com](https://blockexplorer.electroneum.com) | | Endurance | 648 | 648 | `0xe243Fb51d91c5DE62afAbE44F7Ed2D4DC51668C6` | [explorer-endurance.fusionist.io](https://explorer-endurance.fusionist.io) | | ENI | 173 | 173 | `0x7B8AA8f23Ab6B0757eC6FC71894211376D9335b0` | [scan.eniac.network](https://scan.eniac.network) | | Ethereum | 1 | 1 | `0xc9a103990A8dB11b4f627bc5CD1D0c2685484Ec5` | [etherscan.io](https://etherscan.io) | | Everclear | 25327 | 25327 | `0xf8344D85a1429708e0BE6724218E938087e596DF` | [scan.everclear.org](https://scan.everclear.org) | | Flare | 14 | 14 | `0xA38D1D7F217A52A27b0e6BF50E0a9ddAD05798C0` | [flare-explorer.flare.network](https://flare-explorer.flare.network) | | EVM on Flow | 1000000747 | 747 | `0xa2554A53890c0E769e3fa8b9A0b7e72F6A617367` | [evm.flowscan.io](https://evm.flowscan.io) | | Fluence | 9999999 | 9999999 | `0x4A91738390a3D55CB27c2863e8950c9cD1b89d0e` | [blockscout.mainnet.fluence.dev](https://blockscout.mainnet.fluence.dev) | | Fluent | 25363 | 25363 | `0x7B8AA8f23Ab6B0757eC6FC71894211376D9335b0` | [fluentscan.xyz](https://fluentscan.xyz) | | Fraxtal | 252 | 252 | `0x5060eCD5dFAD300A90592C04e504600A7cdcF70b` | [fraxscan.com](https://fraxscan.com) | | Fuse | 122 | 122 | `0x61374178e45F65fF9D6252d017Cd580FC60B7654` | [explorer.fuse.io](https://explorer.fuse.io) | | Galactica | 613419 | 613419 | `0x794Fe7970EE45945b0ad2667f99A5bBc9ddfB5d7` | [explorer.galactica.com](https://explorer.galactica.com) | | Gnosis | 100 | 100 | `0x5E01d8F34b629E3f92d69546bbc4142A7Adee7e9` | [gnosisscan.io](https://gnosisscan.io) | | Gravity Alpha Mainnet | 1625 | 1625 | `0xD0dca420feFda68537695A8D887080eeF4030AF7` | [explorer.gravity.xyz](https://explorer.gravity.xyz) | | Hashkey | 177 | 177 | `0xBCD18636e5876DFd7AAb5F2B2a5Eb5ca168BA1d8` | [explorer.hsk.xyz](https://explorer.hsk.xyz) | | Hemi Network | 43111 | 43111 | `0x60515f328B2c55Df63f456D9D839a0082892dEf8` | [explorer.hemi.xyz](https://explorer.hemi.xyz) | | HyperEVM | 999 | 999 | `0xd766e7C7517f2d0D92754b2fe4aE7AdEf7bDEC3e` | [www.hyperscan.com](https://www.hyperscan.com) | | Igra | 38833 | 38833 | `0x9fE454AA2B01fc7A2a777AE561bc58Ce560CD5a9` | [explorer.igralabs.com](https://explorer.igralabs.com) | | Immutable zkEVM | 1000013371 | 13371 | `0x9c2214467Daf9e2e1F45b36d08ce0b9C65BFeA88` | [explorer.immutable.com](https://explorer.immutable.com) | | Incentiv | 24101 | 24101 | `0xC4F464C89184c7870858A8B12ca822daB6ed04F3` | [explorer.incentiv.io](http://explorer.incentiv.io) | | Ink | 57073 | 57073 | `0x9e8b689e83d929cb8c2d9166E55319a4e6aA83B7` | [explorer.inkonchain.com](https://explorer.inkonchain.com) | | Kaia | 8217 | 8217 | `0x2F619Ac5122689180AeBB930ADccdae215d538a9` | [kaiascope.com](https://kaiascope.com) | | Katana | 747474 | 747474 | `0xA9Adb480F10547f10202173a49b7F52116304476` | [explorer.katanarpc.com](https://explorer.katanarpc.com) | | Kiichain | 1783 | 1783 | `0x7B8AA8f23Ab6B0757eC6FC71894211376D9335b0` | [mainnet.explorer.kiichain.io](https://mainnet.explorer.kiichain.io) | | Krown | 1983 | 1983 | `0x89Ebf977E83087959aD78e5372F4AF15DcdC8143` | N/A | | LazAI | 52924 | 52924 | `0x0DbB60c348DF645c295Fd0ce26F87bB850710185` | [explorer.mainnet.lazai.network](https://explorer.mainnet.lazai.network) | | Linea | 59144 | 59144 | `0x781bE492F1232E66990d83a9D3AC3Ec26f56DAfB` | [lineascan.build](https://lineascan.build) | | Lisk | 1135 | 1135 | `0x7b2e996742fA42d223652A344252B725D1bC428C` | [blockscout.lisk.com](https://blockscout.lisk.com) | | Lit Chain | 175200 | 175200 | `0x5887BDA66EC9e854b0da6BFFe423511e69d327DC` | [lit-chain-explorer.litprotocol.com](https://lit-chain-explorer.litprotocol.com) | | LUKSO | 42 | 42 | `0x5F954cA945671e48466680eA815727948Ca340ef` | [explorer.execution.mainnet.lukso.network](https://explorer.execution.mainnet.lukso.network) | | Lumia Prism | 1000073017 | 994873017 | `0x3c38fC01159E7BE0685653A0C896eA49F2BAa7c1` | [explorer.lumia.org](https://explorer.lumia.org) | | Manta Pacific | 169 | 169 | `0x19dc38aeae620380430C200a6E990D5Af5480117` | [pacific-explorer.manta.network](https://pacific-explorer.manta.network) | | Mantle | 5000 | 5000 | `0xf9DbC8776Bc2812c4DBEc45383A1783Ac758Fb55` | [explorer.mantle.xyz](https://explorer.mantle.xyz) | | MANTRA | 5888 | 5888 | `0x5887BDA66EC9e854b0da6BFFe423511e69d327DC` | [blockscout.mantrascan.io](https://blockscout.mantrascan.io) | | Matchain | 698 | 698 | `0xff72A726Ce261846f2dF6F32113e514b5Ddb0E37` | [matchscan.io](https://matchscan.io) | | MegaETH | 4326 | 4326 | `0x4A91738390a3D55CB27c2863e8950c9cD1b89d0e` | [megaeth.blockscout.com](https://megaeth.blockscout.com) | | Metal L2 | 1000001750 | 1750 | `0xE7487b4DF583c63D6841997ab56324D0a825e7F4` | [explorer.metall2.com](https://explorer.metall2.com) | | Metis Andromeda | 1088 | 1088 | `0x7b2e996742fA42d223652A344252B725D1bC428C` | [andromeda-explorer.metis.io](https://andromeda-explorer.metis.io) | | Miraclechain | 92278 | 92278 | `0x794Fe7970EE45945b0ad2667f99A5bBc9ddfB5d7` | [explorer.miracleplay.io](https://explorer.miracleplay.io) | | Mitosis | 124816 | 124816 | `0xf6092016a7bef22F7aC9C982C9E96D968F709C05` | [mitoscan.io](https://mitoscan.io) | | Moca Chain | 2288 | 2288 | `0x7B8AA8f23Ab6B0757eC6FC71894211376D9335b0` | [moca-mainnet.cloud.blockscout.com](https://moca-mainnet.cloud.blockscout.com) | | Mode | 34443 | 34443 | `0xC9B8ea6230d6687a4b13fD3C0b8f0Ec607B26465` | [explorer.mode.network](https://explorer.mode.network) | | Molten | 360 | 360 | `0xA38D1D7F217A52A27b0e6BF50E0a9ddAD05798C0` | [molten.calderaexplorer.xyz](https://molten.calderaexplorer.xyz) | | Monad | 143 | 143 | `0xC4F464C89184c7870858A8B12ca822daB6ed04F3` | [mainnet-beta.monvision.io](https://mainnet-beta.monvision.io) | | Morph | 2818 | 2818 | `0x2F619Ac5122689180AeBB930ADccdae215d538a9` | [explorer.morphl2.io](https://explorer.morphl2.io) | | Nibiru | 6900 | 6900 | `0xf303B04d9ad21dAe2658Cf302478A424e0B45368` | [nibiscan.io](https://nibiscan.io) | | Ontology | 58 | 58 | `0xc5068BB6803ADbe5600DE5189fe27A4dAcE31170` | [explorer.ont.io](https://explorer.ont.io) | | Oort | 970 | 970 | `0x2c61Cda929e4e2174cb10cd8e2724A9ceaD62E67` | [mainnet-scan.oortech.com](https://mainnet-scan.oortech.com) | | opBNB | 204 | 204 | `0x7947b7Fe737B4bd1D3387153f32148974066E591` | [opbnb.bscscan.com](https://opbnb.bscscan.com) | | Optimism | 10 | 10 | `0x27e88AeB8EA4B159d81df06355Ea3d20bEB1de38` | [optimistic.etherscan.io](https://optimistic.etherscan.io) | | Orderly L2 | 291 | 291 | `0x2F619Ac5122689180AeBB930ADccdae215d538a9` | [explorer.orderly.network](https://explorer.orderly.network) | | Peaq | 3338 | 3338 | `0x4A91738390a3D55CB27c2863e8950c9cD1b89d0e` | [peaq.subscan.io](https://peaq.subscan.io) | | Plasma | 9745 | 9745 | `0xcDD89f19b2d00DCB9510BB3fBd5eCeCa761fe5Ab` | [plasmascan.to](https://plasmascan.to) | | Plume | 98866 | 98866 | `0x1e4dE25C3b07c8DF66D4c193693d8B5f3b431d51` | [explorer.plume.org](https://explorer.plume.org) | | Polygon | 137 | 137 | `0xA3a24EC5670F1F416AB9fD554FcE2f226AE9D7eB` | [polygonscan.com](https://polygonscan.com) | | Polynomial | 1000008008 | 8008 | `0x2b79328DA089E89A9E9c08732b56dd31F01011Db` | [polynomialscan.io](https://polynomialscan.io) | | Prom | 227 | 227 | `0x33E0c225A54a0A86E9B267e90A90DE8CBb0fDB8f` | [prom-blockscout.eu-north-2.gateway.fm](https://prom-blockscout.eu-north-2.gateway.fm) | | PulseChain | 369 | 369 | `0xe974B5F169a5770DbfFB20F669e662Bd721c9Cc4` | [scan.pulsechain.box](https://scan.pulsechain.box) | | RARI Chain | 1000012617 | 1380012617 | `0x16625230dD6cFe1B2bec3eCaEc7d43bA3A902CD6` | [mainnet.explorer.rarichain.org](https://mainnet.explorer.rarichain.org) | | Reactive Mainnet | 1597 | 1597 | `0x7947b7Fe737B4bd1D3387153f32148974066E591` | [reactscan.net](https://reactscan.net) | | Redstone | 690 | 690 | `0x6Fae4D9935E2fcb11fC79a64e917fb2BF14DaFaa` | [explorer.redstone.xyz](https://explorer.redstone.xyz) | | Ronin | 2020 | 2020 | `0x6e1B9f776bd415d7cC3C7458A5f0d801016918f8` | [app.roninchain.com](https://app.roninchain.com) | | Sei | 1329 | 1329 | `0x26f32245fCF5Ad53159E875d5Cae62aEcf19c2d4` | [seitrace.com](https://seitrace.com) | | Shibarium | 109 | 109 | `0xA38D1D7F217A52A27b0e6BF50E0a9ddAD05798C0` | [shibariumscan.io](https://shibariumscan.io) | | Somnia | 5031 | 5031 | `0x53642476e24E28c3218E8Da44eDEBB4adB9DE13e` | [explorer.somnia.network](https://explorer.somnia.network) | | Soneium | 1868 | 1868 | `0x1c6f404800bA49Ed581af734eA0d25c0c7d017B2` | [soneium.blockscout.com](https://soneium.blockscout.com) | | Sonic | 146 | 146 | `0x1c6f404800bA49Ed581af734eA0d25c0c7d017B2` | [sonicscan.org](https://sonicscan.org) | | Sophon | 50104 | 50104 | `0xA1ADFCa9666Bcd68b7b5C8b55e3ecC465DcDfE65` | [explorer.sophon.xyz](https://explorer.sophon.xyz) | | Stable | 988 | 988 | `0x5B7a808CaA2C3F1378B07cDd46eB8ccA52F67e3B` | [stablescan.xyz](https://stablescan.xyz) | | Subtensor | 964 | 964 | `0xEa2Bcee14eA30bbBe3018E5E7829F963230F71C3` | [evm.taostats.io](https://evm.taostats.io) | | Superseed | 5330 | 5330 | `0xbb0AE51BCa526cF313b6a95BfaB020794af6C394` | [explorer.superseed.xyz](https://explorer.superseed.xyz) | | Swell | 1923 | 1923 | `0xCDeb368Db32ecCefaf7018e152DA9120565cb572` | [explorer.swellnetwork.io](https://explorer.swellnetwork.io) | | TAC | 239 | 239 | `0xcF84aa21501483B3D907d16c8102082a0991fC5F` | [explorer.tac.build](https://explorer.tac.build) | | Taiko | 167000 | 167000 | `0x7556a0E61d577D921Cba8Fca0d7D6299d36E607E` | [taikoscan.io](https://taikoscan.io) | | Tempo | 4217 | 4217 | `0xa36172F79a248C24693a208b0CEF0e7D6FB995F0` | [explore.tempo.xyz](https://explore.tempo.xyz) | | Torus | 21000 | 21000 | `0x248aDe14C0489E20C9a7Fea5F86DBfC3702208eF` | [blockscout.torus.network](https://blockscout.torus.network) | | Tron | 728126428 | 728126428 | `0x59658f074b3Ae3BAEB66a388095152066be39661` | [tronscan.org](https://tronscan.org/#) | | Unichain | 130 | 130 | `0xbb0AE51BCa526cF313b6a95BfaB020794af6C394` | [uniscan.xyz](https://uniscan.xyz) | | Vana | 1480 | 1480 | `0xbb0AE51BCa526cF313b6a95BfaB020794af6C394` | [vanascan.io](https://vanascan.io) | | Viction | 88 | 88 | `0x19dc38aeae620380430C200a6E990D5Af5480117` | [www.vicscan.xyz](https://www.vicscan.xyz) | | World Chain | 480 | 480 | `0xe4057c5B0c43Dc18E36b08C39B419F190D29Ac2d` | [worldscan.org](https://worldscan.org) | | Xai | 660279 | 660279 | `0x7b2e996742fA42d223652A344252B725D1bC428C` | [explorer.xai-chain.net](https://explorer.xai-chain.net) | | XLayer | 196 | 196 | `0xe4057c5B0c43Dc18E36b08C39B419F190D29Ac2d` | [www.oklink.com](https://www.oklink.com/xlayer) | | XRPL EVM | 1440000 | 1440000 | `0x794Fe7970EE45945b0ad2667f99A5bBc9ddfB5d7` | [explorer.xrplevm.org](https://explorer.xrplevm.org) | | 0G | 16661 | 16661 | `0x74B2b1fC57B28e11A5bAf32a758bbC98FA7837da` | [chainscan.0g.ai](https://chainscan.0g.ai) | | ZetaChain | 7000 | 7000 | `0xC9B8ea6230d6687a4b13fD3C0b8f0Ec607B26465` | [explorer.zetachain.com](https://explorer.zetachain.com) | | Zircuit | 48900 | 48900 | `0x46fa3A5780e5B90Eaf34BDED554d5353B5ABE9E7` | [explorer.zircuit.com](https://explorer.zircuit.com) | | zkSync | 324 | 324 | `0x37f4afe769087738f0577A77ffA24abef6fCBF99` | [explorer.zksync.io](https://explorer.zksync.io) | | Zora | 7777777 | 7777777 | `0xF1854214392864c628A16930E73B699f7a51b3EE` | [explorer.zora.energy](https://explorer.zora.energy) | ## Testnet | Chain | Domain ID | Chain ID | Address | Explorer | | ----------------------- | --------- | ---------- | -------------------------------------------- | ------------------------------------------------------------------------------------ | | Arbitrum Sepolia | 421614 | 421614 | `0xddf4C3e791caCaFd26D7fb275549739B38ae6e75` | [sepolia.arbiscan.io](https://sepolia.arbiscan.io) | | Base Sepolia | 84532 | 84532 | `0x5821f3B6eE05F3dC62b43B74AB1C8F8E6904b1C8` | [sepolia.basescan.org](https://sepolia.basescan.org) | | BSC Testnet | 97 | 97 | `0x124EBCBC018A5D4Efe639f02ED86f95cdC3f6498` | [testnet.bscscan.com](https://testnet.bscscan.com) | | Celo Sepolia | 11142220 | 11142220 | `0x56c09458cC7863fff1Cc6Bcb6652Dcc3412FcA86` | [celo-sepolia.blockscout.com](https://celo-sepolia.blockscout.com) | | Coti Testnet | 7082400 | 7082400 | `0x9667EfF1556A9D092fdbeC09244CB99b677E9D1E` | [testnet.cotiscan.io](https://testnet.cotiscan.io) | | Fuji | 43113 | 43113 | `0x9305dE34306886d615B096Bdf23b94a978f6a6c0` | [testnet.snowtrace.io](https://testnet.snowtrace.io) | | Hyperliquid EVM Testnet | 998 | 998 | `0x783c4a0bB6663359281aD4a637D5af68F83ae213` | [explorer.hyperlend.finance](https://explorer.hyperlend.finance) | | Incentiv Testnet v2 | 28802 | 28802 | `0xf3e31239257b300Daa566131aA6b9e45Ef2A4266` | [explorer-testnet.incentiv.io](https://explorer-testnet.incentiv.io) | | Mode Testnet | 919 | 919 | `0x9450181a7719dAb93483d43a45473Ac2373E25B0` | [testnet.modescan.io](https://testnet.modescan.io) | | Optimism Sepolia | 11155420 | 11155420 | `0x5821f3B6eE05F3dC62b43B74AB1C8F8E6904b1C8` | [sepolia-optimistic.etherscan.io](https://sepolia-optimistic.etherscan.io) | | Polygon Amoy | 80002 | 80002 | `0xD0680F80F4f947968206806C2598Cbc5b6FE5b03` | [amoy.polygonscan.com](https://amoy.polygonscan.com) | | Sepolia | 11155111 | 11155111 | `0x71775B071F77F1ce52Ece810ce084451a3045FFe` | [sepolia.etherscan.io](https://sepolia.etherscan.io) | | Somnia Testnet | 50312 | 50312 | `0x83c55cc03cc66aAFE071698F9BE4c51F5b1561c8` | [shannon-explorer.somnia.network](https://shannon-explorer.somnia.network) | | Sonic Testnet | 64165 | 64165 | `0x7c5B5bdA7F1d1F70A6678ABb4d894612Fc76498F` | [testnet.soniclabs.com](https://testnet.soniclabs.com) | | SUAVE Toliman Testnet | 33626250 | 33626250 | `0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE` | [explorer.toliman.suave.flashbots.net](https://explorer.toliman.suave.flashbots.net) | | Tron Testnet | 346621343 | 2494104990 | `0xf2664b69C42D715E0c1162c23359a3d30872363b` | [shasta.tronscan.org](https://shasta.tronscan.org/#) | # TestRecipient Source: https://docs.hyperlane.xyz/docs/reference/addresses/deployments/testRecipient TestRecipient deployments across Mainnet and Testnet ## Mainnet | Chain | Domain ID | Chain ID | Address | Explorer | | --------------------- | ---------- | ---------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | | Abstract | 2741 | 2741 | `0xCDfE1782fDC9E74810D3B69E971d752bC4b4D6E6` | [abscan.org](https://abscan.org) | | ADI Chain | 36900 | 36900 | `0x7B8AA8f23Ab6B0757eC6FC71894211376D9335b0` | [explorer.adichain](https://explorer.adichain) | | Ancient8 | 888888888 | 888888888 | `0x2Fa570E83009eaEef3a1cbd496a9a30F05266634` | [scan.ancient8.gg](https://scan.ancient8.gg) | | ApeChain | 33139 | 33139 | `0x783EC5e105234a570eB90f314284E5dBe53bdd90` | [apescan.io](https://apescan.io) | | AppChain | 466 | 466 | `0xeF7F4367703cdf4863AD6Be34C1627d8b1C2D67a` | [explorer.appchain.xyz](https://explorer.appchain.xyz) | | Arbitrum | 42161 | 42161 | `0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35` | [arbiscan.io](https://arbiscan.io) | | Arcadia | 4278608 | 4278608 | `0x2D374F85AE2B80147CffEb34d294ce02d1afd4D8` | [explorer.arcadia.khalani.network](https://explorer.arcadia.khalani.network) | | Artela | 11820 | 11820 | `0xa2401b57A8CCBF6AbD9b7e62e28811b2b523AB2B` | [artscan.artela.network](https://artscan.artela.network) | | Astar | 592 | 592 | `0xbB22547D1dc681fe925f568f637Ff67aC06c20fc` | [astar.blockscout.com](https://astar.blockscout.com) | | Avalanche | 43114 | 43114 | `0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35` | [snowtrace.io](https://snowtrace.io) | | Base | 8453 | 8453 | `0xb7C9307fE90B9AB093c6D3EdeE3259f5378D5f03` | [basescan.org](https://basescan.org) | | Berachain | 80094 | 80094 | `0x82540c4C1C6956FC4815E583DDc6d88A782E0F3e` | [beratrail.io](https://beratrail.io) | | Bitlayer | 200901 | 200901 | `0xbB22547D1dc681fe925f568f637Ff67aC06c20fc` | [www.btrscan.com](https://www.btrscan.com) | | Blast | 81457 | 81457 | `0x17E216fBb22dF4ef8A6640ae9Cb147C92710ac84` | [blastscan.io](https://blastscan.io) | | BOB | 60808 | 60808 | `0xe03dad16074BC5EEA9A9311257BF02Eb0B6AAA2b` | [explorer.gobob.xyz](https://explorer.gobob.xyz) | | Boba Mainnet | 288 | 288 | `0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE` | [bobascan.com](https://bobascan.com) | | Botanix | 3637 | 3637 | `0x779B6a921a41ceaFbAE2e2A59B5dFfB951f8C9c8` | [botanixscan.io](https://botanixscan.io) | | Binance Smart Chain | 56 | 56 | `0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35` | [bscscan.com](https://bscscan.com) | | CarrChain | 7667 | 7667 | `0x5244d3359065C883BDfeEEff5329DE38c0Bd227e` | [carrscan.io](https://carrscan.io) | | Celo | 42220 | 42220 | `0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35` | [celoscan.io](https://celoscan.io) | | Chiliz | 1000088888 | 88888 | `0xE67Dc24970B482579923551Ede52BD35a2858989` | [chiliscan.com](https://chiliscan.com) | | Citrea | 4114 | 4114 | `0x00B11f894119065f5AE137279D1A1a208965f0cd` | [explorer.mainnet.citrea.xyz](https://explorer.mainnet.citrea.xyz) | | Core | 1116 | 1116 | `0xbB22547D1dc681fe925f568f637Ff67aC06c20fc` | [scan.coredao.org](https://scan.coredao.org) | | Coti | 2632500 | 2632500 | `0x2ed6030D204745aC0Cd6be8301C3a63bf14D97Cc` | [mainnet.cotiscan.io](https://mainnet.cotiscan.io) | | Cyber | 7560 | 7560 | `0x2c61Cda929e4e2174cb10cd8e2724A9ceaD62E67` | [cyberscan.co](https://cyberscan.co) | | Eden | 714 | 714 | `0xBC9cd961BF6c224FAc51fb049aB6788e38e4A9C0` | N/A | | Electroneum | 52014 | 52014 | `0x6D48135b7584E8Bf828B6e23110Bc0Da4252704f` | [blockexplorer.electroneum.com](https://blockexplorer.electroneum.com) | | Endurance | 648 | 648 | `0xD670c00C0Cad3D32436d7cF270e739772314A8CE` | [explorer-endurance.fusionist.io](https://explorer-endurance.fusionist.io) | | ENI | 173 | 173 | `0xA697222b77cDe62A8C47E627d5A1c49A87018236` | [scan.eniac.network](https://scan.eniac.network) | | Ethereum | 1 | 1 | `0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35` | [etherscan.io](https://etherscan.io) | | Everclear | 25327 | 25327 | `0xF15D70941dE2Bf95A23d6488eBCbedE0a444137f` | [scan.everclear.org](https://scan.everclear.org) | | Flare | 14 | 14 | `0xbB22547D1dc681fe925f568f637Ff67aC06c20fc` | [flare-explorer.flare.network](https://flare-explorer.flare.network) | | EVM on Flow | 1000000747 | 747 | `0xa7028308Ff277DB5851a95d82ED5C5256bB721F2` | [evm.flowscan.io](https://evm.flowscan.io) | | Fluence | 9999999 | 9999999 | `0xF9aE87E9ACE51aa16AED25Ca38F17D258aECb73f` | [blockscout.mainnet.fluence.dev](https://blockscout.mainnet.fluence.dev) | | Fluent | 25363 | 25363 | `0x58CA3F0D65FFd40727cF6Eb2f323151853Ad3D44` | [fluentscan.xyz](https://fluentscan.xyz) | | Fraxtal | 252 | 252 | `0x62B7592C1B6D1E43f4630B8e37f4377097840C05` | [fraxscan.com](https://fraxscan.com) | | Fuse | 122 | 122 | `0x83475ca5bEB2Eaa59A2FF48a0544ebaa4a32c2de` | [explorer.fuse.io](https://explorer.fuse.io) | | Galactica | 613419 | 613419 | `0xc8826EA18D9884A1A335b2Cd7d5f44B159084301` | [explorer.galactica.com](https://explorer.galactica.com) | | Gnosis | 100 | 100 | `0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35` | [gnosisscan.io](https://gnosisscan.io) | | Gravity Alpha Mainnet | 1625 | 1625 | `0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53` | [explorer.gravity.xyz](https://explorer.gravity.xyz) | | Hashkey | 177 | 177 | `0xD233433AeC23F8382DAd87D808F60557Ea35399f` | [explorer.hsk.xyz](https://explorer.hsk.xyz) | | Hemi Network | 43111 | 43111 | `0xa2401b57A8CCBF6AbD9b7e62e28811b2b523AB2B` | [explorer.hemi.xyz](https://explorer.hemi.xyz) | | HyperEVM | 999 | 999 | `0x4eB0d97B48711950ecB01871125c4523939c6Fce` | [www.hyperscan.com](https://www.hyperscan.com) | | Igra | 38833 | 38833 | `0x64F077915B41479901a23Aa798B30701589C5063` | [explorer.igralabs.com](https://explorer.igralabs.com) | | Immutable zkEVM | 1000013371 | 13371 | `0x01EBa6D613DC09Cb899aF1e8E8a747416d7250ad` | [explorer.immutable.com](https://explorer.immutable.com) | | Incentiv | 24101 | 24101 | `0x5244d3359065C883BDfeEEff5329DE38c0Bd227e` | [explorer.incentiv.io](http://explorer.incentiv.io) | | Ink | 57073 | 57073 | `0x65dCf8F6b3f6a0ECEdf3d0bdCB036AEa47A1d615` | [explorer.inkonchain.com](https://explorer.inkonchain.com) | | Kaia | 8217 | 8217 | `0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96` | [kaiascope.com](https://kaiascope.com) | | Katana | 747474 | 747474 | `0x779B6a921a41ceaFbAE2e2A59B5dFfB951f8C9c8` | [explorer.katanarpc.com](https://explorer.katanarpc.com) | | Kiichain | 1783 | 1783 | `0x58CA3F0D65FFd40727cF6Eb2f323151853Ad3D44` | [mainnet.explorer.kiichain.io](https://mainnet.explorer.kiichain.io) | | Krown | 1983 | 1983 | `0xcF84aa21501483B3D907d16c8102082a0991fC5F` | N/A | | LazAI | 52924 | 52924 | `0x2ed6030D204745aC0Cd6be8301C3a63bf14D97Cc` | [explorer.mainnet.lazai.network](https://explorer.mainnet.lazai.network) | | Linea | 59144 | 59144 | `0x273Bc6b01D9E88c064b6E5e409BdF998246AEF42` | [lineascan.build](https://lineascan.build) | | Lisk | 1135 | 1135 | `0x2c61Cda929e4e2174cb10cd8e2724A9ceaD62E67` | [blockscout.lisk.com](https://blockscout.lisk.com) | | Lit Chain | 175200 | 175200 | `0x89Ebf977E83087959aD78e5372F4AF15DcdC8143` | [lit-chain-explorer.litprotocol.com](https://lit-chain-explorer.litprotocol.com) | | LUKSO | 42 | 42 | `0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd` | [explorer.execution.mainnet.lukso.network](https://explorer.execution.mainnet.lukso.network) | | Lumia Prism | 1000073017 | 994873017 | `0x128Ff1d24665d55f4b77B1FDbb6d8D0Ec4a0c0a1` | [explorer.lumia.org](https://explorer.lumia.org) | | Manta Pacific | 169 | 169 | `0x4E1c88DD261BEe2941e6c1814597e30F53330428` | [pacific-explorer.manta.network](https://pacific-explorer.manta.network) | | Mantle | 5000 | 5000 | `0x62B7592C1B6D1E43f4630B8e37f4377097840C05` | [explorer.mantle.xyz](https://explorer.mantle.xyz) | | MANTRA | 5888 | 5888 | `0x89Ebf977E83087959aD78e5372F4AF15DcdC8143` | [blockscout.mantrascan.io](https://blockscout.mantrascan.io) | | Matchain | 698 | 698 | `0xFa6fDABA1d0688675f05cE1B9DE17461247Bce9e` | [matchscan.io](https://matchscan.io) | | MegaETH | 4326 | 4326 | `0xF9aE87E9ACE51aa16AED25Ca38F17D258aECb73f` | [megaeth.blockscout.com](https://megaeth.blockscout.com) | | Metal L2 | 1000001750 | 1750 | `0xc4D0b4ef01eD7091792fe3D4c039457719e2DC68` | [explorer.metall2.com](https://explorer.metall2.com) | | Metis Andromeda | 1088 | 1088 | `0x2c61Cda929e4e2174cb10cd8e2724A9ceaD62E67` | [andromeda-explorer.metis.io](https://andromeda-explorer.metis.io) | | Miraclechain | 92278 | 92278 | `0xc8826EA18D9884A1A335b2Cd7d5f44B159084301` | [explorer.miracleplay.io](https://explorer.miracleplay.io) | | Mitosis | 124816 | 124816 | `0x72246331d057741008751AB3976a8297Ce7267Bc` | [mitoscan.io](https://mitoscan.io) | | Moca Chain | 2288 | 2288 | `0x58CA3F0D65FFd40727cF6Eb2f323151853Ad3D44` | [moca-mainnet.cloud.blockscout.com](https://moca-mainnet.cloud.blockscout.com) | | Mode | 34443 | 34443 | `0x12582c7B0f43c6A667CBaA7fA8b112F7fb1E69F0` | [explorer.mode.network](https://explorer.mode.network) | | Molten | 360 | 360 | `0xbB22547D1dc681fe925f568f637Ff67aC06c20fc` | [molten.calderaexplorer.xyz](https://molten.calderaexplorer.xyz) | | Monad | 143 | 143 | `0x284226F651eb5cbd696365BC27d333028FCc5D54` | [mainnet-beta.monvision.io](https://mainnet-beta.monvision.io) | | Morph | 2818 | 2818 | `0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96` | [explorer.morphl2.io](https://explorer.morphl2.io) | | Nibiru | 6900 | 6900 | `0xBCD18636e5876DFd7AAb5F2B2a5Eb5ca168BA1d8` | [nibiscan.io](https://nibiscan.io) | | Ontology | 58 | 58 | `0xdBa3b98DC83fec149c8C8F6617700b9e45937a2b` | [explorer.ont.io](https://explorer.ont.io) | | Oort | 970 | 970 | `0x58556AaeB2e3829d52EE5E711D44735412efA43B` | [mainnet-scan.oortech.com](https://mainnet-scan.oortech.com) | | opBNB | 204 | 204 | `0x76F2cC245882ceFf209A61d75b9F0f1A3b7285fB` | [opbnb.bscscan.com](https://opbnb.bscscan.com) | | Optimism | 10 | 10 | `0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35` | [optimistic.etherscan.io](https://optimistic.etherscan.io) | | Orderly L2 | 291 | 291 | `0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96` | [explorer.orderly.network](https://explorer.orderly.network) | | Paradex | 514051890 | 0x505249564154455f534e5f50415241434c4541525f4d41494e4e4554 | `0x02ed6a7815eac67136bf8950d91cca4ab1fd3bc98d3852f361f47a6cff6d850f` | [voyager.prod.paradex.trade](https://voyager.prod.paradex.trade) | | Peaq | 3338 | 3338 | `0xF9aE87E9ACE51aa16AED25Ca38F17D258aECb73f` | [peaq.subscan.io](https://peaq.subscan.io) | | Plasma | 9745 | 9745 | `0x6D48135b7584E8Bf828B6e23110Bc0Da4252704f` | [plasmascan.to](https://plasmascan.to) | | Plume | 98866 | 98866 | `0x8D8979F2C29bA49FAb259A826D0271c43F70288c` | [explorer.plume.org](https://explorer.plume.org) | | Polygon | 137 | 137 | `0x36FdA966CfffF8a9Cdc814f546db0e6378bFef35` | [polygonscan.com](https://polygonscan.com) | | Polynomial | 1000008008 | 8008 | `0xa1c3884EbE24Cccb120B2E98a55f85140563aa4C` | [polynomialscan.io](https://polynomialscan.io) | | Prom | 227 | 227 | `0x83f647970B213675412b76e1cCDB55D0e35365fD` | [prom-blockscout.eu-north-2.gateway.fm](https://prom-blockscout.eu-north-2.gateway.fm) | | PulseChain | 369 | 369 | `0x08462526f57DADfc371bc0c0cb3227eBb4576a7c` | [scan.pulsechain.box](https://scan.pulsechain.box) | | RARI Chain | 1000012617 | 1380012617 | `0xCE8260c1b5cF2fAD15bb4B6542716b050Fdf35c9` | [mainnet.explorer.rarichain.org](https://mainnet.explorer.rarichain.org) | | Reactive Mainnet | 1597 | 1597 | `0x76F2cC245882ceFf209A61d75b9F0f1A3b7285fB` | [reactscan.net](https://reactscan.net) | | Redstone | 690 | 690 | `0x1Ab68dC4f7b6cfcd00218D4b761b7F3b5a724555` | [explorer.redstone.xyz](https://explorer.redstone.xyz) | | Ronin | 2020 | 2020 | `0x51545389E04c2Ac07d98A40b85d29B480a2AF6ce` | [app.roninchain.com](https://app.roninchain.com) | | Sei | 1329 | 1329 | `0xdB670e1a1e312BF17425b08cE55Bdf2cD8F8eD54` | [seitrace.com](https://seitrace.com) | | Shibarium | 109 | 109 | `0xbB22547D1dc681fe925f568f637Ff67aC06c20fc` | [shibariumscan.io](https://shibariumscan.io) | | Somnia | 5031 | 5031 | `0x55Dc6325F6eA1DDa5286257E1e8EE4E1d281bD8D` | [explorer.somnia.network](https://explorer.somnia.network) | | Soneium | 1868 | 1868 | `0x4Ee9dEBB3046139661b51E17bdfD54Fd63211de7` | [soneium.blockscout.com](https://soneium.blockscout.com) | | Sonic | 146 | 146 | `0x4Ee9dEBB3046139661b51E17bdfD54Fd63211de7` | [sonicscan.org](https://sonicscan.org) | | Sophon | 50104 | 50104 | `0xB35eCb9714e8f48332Af22B48C18ca21E2607438` | [explorer.sophon.xyz](https://explorer.sophon.xyz) | | Stable | 988 | 988 | `0x794Fe7970EE45945b0ad2667f99A5bBc9ddfB5d7` | [stablescan.xyz](https://stablescan.xyz) | | Starknet | 358974494 | 0x534e5f4d41494e | `0x07e75bba1a8a48e9246a3a32216a59fba3cb0bec7036610e45787b998b9f7060` | [voyager.online](https://voyager.online) | | Subtensor | 964 | 964 | `0xcDD89f19b2d00DCB9510BB3fBd5eCeCa761fe5Ab` | [evm.taostats.io](https://evm.taostats.io) | | Superseed | 5330 | 5330 | `0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE` | [explorer.superseed.xyz](https://explorer.superseed.xyz) | | Swell | 1923 | 1923 | `0xBC53dACd8c0ac0d2bAC461479EAaf5519eCC8853` | [explorer.swellnetwork.io](https://explorer.swellnetwork.io) | | TAC | 239 | 239 | `0x2f4Eb04189e11Af642237Da62d163Ab714614498` | [explorer.tac.build](https://explorer.tac.build) | | Taiko | 167000 | 167000 | `0x5fC427653b175F6De5A494DE17d1c7636d7E7965` | [taikoscan.io](https://taikoscan.io) | | Tempo | 4217 | 4217 | `0x2655CB4496239537A3D19aA28537Ef07c75569D0` | [explore.tempo.xyz](https://explore.tempo.xyz) | | Torus | 21000 | 21000 | `0x92249B8ed35C2980e58666a3EBF4a075DDD2895f` | [blockscout.torus.network](https://blockscout.torus.network) | | Tron | 728126428 | 728126428 | `0xC63B236C46d7965edAE1211f9a9E0478D46A433b` | [tronscan.org](https://tronscan.org/#) | | Unichain | 130 | 130 | `0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE` | [uniscan.xyz](https://uniscan.xyz) | | Vana | 1480 | 1480 | `0xbB88a31E4b709b645c06825c0E0b5CAC906d97DE` | [vanascan.io](https://vanascan.io) | | Viction | 88 | 88 | `0x17E216fBb22dF4ef8A6640ae9Cb147C92710ac84` | [www.vicscan.xyz](https://www.vicscan.xyz) | | World Chain | 480 | 480 | `0x4848d54987ffc732aD313827cdC25DF2eedD79d8` | [worldscan.org](https://worldscan.org) | | Xai | 660279 | 660279 | `0x2c61Cda929e4e2174cb10cd8e2724A9ceaD62E67` | [explorer.xai-chain.net](https://explorer.xai-chain.net) | | XLayer | 196 | 196 | `0x4848d54987ffc732aD313827cdC25DF2eedD79d8` | [www.oklink.com](https://www.oklink.com/xlayer) | | XRPL EVM | 1440000 | 1440000 | `0xc8826EA18D9884A1A335b2Cd7d5f44B159084301` | [explorer.xrplevm.org](https://explorer.xrplevm.org) | | 0G | 16661 | 16661 | `0xc8826EA18D9884A1A335b2Cd7d5f44B159084301` | [chainscan.0g.ai](https://chainscan.0g.ai) | | ZetaChain | 7000 | 7000 | `0x12582c7B0f43c6A667CBaA7fA8b112F7fb1E69F0` | [explorer.zetachain.com](https://explorer.zetachain.com) | | Zircuit | 48900 | 48900 | `0xA34ceDf9068C5deE726C67A4e1DCfCc2D6E2A7fD` | [explorer.zircuit.com](https://explorer.zircuit.com) | | zkSync | 324 | 324 | `0xD55078c54b0cEAa87Ba5c3fAeAC89861c69F636d` | [explorer.zksync.io](https://explorer.zksync.io) | | Zora | 7777777 | 7777777 | `0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1` | [explorer.zora.energy](https://explorer.zora.energy) | ## Testnet | Chain | Domain ID | Chain ID | Address | Explorer | | ----------------------- | --------- | ------------------------------------------------ | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | Arbitrum Sepolia | 421614 | 421614 | `0x6c13643B3927C57DB92c790E4E3E7Ee81e13f78C` | [sepolia.arbiscan.io](https://sepolia.arbiscan.io) | | Base Sepolia | 84532 | 84532 | `0x783c4a0bB6663359281aD4a637D5af68F83ae213` | [sepolia.basescan.org](https://sepolia.basescan.org) | | BSC Testnet | 97 | 97 | `0xfbcD1c00a3d809f36cC1A15918694B17B32c0b6c` | [testnet.bscscan.com](https://testnet.bscscan.com) | | Celo Sepolia | 11142220 | 11142220 | `0xdB1a04C9e08cd96c170bFD8C2f1D0F7fAE8aB0f9` | [celo-sepolia.blockscout.com](https://celo-sepolia.blockscout.com) | | Coti Testnet | 7082400 | 7082400 | `0xfc0da0E35Bba1F49318B2207ecaE86eb088dd3Bb` | [testnet.cotiscan.io](https://testnet.cotiscan.io) | | Fuji | 43113 | 43113 | `0x44a7e1d76fD8AfA244AdE7278336E3D5C658D398` | [testnet.snowtrace.io](https://testnet.snowtrace.io) | | Hyperliquid EVM Testnet | 998 | 998 | `0xB057Fb841027a8554521DcCdeC3c3474CaC99AB5` | [explorer.hyperlend.finance](https://explorer.hyperlend.finance) | | Incentiv Testnet v2 | 28802 | 28802 | `0x48c94311789194215Fe19002C2D33681A76d63dF` | [explorer-testnet.incentiv.io](https://explorer-testnet.incentiv.io) | | Mode Testnet | 919 | 919 | `0xF8E6c1222049AAb68E410E43242449994Cb64996` | [testnet.modescan.io](https://testnet.modescan.io) | | Optimism Sepolia | 11155420 | 11155420 | `0x783c4a0bB6663359281aD4a637D5af68F83ae213` | [sepolia-optimistic.etherscan.io](https://sepolia-optimistic.etherscan.io) | | Paradex Sepolia | 12263410 | 0x505249564154455f534e5f504f54435f5345504f4c4941 | `0x0581bd2065f73576ba98009371de66c8c728977cf8de3b9e40b6ef1a1364132a` | [voyager.testnet.paradex.trade](https://voyager.testnet.paradex.trade) | | Polygon Amoy | 80002 | 80002 | `0x04438ef7622f5412f82915F59caD4f704C61eA48` | [amoy.polygonscan.com](https://amoy.polygonscan.com) | | Sepolia | 11155111 | 11155111 | `0xeDc1A3EDf87187085A3ABb7A9a65E1e7aE370C07` | [sepolia.etherscan.io](https://sepolia.etherscan.io) | | Somnia Testnet | 50312 | 50312 | `0x6cB503d97D1c900316583C8D55997A1f17b1ABd1` | [shannon-explorer.somnia.network](https://shannon-explorer.somnia.network) | | Sonic Testnet | 64165 | 64165 | `0x01812D60958798695391dacF092BAc4a715B1718` | [testnet.soniclabs.com](https://testnet.soniclabs.com) | | Starknet Sepolia | 23448591 | 0x534e5f5345504f4c4941 | `0x01c1d7a109c1d67443ec222f65255ce9f5a783a4ad9da2052db5848910a4f18f` | [sepolia.voyager.online](https://sepolia.voyager.online) | | SUAVE Toliman Testnet | 33626250 | 33626250 | `0x7483faD0Bc297667664A43A064bA7c9911659f57` | [explorer.toliman.suave.flashbots.net](https://explorer.toliman.suave.flashbots.net) | | Tangle Testnet | 3799 | 3799 | `0xE73cdFFcE97AD56723dbA6145a3cC0Dd3aeF112f` | [testnet-explorer.tangle.tools](https://testnet-explorer.tangle.tools) | | Tron Testnet | 346621343 | 2494104990 | `0x1355BfC3C1563972b6aec05F28bDd82dbF9D09B3` | [shasta.tronscan.org](https://shasta.tronscan.org/#) | # ValidatorAnnounce Source: https://docs.hyperlane.xyz/docs/reference/addresses/deployments/validatorAnnounce ValidatorAnnounce deployments across Mainnet and Testnet ## Mainnet | Chain | Domain ID | Chain ID | Address | Explorer | | --------------------- | ---------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | Abstract | 2741 | 2741 | `0x2235662a9a8ED39AE489aafb2feE13Db26f72044` | [abscan.org](https://abscan.org) | | ADI Chain | 36900 | 36900 | `0x794Fe7970EE45945b0ad2667f99A5bBc9ddfB5d7` | [explorer.adichain](https://explorer.adichain) | | Aleo | 1634493807 | 0 | `hyp_validator_announce.aleo/aleo1egcx57dccp3llddqtnuawt63u2xns24v704masl9dne483gymcrq3wpn6q` | [explorer.provable.com](https://explorer.provable.com) | | Ancient8 | 888888888 | 888888888 | `0x931dFCc8c1141D6F532FD023bd87DAe0080c835d` | [scan.ancient8.gg](https://scan.ancient8.gg) | | ApeChain | 33139 | 33139 | `0xcDA455DfD9C938451BfaFC6FF0D497c8C0469C96` | [apescan.io](https://apescan.io) | | AppChain | 466 | 466 | `0x1196055C61af3e3DA6f8458B07b255a72b64Bcf7` | [explorer.appchain.xyz](https://explorer.appchain.xyz) | | Arbitrum | 42161 | 42161 | `0x1df063280C4166AF9a725e3828b4dAC6c7113B08` | [arbiscan.io](https://arbiscan.io) | | Arcadia | 4278608 | 4278608 | `0xEa2Bcee14eA30bbBe3018E5E7829F963230F71C3` | [explorer.arcadia.khalani.network](https://explorer.arcadia.khalani.network) | | Artela | 11820 | 11820 | `0xb89c6ED617f5F46175E41551350725A09110bbCE` | [artscan.artela.network](https://artscan.artela.network) | | Astar | 592 | 592 | `0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86` | [astar.blockscout.com](https://astar.blockscout.com) | | Avalanche | 43114 | 43114 | `0x9Cad0eC82328CEE2386Ec14a12E81d070a27712f` | [snowtrace.io](https://snowtrace.io) | | Base | 8453 | 8453 | `0x182E8d7c5F1B06201b102123FC7dF0EaeB445a7B` | [basescan.org](https://basescan.org) | | Berachain | 80094 | 80094 | `0xa377b8269e0A47cdd2fD5AAeAe860b45623c6d82` | [beratrail.io](https://beratrail.io) | | Bitlayer | 200901 | 200901 | `0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86` | [www.btrscan.com](https://www.btrscan.com) | | Blast | 81457 | 81457 | `0xFC62DeF1f08793aBf0E67f69257c6be258194F72` | [blastscan.io](https://blastscan.io) | | BOB | 60808 | 60808 | `0x7E27456a839BFF31CA642c060a2b68414Cb6e503` | [explorer.gobob.xyz](https://explorer.gobob.xyz) | | Boba Mainnet | 288 | 288 | `0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e` | [bobascan.com](https://bobascan.com) | | Botanix | 3637 | 3637 | `0x466b330C2e360c0214A9Da2428415298f720883E` | [botanixscan.io](https://botanixscan.io) | | Binance Smart Chain | 56 | 56 | `0x7024078130D9c2100fEA474DAD009C2d1703aCcd` | [bscscan.com](https://bscscan.com) | | CarrChain | 7667 | 7667 | `0x5B7a808CaA2C3F1378B07cDd46eB8ccA52F67e3B` | [carrscan.io](https://carrscan.io) | | Celestia | 1128614981 | celestia | `0x68797065726c616e650000000000000000000000000000000000000000000000` | [celenium.io](https://celenium.io) | | Celo | 42220 | 42220 | `0xCeF677b65FDaA6804d4403083bb12B8dB3991FE1` | [celoscan.io](https://celoscan.io) | | Chiliz | 1000088888 | 88888 | `0x16625230dD6cFe1B2bec3eCaEc7d43bA3A902CD6` | [chiliscan.com](https://chiliscan.com) | | Citrea | 4114 | 4114 | `0x1D9c7400E3392e1854CFeBD7C409EB22824d9023` | [explorer.mainnet.citrea.xyz](https://explorer.mainnet.citrea.xyz) | | Core | 1116 | 1116 | `0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86` | [scan.coredao.org](https://scan.coredao.org) | | Coti | 2632500 | 2632500 | `0xD233433AeC23F8382DAd87D808F60557Ea35399f` | [mainnet.cotiscan.io](https://mainnet.cotiscan.io) | | Cyber | 7560 | 7560 | `0x062200d92df6bb7ba89ce4d6800110450f94784e` | [cyberscan.co](https://cyberscan.co) | | Eclipse | 1408864445 | 1408864445 | `Hqnn593pqDZWLy6bKZ4NbY767wFhUNBShDrLktuQa3Q2` | [eclipsescan.xyz](https://eclipsescan.xyz) | | Eden | 714 | 714 | `0x7082e975Fde8D85B0C56B4512b437efFb46F0a09` | N/A | | Electroneum | 52014 | 52014 | `0x75719C858e0c73e07128F95B2C466d142490e933` | [blockexplorer.electroneum.com](https://blockexplorer.electroneum.com) | | Endurance | 648 | 648 | `0x3c7653dD0Ec21A833f99293CDC17495CE249532c` | [explorer-endurance.fusionist.io](https://explorer-endurance.fusionist.io) | | ENI | 173 | 173 | `0x23cc88CF424d48fDB05b4f0A8Ff6099aa4D56D8e` | [scan.eniac.network](https://scan.eniac.network) | | Ethereum | 1 | 1 | `0xCe74905e51497b4adD3639366708b821dcBcff96` | [etherscan.io](https://etherscan.io) | | Everclear | 25327 | 25327 | `0xC88bAD76EC7acD9fd3b9Bb264f7f5C18097c5710` | [scan.everclear.org](https://scan.everclear.org) | | Flare | 14 | 14 | `0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86` | [flare-explorer.flare.network](https://flare-explorer.flare.network) | | EVM on Flow | 1000000747 | 747 | `0x5C6699c133A583d389Ba7e0bDD4993e2e63fA804` | [evm.flowscan.io](https://evm.flowscan.io) | | Fluence | 9999999 | 9999999 | `0x7B8AA8f23Ab6B0757eC6FC71894211376D9335b0` | [blockscout.mainnet.fluence.dev](https://blockscout.mainnet.fluence.dev) | | Fluent | 25363 | 25363 | `0xc8826EA18D9884A1A335b2Cd7d5f44B159084301` | [fluentscan.xyz](https://fluentscan.xyz) | | Fraxtal | 252 | 252 | `0x1956848601549de5aa0c887892061fA5aB4f6fC4` | [fraxscan.com](https://fraxscan.com) | | Fuse | 122 | 122 | `0x60bB6D060393D3C206719A7bD61844cC82891cfB` | [explorer.fuse.io](https://explorer.fuse.io) | | Galactica | 613419 | 613419 | `0x5b1A451c85e5bcCd79A56eb638aBd9998fA215f9` | [explorer.galactica.com](https://explorer.galactica.com) | | Gnosis | 100 | 100 | `0x87ED6926abc9E38b9C7C19f835B41943b622663c` | [gnosisscan.io](https://gnosisscan.io) | | Gravity Alpha Mainnet | 1625 | 1625 | `0x61374178e45F65fF9D6252d017Cd580FC60B7654` | [explorer.gravity.xyz](https://explorer.gravity.xyz) | | Hashkey | 177 | 177 | `0x6c5012B7eDfE317Be53D13Fc730a460f4810e234` | [explorer.hsk.xyz](https://explorer.hsk.xyz) | | Hemi Network | 43111 | 43111 | `0xb89c6ED617f5F46175E41551350725A09110bbCE` | [explorer.hemi.xyz](https://explorer.hemi.xyz) | | HyperEVM | 999 | 999 | `0xf4035357EB3e3B48E498FA6e1207892f615A2c2f` | [www.hyperscan.com](https://www.hyperscan.com) | | Igra | 38833 | 38833 | `0x8452363d5c78bf95538614441Dc8B465e03A89ca` | [explorer.igralabs.com](https://explorer.igralabs.com) | | Immutable zkEVM | 1000013371 | 13371 | `0x8c794a781327b819416E7b67908f1D22397f1E67` | [explorer.immutable.com](https://explorer.immutable.com) | | Incentiv | 24101 | 24101 | `0x5B7a808CaA2C3F1378B07cDd46eB8ccA52F67e3B` | [explorer.incentiv.io](http://explorer.incentiv.io) | | Ink | 57073 | 57073 | `0x426a3CE72C1586b1867F9339550371E86DB3e396` | [explorer.inkonchain.com](https://explorer.inkonchain.com) | | Kaia | 8217 | 8217 | `0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53` | [kaiascope.com](https://kaiascope.com) | | Katana | 747474 | 747474 | `0x466b330C2e360c0214A9Da2428415298f720883E` | [explorer.katanarpc.com](https://explorer.katanarpc.com) | | Kiichain | 1783 | 1783 | `0xc8826EA18D9884A1A335b2Cd7d5f44B159084301` | [mainnet.explorer.kiichain.io](https://mainnet.explorer.kiichain.io) | | Krown | 1983 | 1983 | `0xA697222b77cDe62A8C47E627d5A1c49A87018236` | N/A | | LazAI | 52924 | 52924 | `0xA28344Ac1Fc47C1dc212E178540dD0F3e7a781A6` | [explorer.mainnet.lazai.network](https://explorer.mainnet.lazai.network) | | Linea | 59144 | 59144 | `0x62B7592C1B6D1E43f4630B8e37f4377097840C05` | [lineascan.build](https://lineascan.build) | | Lisk | 1135 | 1135 | `0x062200d92dF6bB7bA89Ce4D6800110450f94784e` | [blockscout.lisk.com](https://blockscout.lisk.com) | | Lit Chain | 175200 | 175200 | `0xBCD18636e5876DFd7AAb5F2B2a5Eb5ca168BA1d8` | [lit-chain-explorer.litprotocol.com](https://lit-chain-explorer.litprotocol.com) | | LUKSO | 42 | 42 | `0x3C2b535a49c6827DF0b8e94467e6922c99E3c092` | [explorer.execution.mainnet.lukso.network](https://explorer.execution.mainnet.lukso.network) | | Lumia Prism | 1000073017 | 994873017 | `0x803d2A87429E20d4B52266bF97Ca1c7e4f4F5Dfa` | [explorer.lumia.org](https://explorer.lumia.org) | | Manta Pacific | 169 | 169 | `0x2fa5F5C96419C222cDbCeC797D696e6cE428A7A9` | [pacific-explorer.manta.network](https://pacific-explorer.manta.network) | | Mantle | 5000 | 5000 | `0x1956848601549de5aa0c887892061fA5aB4f6fC4` | [explorer.mantle.xyz](https://explorer.mantle.xyz) | | MANTRA | 5888 | 5888 | `0xBCD18636e5876DFd7AAb5F2B2a5Eb5ca168BA1d8` | [blockscout.mantrascan.io](https://blockscout.mantrascan.io) | | Matchain | 698 | 698 | `0xC5f2c60073DCAA9D157C45d5B017D639dF9C5CeB` | [matchscan.io](https://matchscan.io) | | MegaETH | 4326 | 4326 | `0x7B8AA8f23Ab6B0757eC6FC71894211376D9335b0` | [megaeth.blockscout.com](https://megaeth.blockscout.com) | | Metal L2 | 1000001750 | 1750 | `0xc6835e52C1b976F1ebC71Bc8919738E02849FdA9` | [explorer.metall2.com](https://explorer.metall2.com) | | Metis Andromeda | 1088 | 1088 | `0x062200d92dF6bB7bA89Ce4D6800110450f94784e` | [andromeda-explorer.metis.io](https://andromeda-explorer.metis.io) | | MilkyWay | 1835625579 | milkyway | `0x68797065726c616e650000000000000000000000000000000000000000000000` | N/A | | Miraclechain | 92278 | 92278 | `0x5b1A451c85e5bcCd79A56eb638aBd9998fA215f9` | [explorer.miracleplay.io](https://explorer.miracleplay.io) | | Mitosis | 124816 | 124816 | `0xdf4aA3905e0391C7763e33CB6A08fFa97221D49B` | [mitoscan.io](https://mitoscan.io) | | Moca Chain | 2288 | 2288 | `0xc8826EA18D9884A1A335b2Cd7d5f44B159084301` | [moca-mainnet.cloud.blockscout.com](https://moca-mainnet.cloud.blockscout.com) | | Mode | 34443 | 34443 | `0x48083C69f5a42c6B69ABbAd48AE195BD36770ee2` | [explorer.mode.network](https://explorer.mode.network) | | Molten | 360 | 360 | `0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86` | [molten.calderaexplorer.xyz](https://molten.calderaexplorer.xyz) | | Monad | 143 | 143 | `0x89Ebf977E83087959aD78e5372F4AF15DcdC8143` | [mainnet-beta.monvision.io](https://mainnet-beta.monvision.io) | | Morph | 2818 | 2818 | `0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53` | [explorer.morphl2.io](https://explorer.morphl2.io) | | Nibiru | 6900 | 6900 | `0x4A91738390a3D55CB27c2863e8950c9cD1b89d0e` | [nibiscan.io](https://nibiscan.io) | | Ontology | 58 | 58 | `0x4e128A1b613A9C9Ecf650FeE461c353612559fcf` | [explorer.ont.io](https://explorer.ont.io) | | Oort | 970 | 970 | `0x6f77d5Ef273C38CC19d1d02352785F52565A1A6c` | [mainnet-scan.oortech.com](https://mainnet-scan.oortech.com) | | opBNB | 204 | 204 | `0x9fE454AA2B01fc7A2a777AE561bc58Ce560CD5a9` | [opbnb.bscscan.com](https://opbnb.bscscan.com) | | Optimism | 10 | 10 | `0x30f5b08e01808643221528BB2f7953bf2830Ef38` | [optimistic.etherscan.io](https://optimistic.etherscan.io) | | Orderly L2 | 291 | 291 | `0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53` | [explorer.orderly.network](https://explorer.orderly.network) | | Paradex | 514051890 | 0x505249564154455f534e5f50415241434c4541525f4d41494e4e4554 | `0x04cc184bc56545c39a71717fc9b62bef3374268d33450095f5b6904788087b68` | [voyager.prod.paradex.trade](https://voyager.prod.paradex.trade) | | Peaq | 3338 | 3338 | `0x7B8AA8f23Ab6B0757eC6FC71894211376D9335b0` | [peaq.subscan.io](https://peaq.subscan.io) | | Plasma | 9745 | 9745 | `0x75719C858e0c73e07128F95B2C466d142490e933` | [plasmascan.to](https://plasmascan.to) | | Plume | 98866 | 98866 | `0xbE58F200ffca4e1cE4D2F4541E94Ae18370fC405` | [explorer.plume.org](https://explorer.plume.org) | | Polygon | 137 | 137 | `0x454E1a1E1CA8B51506090f1b5399083658eA4Fc5` | [polygonscan.com](https://polygonscan.com) | | Polynomial | 1000008008 | 8008 | `0xA166219dF110BDA97b91e65D4BB4Aae4159978b9` | [polynomialscan.io](https://polynomialscan.io) | | Prom | 227 | 227 | `0x5ae1ECA065aC8ee92Ce98E584fc3CE43070020e7` | [prom-blockscout.eu-north-2.gateway.fm](https://prom-blockscout.eu-north-2.gateway.fm) | | PulseChain | 369 | 369 | `0xB08bd33086CF244D3757843DdD771c3263e1C02c` | [scan.pulsechain.box](https://scan.pulsechain.box) | | Radix | 1633970780 | 1 | `component_rdx1cr0hsv0qg58ud3pv3prd4kv2m4dl4vd4ma2yd0et64987qukxp9n94` | [dashboard.radixdlt.com](https://dashboard.radixdlt.com) | | RARI Chain | 1000012617 | 1380012617 | `0x38D361861d321B8B05de200c61B8F18740Daf4D8` | [mainnet.explorer.rarichain.org](https://mainnet.explorer.rarichain.org) | | Reactive Mainnet | 1597 | 1597 | `0x9fE454AA2B01fc7A2a777AE561bc58Ce560CD5a9` | [reactscan.net](https://reactscan.net) | | Redstone | 690 | 690 | `0x12582c7B0f43c6A667CBaA7fA8b112F7fb1E69F0` | [explorer.redstone.xyz](https://explorer.redstone.xyz) | | Ronin | 2020 | 2020 | `0xB2b0A80b2fa3fC9aB1564A4FaF013d4D6084B325` | [app.roninchain.com](https://app.roninchain.com) | | Sei | 1329 | 1329 | `0x5332D1AC0A626D265298c14ff681c0A8D28dB86d` | [seitrace.com](https://seitrace.com) | | Shibarium | 109 | 109 | `0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86` | [shibariumscan.io](https://shibariumscan.io) | | Solana | 1399811149 | 1399811149 | `pRgs5vN4Pj7WvFbxf6QDHizo2njq2uksqEUbaSghVA8` | [solscan.io](https://solscan.io) | | Solaxy | 1936682104 | 1936682104 | `28S9ToSehVxdE7rTGEAA3vAX3AchHJh1MXcq9AeM1rL8` | [explorer.solaxy.io](https://explorer.solaxy.io) | | Somnia | 5031 | 5031 | `0xfa656a97b8FD2D7A94a728c0373cfd820b1f0747` | [explorer.somnia.network](https://explorer.somnia.network) | | Soneium | 1868 | 1868 | `0x84444cE490233CFa76E3F1029bc166aa8c266907` | [soneium.blockscout.com](https://soneium.blockscout.com) | | Sonic | 146 | 146 | `0x84444cE490233CFa76E3F1029bc166aa8c266907` | [sonicscan.org](https://sonicscan.org) | | Sonic SVM | 507150715 | 507150715 | `4LxdrQjqUzueko4MEn3cYCniEtcAZ6AxuHot2Fp3jskH` | [explorer.sonic.game](https://explorer.sonic.game/?cluster=custom\&customUrl=https%3A%2F%2Fapi.mainnet-alpha.sonic.game) | | SOON | 50075007 | 50075007 | `GFqF38mSacfvbJRKkhmjJvSkzTEKemSNVoWi4Q94ZPvz` | [explorer.soo.network](https://explorer.soo.network) | | Sophon | 50104 | 50104 | `0x54E88f2ab58E0Ab4B7Ce081FB20D85b16af041d2` | [explorer.sophon.xyz](https://explorer.sophon.xyz) | | Stable | 988 | 988 | `0xF6CC9B10c607afB777380bF71F272E4D7037C3A9` | [stablescan.xyz](https://stablescan.xyz) | | Starknet | 358974494 | 0x534e5f4d41494e | `0x03bcb0295d31170c5d51f6edce35d5802ce62527e0f15bd8b9f1b979db32e53a` | [voyager.online](https://voyager.online) | | Subtensor | 964 | 964 | `0x8D8979F2C29bA49FAb259A826D0271c43F70288c` | [evm.taostats.io](https://evm.taostats.io) | | Superseed | 5330 | 5330 | `0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e` | [explorer.superseed.xyz](https://explorer.superseed.xyz) | | Swell | 1923 | 1923 | `0x4D50044335dc1d4D26c343AdeDf6E47808475Deb` | [explorer.swellnetwork.io](https://explorer.swellnetwork.io) | | TAC | 239 | 239 | `0x96D51cc3f7500d501bAeB1A2a62BB96fa03532F8` | [explorer.tac.build](https://explorer.tac.build) | | Taiko | 167000 | 167000 | `0x01aE937A7B05d187bBCBE80F44F41879D3D335a4` | [taikoscan.io](https://taikoscan.io) | | Tempo | 4217 | 4217 | `0xA97DD6fBe11188322f9FDB013a88c86Eb8E2C535` | [explore.tempo.xyz](https://explore.tempo.xyz) | | Torus | 21000 | 21000 | `0x65dCf8F6b3f6a0ECEdf3d0bdCB036AEa47A1d615` | [blockscout.torus.network](https://blockscout.torus.network) | | Tron | 728126428 | 728126428 | `0x12eAD5d1628f8E405f9B57F8c86E2bb860E4380A` | [tronscan.org](https://tronscan.org/#) | | Unichain | 130 | 130 | `0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e` | [uniscan.xyz](https://uniscan.xyz) | | Vana | 1480 | 1480 | `0xD743801ABB6c7664B623D8534C0f5AF8cD2F1C5e` | [vanascan.io](https://vanascan.io) | | Viction | 88 | 88 | `0x2fa5F5C96419C222cDbCeC797D696e6cE428A7A9` | [www.vicscan.xyz](https://www.vicscan.xyz) | | World Chain | 480 | 480 | `0x047ba6c9949baB22d13C347B40819b7A20C4C53a` | [worldscan.org](https://worldscan.org) | | Xai | 660279 | 660279 | `0x062200d92dF6bB7bA89Ce4D6800110450f94784e` | [explorer.xai-chain.net](https://explorer.xai-chain.net) | | XLayer | 196 | 196 | `0x047ba6c9949baB22d13C347B40819b7A20C4C53a` | [www.oklink.com](https://www.oklink.com/xlayer) | | XRPL EVM | 1440000 | 1440000 | `0x5b1A451c85e5bcCd79A56eb638aBd9998fA215f9` | [explorer.xrplevm.org](https://explorer.xrplevm.org) | | 0G | 16661 | 16661 | `0x5b1A451c85e5bcCd79A56eb638aBd9998fA215f9` | [chainscan.0g.ai](https://chainscan.0g.ai) | | ZetaChain | 7000 | 7000 | `0x48083C69f5a42c6B69ABbAd48AE195BD36770ee2` | [explorer.zetachain.com](https://explorer.zetachain.com) | | Zircuit | 48900 | 48900 | `0x5366362c41e34869BDa231061603E4356D66079D` | [explorer.zircuit.com](https://explorer.zircuit.com) | | zkSync | 324 | 324 | `0x576aF402c97bFE452Dcc203B6c3f6F4EBC92A0f5` | [explorer.zksync.io](https://explorer.zksync.io) | | Zora | 7777777 | 7777777 | `0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed` | [explorer.zora.energy](https://explorer.zora.energy) | ## Testnet | Chain | Domain ID | Chain ID | Address | Explorer | | ----------------------- | ---------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | Aleo Testnet | 1617853565 | 1 | `test_hyp_validator_announce.aleo/aleo1exucqw8zpx05swkl8dt7us3xl9z88fypla7nvwy4vt2rvfvazy8s0phz2l` | [testnet.explorer.provable.com](https://testnet.explorer.provable.com) | | Arbitrum Sepolia | 421614 | 421614 | `0x1b33611fCc073aB0737011d5512EF673Bff74962` | [sepolia.arbiscan.io](https://sepolia.arbiscan.io) | | Base Sepolia | 84532 | 84532 | `0x20c44b1E3BeaDA1e9826CFd48BeEDABeE9871cE9` | [sepolia.basescan.org](https://sepolia.basescan.org) | | BSC Testnet | 97 | 97 | `0xf09701B0a93210113D175461b6135a96773B5465` | [testnet.bscscan.com](https://testnet.bscscan.com) | | Celestia Testnet | 1297040200 | mocha-4 | `0x68797065726c616e650000000000000000000000000000000000000000000000` | N/A | | Celo Sepolia | 11142220 | 11142220 | `0x555B5d0AD2C1f5010e39dA82342A2E85402E4637` | [celo-sepolia.blockscout.com](https://celo-sepolia.blockscout.com) | | Coti Testnet | 7082400 | 7082400 | `0x6202f54B22b72526dEC5364F6b7bE2bd0abEd8A6` | [testnet.cotiscan.io](https://testnet.cotiscan.io) | | Fuji | 43113 | 43113 | `0x4f7179A691F8a684f56cF7Fed65171877d30739a` | [testnet.snowtrace.io](https://testnet.snowtrace.io) | | Hyperliquid EVM Testnet | 998 | 998 | `0x086E902d2f99BcCEAa28B31747eC6Dc5fd43B1bE` | [explorer.hyperlend.finance](https://explorer.hyperlend.finance) | | Incentiv Testnet v2 | 28802 | 28802 | `0xE3D93F9296FA3dF262E1a54f0de02F71E845af6b` | [explorer-testnet.incentiv.io](https://explorer-testnet.incentiv.io) | | Mode Testnet | 919 | 919 | `0x6AD4DEBA8A147d000C09de6465267a9047d1c217` | [testnet.modescan.io](https://testnet.modescan.io) | | Optimism Sepolia | 11155420 | 11155420 | `0x20c44b1E3BeaDA1e9826CFd48BeEDABeE9871cE9` | [sepolia-optimistic.etherscan.io](https://sepolia-optimistic.etherscan.io) | | Paradex Sepolia | 12263410 | 0x505249564154455f534e5f504f54435f5345504f4c4941 | `0x03606e11cfdec0745e8c49cf3179df9b4c37528baf0131ae1ec079055a7cab0b` | [voyager.testnet.paradex.trade](https://voyager.testnet.paradex.trade) | | Polygon Amoy | 80002 | 80002 | `0x11918DC33E067C5DA83EEF58E50F856398b8Df4C` | [amoy.polygonscan.com](https://amoy.polygonscan.com) | | Radix Stokenet | 1280787160 | 2 | `component_tdx_2_1cq3wn6y87j7nw8hnqk545246mrg4q4amsmnm03hk4gxky2tsx0jy93` | [stokenet-dashboard.radixdlt.com](https://stokenet-dashboard.radixdlt.com) | | Sepolia | 11155111 | 11155111 | `0xE6105C59480a1B7DD3E4f28153aFdbE12F4CfCD9` | [sepolia.etherscan.io](https://sepolia.etherscan.io) | | Solana Testnet | 1399811150 | 1399811150 | `8qNYSi9EP1xSnRjtMpyof88A26GBbdcrsa61uSaHiwx3` | [explorer.solana.com](https://explorer.solana.com?cluster=testnet) | | Somnia Testnet | 50312 | 50312 | `0x0b9A4A46f50f91f353B8Aa0F3Ca80E35E253bDd8` | [shannon-explorer.somnia.network](https://shannon-explorer.somnia.network) | | Sonic SVM Testnet | 15153042 | 15153042 | `84NjUotjZcNBVGBhvwERPNS6zaAfhkJkG33aSiNxPma2` | [explorer.sonic.game](https://explorer.sonic.game/?cluster=testnet.v1) | | Sonic Testnet | 64165 | 64165 | `0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f` | [testnet.soniclabs.com](https://testnet.soniclabs.com) | | Starknet Sepolia | 23448591 | 0x534e5f5345504f4c4941 | `0x06587686d7270349bf233976265fa6bd53d73c9f13b5fc916f541ad9b297dce8` | [sepolia.voyager.online](https://sepolia.voyager.online) | | SUAVE Toliman Testnet | 33626250 | 33626250 | `0xEa7e618Bee8927fBb2fA20Bc41eE8DEA51838aAD` | [explorer.toliman.suave.flashbots.net](https://explorer.toliman.suave.flashbots.net) | | Tangle Testnet | 3799 | 3799 | `0x6D35A0f235aa0fBf0163C8b5171eF6E55843849b` | [testnet-explorer.tangle.tools](https://testnet-explorer.tangle.tools) | | Tron Testnet | 346621343 | 2494104990 | `0x6b6CeC744dd24E21A29bed6d3Eebc391b478D78b` | [shasta.tronscan.org](https://shasta.tronscan.org/#) | # Latencies Source: https://docs.hyperlane.xyz/docs/reference/addresses/validators/latencies Validators must wait a certain number of blocks to be mined before they are considered valid and [reorg-safe](https://www.alchemy.com/overviews/what-is-a-reorg). Without this, validators could be slashed since they may have signed a checkpoint that is no longer valid. Refer to the following sections for block finality configuration used by the Hyperlane validators. | Chain | Domain | Reorg Period (blocks) | Estimated Block Time (seconds) | | --------------------- | ---------- | --------------------- | ------------------------------ | | Abstract | 2741 | 0 | 1 | | ADI Chain | 36900 | 0 | 1 | | Aleo | 1634493807 | 0 | 3 | | Ancient8 | 888888888 | 5 | 2 | | ApeChain | 33139 | 5 | 0.2 | | AppChain | 466 | 0 | 2 | | Arbitrum | 42161 | 5 | 0.25 | | Arcadia | 4278608 | 5 | 2 | | Artela | 11820 | 5 | 2 | | Astar | 592 | finalized | 13 | | Avalanche | 43114 | 3 | 2 | | Base | 8453 | 10 | 2 | | Berachain | 80094 | 5 | 2 | | Bitlayer | 200901 | 20 | 3 | | Blast | 81457 | 5 | 2 | | BOB | 60808 | 5 | 2 | | Boba Mainnet | 288 | 5 | 2 | | Botanix | 3637 | 5 | 6 | | Binance Smart Chain | 56 | finalized | 3 | | CarrChain | 7667 | 0 | 1 | | Celestia | 1128614981 | 1 | 6 | | Celo | 42220 | 5 | 1 | | Chiliz | 1000088888 | 9 | 3 | | Citrea | 4114 | 5 | 2 | | Core | 1116 | 21 | 3 | | Coti | 2632500 | 5 | 5 | | Cyber | 7560 | 5 | 2 | | Eclipse | 1408864445 | 0 | 0.4 | | Eden | 714 | 5 | 1 | | Electroneum | 52014 | 10 | 5 | | Endurance | 648 | 15 | 12 | | ENI | 173 | 5 | 1 | | Ethereum | 1 | 15 | 13 | | Everclear | 25327 | 2 | 2 | | Flare | 14 | 3 | 2 | | EVM on Flow | 1000000747 | 25 | 1 | | Fluence | 9999999 | 5 | 1 | | Fluent | 25363 | 5 | 1 | | Fraxtal | 252 | 5 | 2 | | Fuse | 122 | 19 | 5 | | Galactica | 613419 | 0 | 1 | | Gnosis | 100 | 5 | 5 | | Gravity Alpha Mainnet | 1625 | 5 | 1 | | Hashkey | 177 | 5 | 2 | | Hemi Network | 43111 | 5 | 12 | | HyperEVM | 999 | 5 | 2 | | Igra | 38833 | 5 | 1 | | Immutable zkEVM | 1000013371 | 20 | 2 | | Incentiv | 24101 | 10 | 5 | | Ink | 57073 | 5 | 1 | | Kaia | 8217 | 5 | 1 | | Katana | 747474 | 5 | 1 | | Kiichain | 1783 | 5 | 2 | | Krown | 1983 | 5 | 12 | | LazAI | 52924 | 5 | 1 | | Linea | 59144 | 5 | 3 | | Lisk | 1135 | 5 | 2 | | Lit Chain | 175200 | 0 | 1 | | LUKSO | 42 | 15 | 12 | | Lumia Prism | 1000073017 | 5 | 4 | | Manta Pacific | 169 | 5 | 3 | | Mantle | 5000 | 2 | 2 | | MANTRA | 5888 | 5 | 3 | | Matchain | 698 | 5 | 1 | | MegaETH | 4326 | 5 | 1 | | Metal L2 | 1000001750 | 5 | 2 | | Metis Andromeda | 1088 | 5 | 5 | | MilkyWay | 1835625579 | 1 | 6 | | Miraclechain | 92278 | 0 | 3 | | Mitosis | 124816 | 5 | 2 | | Moca Chain | 2288 | 5 | 1 | | Mode | 34443 | 5 | 2 | | Molten | 360 | 0 | 30 | | Monad | 143 | 5 | 1 | | Morph | 2818 | 5 | 4 | | Nibiru | 6900 | 5 | 2 | | Ontology | 58 | 5 | 1 | | Oort | 970 | 0 | 2 | | opBNB | 204 | 5 | 1 | | Optimism | 10 | 10 | 2 | | Orderly L2 | 291 | 5 | 2 | | Paradex | 514051890 | 1 | 30 | | Peaq | 3338 | finalized | 6 | | Plasma | 9745 | 10 | 1 | | Plume | 98866 | 0 | 2 | | Polygon | 137 | finalized | 2 | | Polynomial | 1000008008 | 5 | 2 | | Prom | 227 | 5 | 6 | | PulseChain | 369 | 10 | 10 | | Radix | 1633970780 | 0 | 5 | | RARI Chain | 1000012617 | 0 | 30 | | Reactive Mainnet | 1597 | 5 | 7 | | Redstone | 690 | 5 | 2 | | Ronin | 2020 | 5 | 3 | | Sei | 1329 | 1 | 1 | | Shibarium | 109 | finalized | 5 | | Solana | 1399811149 | 0 | 0.4 | | Solaxy | 1936682104 | 0 | 1.2 | | Somnia | 5031 | 10 | 1 | | Soneium | 1868 | 5 | 2 | | Sonic | 146 | 5 | 2 | | Sonic SVM | 507150715 | 0 | 0.4 | | SOON | 50075007 | 0 | 0.05 | | Sophon | 50104 | 0 | 1 | | Stable | 988 | 5 | 1 | | Starknet | 358974494 | 1 | 30 | | Subtensor | 964 | 5 | 12 | | Superseed | 5330 | 5 | 2 | | Swell | 1923 | 5 | 2 | | TAC | 239 | 5 | 1 | | Taiko | 167000 | 5 | 12 | | Tempo | 4217 | 5 | 1 | | Torus | 21000 | finalized | 8 | | Tron | 728126428 | finalized | 3 | | Unichain | 130 | 5 | 1 | | Vana | 1480 | 5 | 6 | | Viction | 88 | 3 | 2 | | World Chain | 480 | 5 | 2 | | Xai | 660279 | 5 | 1 | | XLayer | 196 | 5 | 10 | | XRPL EVM | 1440000 | 5 | 6 | | 0G | 16661 | 10 | 0.4 | | ZetaChain | 7000 | 0 | 6 | | Zircuit | 48900 | 300 | 2 | | zkSync | 324 | 0 | 1 | | Zora | 7777777 | 5 | 2 | | Chain | Domain | Reorg Period (blocks) | Estimated Block Time (seconds) | | ----------------------- | ---------- | --------------------- | ------------------------------ | | Aleo Testnet | 1617853565 | 0 | 3 | | Arbitrum Sepolia | 421614 | 0 | 3 | | Base Sepolia | 84532 | 1 | 2 | | BSC Testnet | 97 | 9 | 3 | | Celestia Testnet | 1297040200 | 1 | 6 | | Celo Sepolia | 11142220 | 1 | 1 | | Coti Testnet | 7082400 | 1 | 5 | | Fuji | 43113 | 3 | 2 | | Hyperliquid EVM Testnet | 998 | 1 | 2 | | Incentiv Testnet v2 | 28802 | 1 | 10 | | Mode Testnet | 919 | 1 | 2 | | Optimism Sepolia | 11155420 | 0 | 2 | | Paradex Sepolia | 12263410 | 1 | 30 | | Polygon Amoy | 80002 | 10 | 2 | | Radix Stokenet | 1280787160 | 0 | 5 | | Sepolia | 11155111 | 2 | 13 | | Solana Testnet | 1399811150 | 0 | 0.4 | | Somnia Testnet | 50312 | 1 | 1 | | Sonic SVM Testnet | 15153042 | 0 | 0.4 | | Sonic Testnet | 64165 | 1 | 1 | | Starknet Sepolia | 23448591 | 1 | 30 | | SUAVE Toliman Testnet | 33626250 | 1 | 4 | | Tangle Testnet | 3799 | 0 | 6 | | Tron Testnet | 346621343 | 20 | 3 | # Mainnet Source: https://docs.hyperlane.xyz/docs/reference/addresses/validators/mainnet-default-ism-validators Default ISM validator configurations for mainnet chains ## Abstract (2741) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x2ef8ece5b51562e65970c7d36007baa43a1de685` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## ADI Chain (36900) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x4b11a6310bc06300b529b0397683ca3376407eca` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Aleo (1634493807) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xb9e79db67d02db0f79726c1aa499cc4d26b084fa` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Ancient8 (888888888) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xbb5842ae0e05215b53df4787a29144efb7e67551` | | Coin98 | `0xa5a56e97fb46f0ac3a3d261e404acb998d9a6969` | | Ancient8 | `0x95c7bf235837cb5a609fe6c95870410b9f68bcff` | ## ApeChain (33139) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x773d7fe6ffb1ba4de814c28044ff9a2d83a48221` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## AppChain (466) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x0531251bbadc1f9f19ccce3ca6b3f79f08eae1be` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Arbitrum (42161) Threshold: 3 of 5 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x4d966438fe9e2b1e7124c87bbb90cb4f0f6c59a1` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Luganodes | `0x57ddf0cd46f31ead8084069ce481507f4305c716` | | Enigma | `0xde6c50c3e49852dd9fe0388166ebc1ba39ad8505` | ## Arcadia (4278608) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xe16ee9618f138cc2dcf9f9a95462099a8bf33a38` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Artela (11820) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x8fcc1ebd4c0b463618db13f83e4565af3e166b00` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Astar (592) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x4d1b2cade01ee3493f44304653d8e352c66ec3e7` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Avalanche (43114) Threshold: 3 of 4 | Operator | Address | | -------------- | -------------------------------------------- | | Abacus Works | `0x3fb8263859843bffb02950c492d492cae169f4cf` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Substance Labs | `0x74de235ace64fa8a3d5e3d5e414360888e655c62` | | Luganodes | `0x4488dbc191c39ae026b4a1fdb2aefe21960226d5` | ## Base (8453) Threshold: 3 of 5 | Operator | Address | | -------------- | -------------------------------------------- | | Abacus Works | `0xb9453d675e0fa3c178a17b4ce1ad5b1a279b3af9` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | | Substance Labs | `0xb8cf45d7bab79c965843206d5f4d83bb866d6e86` | | Luganodes | `0xe957310e17730f29862e896709cce62d24e4b773` | | Enigma | `0x34a14934d7c18a21440b59dfe9bf132ce601457d` | ## Berachain (80094) Threshold: 3 of 5 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x0190915c55d9c7555e6d2cb838f04d18b5e2260e` | | Luganodes | `0xa7341aa60faad0ce728aa9aeb67bb880f55e4392` | | Renzo | `0xae09cb3febc4cad59ef5a56c1df741df4eb1f4b6` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Bitlayer (200901) Threshold: 4 of 6 | Operator | Address | | -------------- | -------------------------------------------- | | Abacus Works | `0x1d9b0f4ea80dbfc71cb7d64d8005eccf7c41e75f` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Substance Labs | `0xaa00a849fc770d742724cbd2862f91d51db7fb62` | | Luganodes | `0x68e869315e51f6bd0ba4aac844cf216fd3dec762` | | Enigma | `0x0677b2daf18b71a2c4220fb17dc81cd3aa7d355b` | ## Blast (81457) Threshold: 3 of 4 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xf20c0b09f597597c8d2430d3d72dfddaf09177d1` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Everclear | `0x1652d8ba766821cf01aeea34306dfc1cab964a32` | | Renzo | `0x54bb0036f777202371429e062fe6aee0d59442f9` | ## BOB (60808) Threshold: 3 of 5 | Operator | Address | | -------------- | -------------------------------------------- | | Abacus Works | `0x20f283be1eb0e81e22f51705dcb79883cfdd34aa` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Substance Labs | `0x53d2738453c222e49c556d937bcef3f80f1c2eec` | | Enigma | `0xb574b2b5822a8cb9ca071e7d43865694f23b0bde` | ## Boba Mainnet (288) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xebeb92c94ca8408e73aa16fd554cb3a7df075c59` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Botanix (3637) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xc944176bc4d4e5c7b0598884478a27a2b1904664` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Binance Smart Chain (56) Threshold: 4 of 6 | Operator | Address | | -------------- | -------------------------------------------- | | Abacus Works | `0x570af9b7b36568c8877eebba6c6727aa9dab7268` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | | Tessellated | `0x0d4c1394a255568ec0ecd11795b28d1bda183ca4` | | Substance Labs | `0x24c1506142b2c859aee36474e59ace09784f71e8` | | Luganodes | `0xc67789546a7a983bf06453425231ab71c119153f` | | Enigma | `0x2d74f6edfd08261c927ddb6cb37af57ab89f0eff` | ## CarrChain (7667) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x7ed0a7582af75dc38ad82e7125b51e3eaa6ec33b` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Celestia (1128614981) Threshold: 4 of 6 | Operator | Address | | --------------- | -------------------------------------------- | | Abacus Works | `0x6dbc192c06907784fb0af0c0c2d8809ea50ba675` | | ZKV | `0x761980c3debdc8ddb69a2713cf5126d4db900f0f` | | P2P.ORG | `0x885a8c1ef7f7eea8955c8f116fc1fbe1113c4a78` | | P-OPS Team | `0xa6c998f0db2b56d7a63faf30a9b677c8b9b6faab` | | Binary Builders | `0x21e93a81920b73c0e98aed8e6b058dae409e4909` | | Cosmostation | `0x7b8606d61bc990165d1e5977037ddcf7f2de74d6` | ## Celo (42220) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x63478422679303c3e4fc611b771fa4a707ef7f4a` | | Imperator | `0xeb0c31e2f2671d724a2589d4a8eca91b97559148` | | Enigma | `0x033e391e9fc57a7b5dd6c91b69be9a1ed11c4986` | | Luganodes | `0x4a2423ef982b186729e779b6e54b0e84efea7285` | | Tessellated | `0x0d4c1394a255568ec0ecd11795b28d1bda183ca4` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Chiliz (1000088888) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x7403e5d58b48b0f5f715d9c78fbc581f01a625cb` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Citrea (4114) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xe175e8db1d04fb525879ce9f088a215d3e3fe3f0` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Core (1116) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xbd6e158a3f5830d99d7d2bce192695bc4a148de2` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Coti (2632500) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x3c89379537f8beafc54e7e8ab4f8a1cf7974b9f0` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Cyber (7560) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x94d7119ceeb802173b6924e6cc8c4cd731089a27` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Eclipse (1408864445) Threshold: 3 of 4 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xebb52d7eaa3ff7a5a6260bfe5111ce52d57401d0` | | Luganodes | `0x3571223e745dc0fcbdefa164c9b826b90c0d2dac` | | Eclipse | `0x4d4629f5bfeabe66edc7a78da26ef5273c266f97` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Electroneum (52014) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x32917f0a38c60ff5b1c4968cb40bc88b14ef0d83` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Endurance (648) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x28c5b322da06f184ebf68693c5d19df4d4af13e5` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Fusionist | `0x7419021c0de2772b763e554480158a82a291c1f2` | ## ENI (173) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xaedc7f95c57baa668eb94341589837b5430a484c` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Ethereum (1) Threshold: 6 of 9 | Operator | Address | | -------------- | -------------------------------------------- | | Abacus Works | `0x03c842db86a6a3e524d4a6615390c1ea8e2b9541` | | DSRV | `0x94438a7de38d4548ae54df5c6010c4ebc5239eae` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | | Staked | `0xb3ac35d3988bca8c2ffd195b1c6bee18536b317b` | | AVS: Luganodes | `0xb683b742b378632a5f73a2a5a45801b3489bba44` | | Imperator | `0x3786083ca59dc806d894104e65a13a70c2b39276` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Substance Labs | `0x29d783efb698f9a2d3045ef4314af1f5674f52c5` | | Enigma | `0x36a669703ad0e11a0382b098574903d2084be22c` | ## Everclear (25327) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xeff20ae3d5ab90abb11e882cfce4b92ea6c74837` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Everclear | `0xD79DFbF56ee2268f061cc613027a44A880f61Ba2` | ## Flare (14) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xb65e52be342dba3ab2c088ceeb4290c744809134` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## EVM on Flow (1000000747) Threshold: 3 of 4 | Operator | Address | | --------------- | -------------------------------------------- | | Abacus Works | `0xe132235c958ca1f3f24d772e5970dd58da4c0f6e` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Flow Foundation | `0x14ADB9e3598c395Fe3290f3ba706C3816Aa78F59` | ## Fluence (9999999) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xabc8dd7594783c90a3c0fb760943f78c37ea6d75` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Fluent (25363) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xea189ae1a9c3e86bcb63597a34a8ea3b0bb83406` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Fraxtal (252) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x4bce180dac6da60d0f3a2bdf036ffe9004f944c1` | | Tessellated | `0x0d4c1394a255568ec0ecd11795b28d1bda183ca4` | | Enigma | `0x1c3C3013B863Cf666499Da1A61949AE396E3Ab82` | | Imperator | `0x573e960e07ad74ea2c5f1e3c31b2055994b12797` | | Luganodes | `0x25b3a88f7cfd3c9f7d7e32b295673a16a6ddbd91` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Fuse (122) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x770c8ec9aac8cec4b2ead583b49acfbc5a1cf8a9` | | Fuse | `0x1FE988A1A20cE4141B2081fF8446DA99e11D61d7` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | ## Galactica (613419) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xfc48af3372d621f476c53d79d42a9e96ce11fd7d` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Gnosis (100) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xd4df66a859585678f2ea8357161d896be19cc1ca` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Gravity Alpha Mainnet (1625) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x23d549bf757a02a6f6068e9363196ecd958c974e` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Hashkey (177) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x55007cab8788cdba22844e7a2499cf43347f487a` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Hemi Network (43111) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x312dc72c17d01f3fd0abd31dd9b569bc473266dd` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## HyperEVM (999) Threshold: 3 of 4 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x01be14a9eceeca36c9c1d46c056ca8c87f77c26f` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Luganodes | `0x04d949c615c9976f89595ddcb9008c92f8ba7278` | ## Igra (38833) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x485f0739639e46d3b06b1b92debe2ade56d8bfb1` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Immutable zkEVM (1000013371) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xbdda85b19a5efbe09e52a32db1a072f043dd66da` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Incentiv (24101) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x72669f47b6f119289f1a42641b02a9656cc8fecd` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Ink (57073) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xb533b8b104522958b984fb258e0684dec0f1a6a5` | | Imperator | `0xd207a6dfd887d91648b672727ff1aef6223cb15a` | | Enigma | `0xa40203b5301659f1e201848d92f5e81f64f206f5` | | Luganodes | `0xff9c1e7b266a36eda0d9177d4236994d94819dc0` | | Tessellated | `0x0d4c1394a255568ec0ecd11795b28d1bda183ca4` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Kaia (8217) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x9de0b3abb221d19719882fa4d61f769fdc2be9a4` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Katana (747474) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xf23003ebdc6c53765d52b1fe7a65046eabb0e73b` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Kiichain (1783) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x5513bc60f0a3a8520edc03828c1bc6111008b54e` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Krown (1983) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x4f78f3fca0660716c4b276893d73f6f4c95fe618` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## LazAI (52924) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x3b00fe3518e739bb978b04d28e1492d8d865d96e` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Linea (59144) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xf2d5409a59e0f5ae7635aff73685624904a77d94` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | | Luganodes | `0x0c760f4bcb508db9144b0579e26f5ff8d94daf4d` | | Enigma | `0x6fbceb2680c8181acf3d1b5f0189e3beaa985338` | ## Lisk (1135) Threshold: 5 of 7 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xc0b282aa5bac43fee83cf71dc3dd1797c1090ea5` | | Tessellated | `0x0d4c1394a255568ec0ecd11795b28d1bda183ca4` | | Enigma | `0x3DA4ee2801Ec6CC5faD73DBb94B10A203ADb3d9e` | | Imperator | `0x4df6e8878992c300e7bfe98cac6bf7d3408b9cbf` | | Luganodes | `0xf0da628f3fb71652d48260bad4691054045832ce` | | Lisk | `0xead4141b6ea149901ce4f4b556953f66d04b1d0c` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Lit Chain (175200) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xde5509be55483aa525e9b5cce6fe64d3e68d068d` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## LUKSO (42) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xa5e953701dcddc5b958b5defb677a829d908df6d` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Blockhunters | `0x101cE77261245140A0871f9407d6233C8230Ec47` | ## Lumia Prism (1000073017) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xb69731640ffd4338a2c9358a935b0274c6463f85` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Manta Pacific (169) Threshold: 4 of 6 | Operator | Address | | ------------- | -------------------------------------------- | | Abacus Works | `0x8e668c97ad76d0e28375275c41ece4972ab8a5bc` | | Cosmostation | `0x521a3e6bf8d24809fde1c1fd3494a859a16f132c` | | P2P | `0x14025fe092f5f8a401dd9819704d9072196d2125` | | Neutron | `0x25b9a0961c51e74fd83295293bc029131bf1e05a` | | Cosmos Spaces | `0xa0eE95e280D46C14921e524B075d0C341e7ad1C8` | | DSRV | `0xcc9a0b6de7fe314bd99223687d784730a75bb957` | ## Mantle (5000) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xf930636c5a1a8bf9302405f72e3af3c96ebe4a52` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | | Luganodes | `0xcd3b3a2007aab3b00418fbac12bea19d04243497` | | Enigma | `0x332b3710e56b843027d4c6da7bca219ece7099b0` | ## MANTRA (5888) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x89b8064e29f125e896f6081ebb77090c46bca9cd` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Matchain (698) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x8a052f7934b0626105f34f980c875ec03aaf82e8` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## MegaETH (4326) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x051ddac8ecf4bae2532b8b7caa626b5567dab528` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Metal L2 (1000001750) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xd9f7f1a05826197a93df51e86cefb41dfbfb896a` | | Imperator | `0x01e3909133d20c05bbc94247769235d30101f748` | | Enigma | `0xaba06266f47e3ef554d218b879bd86114a8dabd4` | | Luganodes | `0x05d91f80377ff5e9c6174025ffaf094c57a4766a` | | Tessellated | `0x0d4c1394a255568ec0ecd11795b28d1bda183ca4` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Metis Andromeda (1088) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xc4a3d25107060e800a43842964546db508092260` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | | Luganodes | `0xad1df94ae078631bfea1623520125e93a6085555` | | Enigma | `0x4272e7b93e127da5bc7cee617febf47bcad20def` | ## MilkyWay (1835625579) Threshold: 3 of 5 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x9985e0c6df8e25b655b46a317af422f5e7756875` | | Nodes.Guru | `0x55010624d5e239281d0850dc7915b78187e8bc0e` | | B-Harvest | `0x9ecf299947b030f9898faf328e5edbf77b13e974` | | DSRV | `0x56fa9ac314ad49836ffb35918043d6b2dec304fb` | | CryptoCrew | `0xb69c0d1aacd305edeca88b482b9dd9657f3a8b5c` | ## Miraclechain (92278) Threshold: 2 of 3 | Operator | Address | | ------------- | -------------------------------------------- | | Abacus Works | `0x8fc655174e99194399822ce2d3a0f71d9fc2de7b` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Miracle Chain | `0x7e592830cc7b26b428eea0297889e195f8438016` | ## Mitosis (124816) Threshold: 3 of 5 | Operator | Address | | -------------- | -------------------------------------------- | | Abacus Works | `0x3b3eb808d90a4e19bb601790a6b6297812d6a61f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | | Enigma | `0x401f25ff73769ed85bdb449a4347a4fd2678acfe` | | Substance Labs | `0x340058f071e8376c2ecff219e1e6620deea8a3c7` | ## Moca Chain (2288) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x31ab8fc95d941defa077f8501c6800e935c3b081` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Mode (34443) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x7eb2e1920a4166c19d6884c1cec3d2cf356fc9b7` | | Tessellated | `0x0d4c1394a255568ec0ecd11795b28d1bda183ca4` | | Enigma | `0x65C140e3a05F33192384AffEF985696Fe3cDDE42` | | Imperator | `0x20eade18ea2af6dfd54d72b3b5366b40fcb47f4b` | | Luganodes | `0x485a4f0009d9afbbf44521016f9b8cdd718e36ea` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Molten (360) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xad5aa33f0d67f6fa258abbe75458ea4908f1dc9f` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Monad (143) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xb4654795b2f1b17513ffde7d85c776e4cade366c` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Morph (2818) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x4884535f393151ec419add872100d352f71af380` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Nibiru (6900) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xba9779d84a8efba1c6bc66326d875c3611a24b24` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Ontology (58) Threshold: 3 of 4 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x2578b0a330c492e1a1682684e27e6a93649befd5` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Ontology | `0x69bbf7d6d8ebf9d60da9607722e8f9c1b0ce7520` | ## Oort (970) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x9b7ff56cd9aa69006f73f1c5b8c63390c706a5d7` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Oort | `0xfa94a494f01d1034b8cea025ca4c2a7e31ca39a1` | ## opBNB (204) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x1bdf52749ef2411ab9c28742dea92f209e96c9c4` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Optimism (10) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x20349eadc6c72e94ce38268b96692b1a5c20de4f` | | Tessellated | `0x0d4c1394a255568ec0ecd11795b28d1bda183ca4` | | Enigma | `0xd8c1cCbfF28413CE6c6ebe11A3e29B0D8384eDbB` | | Imperator | `0x1b9e5f36c4bfdb0e3f0df525ef5c888a4459ef99` | | Luganodes | `0xf9dfaa5c20ae1d84da4b2696b8dc80c919e48b12` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Orderly L2 (291) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xec3dc91f9fa2ad35edf5842aa764d5573b778bb6` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Paradex (514051890) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x0ede747b84071ac24b60c08f8d59ad55d23f8a5c` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Luganodes | `0xc36fe08e2c06ca51f6c3523e54e33505b7aaba37` | ## Peaq (3338) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x7f7fe70b676f65097e2a1e2683d0fc96ea8fea49` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Plasma (9745) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x4ba900a8549fe503bca674114dc98a254637fc2c` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Plume (98866) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x63c9b5ea28710d956a51f0f746ee8df81215663f` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Polygon (137) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x12ecb319c7f4e8ac5eb5226662aeb8528c5cefac` | | DSRV | `0x008f24cbb1cc30ad0f19f2516ca75730e37efb5f` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Polynomial (1000008008) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x23d348c2d365040e56f3fee07e6897122915f513` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Prom (227) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xb0c4042b7c9a95345be8913f4cdbf4043b923d98` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## PulseChain (369) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xa73fc7ebb2149d9c6992ae002cb1849696be895b` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Radix (1633970780) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xa715a7cd97f68caeedb7be64f9e1da10f8ffafb4` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Luganodes | `0xc61209c6b133791c729d0cbe49d6da96c30a515f` | ## RARI Chain (1000012617) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xeac012df7530720dd7d6f9b727e4fe39807d1516` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Reactive Mainnet (1597) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x45768525f6c5ca2e4e7cc50d405370eadee2d624` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Redstone (690) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x1400b9737007f7978d8b4bbafb4a69c83f0641a7` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Ronin (2020) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xa3e11929317e4a871c3d47445ea7bb8c4976fd8a` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | | Luganodes | `0x808a3945d5f9c2f9ccf7a76bde4c4b54c9c7dba4` | | Enigma | `0xe8a821e77bd1ee4658c29e8c3f43c0200b0f06a1` | ## Sei (1329) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x9920d2dbf6c85ffc228fdc2e810bf895732c6aa5` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Shibarium (109) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xfa33391ee38597cbeef72ccde8c9e13e01e78521` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Solana (1399811149) Threshold: 3 of 5 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x28464752829b3ea59a497fca0bdff575c534c3ff` | | Luganodes | `0x2b7514a2f77bd86bbf093fe6bb67d8611f51c659` | | Eclipse | `0xcb6bcbd0de155072a7ff486d9d7286b0f71dcc2d` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Solaxy (1936682104) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x4fa10dd6d854cd05f57bacf6f46d1a72eb1396e5` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Somnia (5031) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xf484907083d32fdc0848bfb998dfdde835e6f9cb` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Soneium (1868) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xd4b7af853ed6a2bfc329ecef545df90c959cbee8` | | Imperator | `0x9f4fa50ce49815b0932428a0eb1988382cef4a97` | | Enigma | `0x8d2f8ebd61d055d58768cf3b07cb2fb565d87716` | | Luganodes | `0x6c5f6ab7a369222e6691218ad981fe08a5def094` | | Tessellated | `0x0d4c1394a255568ec0ecd11795b28d1bda183ca4` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Sonic (146) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xa313d72dbbd3fa51a2ed1611ea50c37946fa42f7` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | | Luganodes | `0x7f0e75c5151d0938eaa9ab8a30f9ddbd74c4ebef` | | Enigma | `0x4e3d1c926843dcc8ff47061bbd7143a2755899f3` | ## Sonic SVM (507150715) Threshold: 3 of 4 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xf21f46905d8d09f76bc8c503f856e5466bc5ffea` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Sonic SVM | `0x85c7a16790cfd9dad6d4abdd4e2d3f1d550c7606` | ## SOON (50075007) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x0E6723b3C1eD3Db0C24347AA2cf16D28BC2a1F76` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Sophon (50104) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xb84c5d02120ed0b39d0f78bbc0e298d89ebcd10b` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Stable (988) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x21820baebcd972c769e490415cfee43a894f3c18` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Starknet (358974494) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x61204c987d1121175a74e04d5045ab708aa1489f` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | | Staked | `0xb3ac35d3988bca8c2ffd195b1c6bee18536b317b` | ## Subtensor (964) Threshold: 3 of 4 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xd5f8196d7060b85bea491f0b52a671e05f3d10a2` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Superseed (5330) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xdc2b87cb555411bb138d3a4e5f7832c87fae2b88` | | Imperator | `0x68f3a3b244f6ddc135130200a6b8729e290b4240` | | Enigma | `0x6ff4554cffbc2e4e4230b78e526eab255101d05a` | | Luganodes | `0x55880ac03fdf15fccff54ed6f8a83455033edd22` | | Tessellated | `0x0d4c1394a255568ec0ecd11795b28d1bda183ca4` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Swell (1923) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x4f51e4f4c7fb45d82f91568480a1a2cfb69216ed` | | Luganodes | `0x9eadf9217be22d9878e0e464727a2176d5c69ff8` | | Imperator | `0xa5a23fa2a67782bbf1a540cb5ca6a47a0f3f66fb` | | Enigma | `0x3f707633ccab09d2978e29107c0bbef8a993e7a0` | | Tessellated | `0x0d4c1394a255568ec0ecd11795b28d1bda183ca4` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## TAC (239) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x606561d6a45188ba0a486e513e440bfc421dbc36` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Taiko (167000) Threshold: 3 of 4 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xa930073c8f2d0b2f7423ea32293e0d1362e65d79` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Luganodes | `0x2F007c82672F2Bb97227D4e3F80Ac481bfB40A2a` | ## Torus (21000) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x96982a325c28a842bc8cf61b63000737bb9f1f7d` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Tron (728126428) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x5f059616ce75d0fe6a02ea1d9fd2b32659b52adb` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Unichain (130) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x9773a382342ebf604a2e5de0a1f462fb499e28b1` | | Imperator | `0xa2549be30fb852c210c2fe8e7639039dca779936` | | Enigma | `0xbcbed4d11e946844162cd92c6d09d1cf146b4006` | | Luganodes | `0xa9d517776fe8beba7d67c21cac1e805bd609c08e` | | Tessellated | `0x0d4c1394a255568ec0ecd11795b28d1bda183ca4` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | ## Vana (1480) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xfdf3b0dfd4b822d10cacb15c8ae945ea269e7534` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Viction (88) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | BlockPI | `0x6d113ae51bfea7b63a8828f97e9dce393b25c189` | | RockX | `0xa3f93fe365bf99f431d8fde740b140615e24f99b` | | Abacus Works | `0x1f87c368f8e05a85ef9126d984a980a20930cb9c` | ## World Chain (480) Threshold: 4 of 6 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x31048785845325b22817448b68d08f8a8fe36854` | | Imperator | `0x11e2a683e83617f186614071e422b857256a9aae` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | | Luganodes | `0xc1545f9fe903736b2e438b733740bd3516486da5` | | Enigma | `0x698810f8ae471f7e34860b465aeeb03df407be47` | ## Xai (660279) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xe993f01fea86eb64cda45ae5af1d5be40ac0c7e9` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## XLayer (196) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xa2ae7c594703e988f23d97220717c513db638ea3` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## XRPL EVM (1440000) Threshold: 2 of 2 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x14d3e2f28d60d54a1659a205cb71e6e440f06510` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## 0G (16661) Threshold: 4 of 6 | Operator | Address | | -------------- | -------------------------------------------- | | Abacus Works | `0xc37e7dad064c11d7ecfc75813a4d8d649d797275` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | | Zee Prime | `0x5450447aee7b544c462c9352bef7cad049b0c2dc` | | Luganodes | `0x25c5fc524ac7ef5e7868644fbe68793e5eb179ea` | | Enigma | `0x782ac2b5244b69779bd7214a2d60212fb35c3ae7` | | Substance Labs | `0xd3e6a4e61b5d902a63df6dac9db5585d9f319b09` | ## ZetaChain (7000) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xa3bca0b80317dbf9c7dce16a16ac89f4ff2b23ef` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Zircuit (48900) Threshold: 3 of 4 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x169ec400cc758fef3df6a0d6c51fbc6cdd1015bb` | | Luganodes | `0x7aC6584c068eb2A72d4Db82A7B7cd5AB34044061` | | Renzo | `0x1da9176C2CE5cC7115340496fa7D1800a98911CE` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## zkSync (324) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xadd1d39ce7a687e32255ac457cf99a6d8c5b5d1a` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | ## Zora (7777777) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x35130945b625bb69b28aee902a3b9a76fa67125f` | | Merkly | `0xcf0211fafbb91fd9d06d7e306b30032dc3a1934f` | | Mitosis | `0x4f977a59fdc2d9e39f6d780a84d5b4add1495a36` | # Testnet Source: https://docs.hyperlane.xyz/docs/reference/addresses/validators/testnet-default-ism-validators Default ISM validator configurations for testnet chains ## Aleo Testnet (1617853565) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x7233d80194c69af6b84b0786a7fd2a7294396ca8` | ## Arbitrum Sepolia (421614) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x09fabfbca0b8bf042e2a1161ee5010d147b0f603` | ## Base Sepolia (84532) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x82e3b437a2944e3ff00258c93e72cd1ba5e0e921` | ## BSC Testnet (97) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x242d8a855a8c932dec51f7999ae7d1e48b10c95e` | | Abacus Works | `0xf620f5e3d25a3ae848fec74bccae5de3edcd8796` | | Abacus Works | `0x1f030345963c54ff8229720dd3a711c15c554aeb` | ## Celestia Testnet (1297040200) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x3e0227b7f129576c53ff5d98d17c9b8433445094` | ## Celo Sepolia (11142220) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x4a5cfcfd7f793f4ceba170c3decbe43bd8253ef6` | ## Coti Testnet (7082400) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x5c535dff16237a2cae97c97f9556404cd230c9c0` | ## Fuji (43113) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xd8154f73d04cc7f7f0c332793692e6e6f6b2402e` | | Abacus Works | `0x895ae30bc83ff1493b9cf7781b0b813d23659857` | | Abacus Works | `0x43e915573d9f1383cbf482049e4a012290759e7f` | ## Hyperliquid EVM Testnet (998) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xea673a92a23ca319b9d85cc16b248645cd5158da` | ## Incentiv Testnet v2 (28802) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x3133eeb96fd96f9f99291088613edf7401149e6f` | ## Mode Testnet (919) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x9a9de3e406ab3e4ff12aa03ca9b868b48dc40402` | ## Optimism Sepolia (11155420) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x03efe4d0632ee15685d7e8f46dea0a874304aa29` | ## Paradex Sepolia (12263410) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x7d49abcceafa5cd82f6615a9779f29c76bfc88e8` | ## Polygon Amoy (80002) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xf0290b06e446b320bd4e9c4a519420354d7ddccd` | ## Radix Stokenet (1280787160) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xeddaf7958627cfd35400c95db19a656a4a8a92c6` | ## Sepolia (11155111) Threshold: 2 of 3 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xb22b65f202558adf86a8bb2847b76ae1036686a5` | | Abacus Works | `0x469f0940684d147defc44f3647146cb90dd0bc8e` | | Abacus Works | `0xd3c75dcf15056012a4d74c483a0c6ea11d8c2b83` | ## Solana Testnet (1399811150) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xd4ce8fa138d4e083fc0e480cca0dbfa4f5f30bd5` | ## Somnia Testnet (50312) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xb3b27a27bfa94002d344e9cf5217a0e3502e018b` | ## Sonic SVM Testnet (15153042) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x83d4ef35f170ec822a0eaadb22a0c40003d8de23` | ## Starknet Sepolia (23448591) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0xd07272cc3665d6e383a319691dcce5731ecf54a5` | ## Tron Testnet (346621343) Threshold: 1 of 1 | Operator | Address | | ------------ | -------------------------------------------- | | Abacus Works | `0x189ea37efb3764ab638cbaecbe764a8e814e7583` | # Deprecated Chains Source: https://docs.hyperlane.xyz/docs/reference/deprecated-chains Chains being removed from Abacus Works agent operations Abacus Works is winding down its [Relayer](/docs/protocol/agents/relayer) and [Validator](/docs/protocol/agents/validators) operations for the chains listed below. **What this means:** * **Relayer** — Once removed, messages will not be automatically delivered. The community can [run their own Relayer](/docs/operate/relayer/run-relayer) to keep message delivery operational. * **Validators** — Abacus Works will wind down its Validators for these chains. Chain teams and ecosystem partners can [run their own Validator](/docs/operate/validators/run-validators) and [reach out to the Abacus Works team](https://github.com/hyperlane-xyz/hyperlane-monorepo/discussions) to update the [default ISM](/docs/reference/addresses/validators/mainnet-default-ism-validators). If you're building on any of these chains, plan your migration before the last supported date. After the listed date, Abacus Works will no longer operate agents for that chain. To take over agent operations, refer to the [Validator](/docs/operate/validators/run-validators) and [Relayer](/docs/operate/relayer/run-relayer) guides. | Chain | Domain ID | Chain ID | Last Supported Date | | ------------- | ---------- | ---------- | ------------------- | | Arbitrum Nova | 42170 | 42170 | May 10, 2026 | | Aurora | 1313161554 | 1313161554 | May 10, 2026 | | B² Network | 223 | 223 | May 10, 2026 | | B3 | 8333 | 8333 | May 10, 2026 | | Degen | 666666666 | 666666666 | May 10, 2026 | | Dogechain | 2000 | 2000 | May 10, 2026 | | Everclear | 25327 | 25327 | May 10, 2026 | | Fantom Opera | 250 | 250 | May 10, 2026 | | Fluence | 9999999 | 9999999 | May 10, 2026 | | Harmony One | 1666600000 | 1666600000 | May 10, 2026 | | Merlin | 4200 | 4200 | May 10, 2026 | | MilkyWay | 1835625579 | milkyway | May 10, 2026 | | Molten | 360 | 360 | May 10, 2026 | | Moonbeam | 1284 | 1284 | May 10, 2026 | | Polygon zkEVM | 1101 | 1101 | May 10, 2026 | | Polynomial | 1000008008 | 8008 | May 10, 2026 | | Scroll | 534352 | 534352 | May 10, 2026 | | Story Mainnet | 1514 | 1514 | May 10, 2026 | | Superposition | 1000055244 | 55244 | May 10, 2026 | | Tangle | 5845 | 5845 | May 10, 2026 | | Zero Network | 543210 | 543210 | May 10, 2026 | | Zora | 7777777 | 7777777 | May 10, 2026 | | Zircuit | 48900 | 48900 | June 20, 2026 | *Chain and domain IDs sourced from the [Hyperlane Registry](https://github.com/hyperlane-xyz/hyperlane-registry).* # Unit testing - EVM Source: https://docs.hyperlane.xyz/docs/reference/developer-tips/unit-testing Unit testing can prove to be challenging for a multichain setup with Foundry. Hence, we've provided a lightweight test environment [`MockHyperlaneEnvironment`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/mock/MockHyperlaneEnvironment.sol) for you to unit test your cross-chain app while avoiding the need to fork multiple networks. Most multichain apps will be built on top of our Mailbox contract. So, we've abstracted away the details of a deployed mailbox with a `MockMailbox` and our environment contains an `originMailbox` and a `destinationMailbox` on the same chain. Internally, we store the messages arriving to the destination in the `inboundMessages` mapping on the destination mailbox. We simulate message delivery by enqueuing messages and increment the `inboundProcessedNonce` with `MockMailbox.processNextInboundMessage()`. The setup for the simple messaging forge test is as following: ## Sending a message ```solidity theme={null} contract SimpleMessagingTest is Test { // origin and destination domains (recommended to be the chainId) uint32 origin = 1; uint32 destination = 2; // both mailboxes will be on the same chain but different addresses MockMailbox originMailbox; MockMailbox destinationMailbox; // contract which can receive messages TestRecipient receiver; function setUp() public { originMailbox = new MockMailbox(origin); destinationMailbox = new MockMailbox(destination); originMailbox.addRemoteMailbox(destination, destinationMailbox); receiver = new TestRecipient(); } function testSendMessage() public { string _message = "Aloha!"; originMailbox.dispatch( destination, TypeCasts.addressToBytes32(address(receiver)), bytes(_message) ); // simulating message delivery to the destinationMailbox destinationMailbox.processNextInboundMessage(); assertEq(string(receiver.lastData()), _message); } } ``` ## Testing Router-based apps Assuming you're testing `TestCrosschainApp` which inherits from `Router`: ```solidity theme={null} contract CrosschainAppTest is Test { // origin and destination domains (recommended to be the chainId) uint32 origin = 1; uint32 destination = 2; function setUp() public { environment = new MockHyperlaneEnvironment(origin, destination); // your cross-chain app TestCrosschainApp originTelephone = new TestCrosschainApp(environment.mailboxes(origin)); TestCrosschainApp destinationTelephone = new TestCrosschainApp(environment.mailboxes(destination)); // assuming you're inheriting the Router pattern from https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/client/Router.sol originTelephone.enrollRemoteRouter(destinationTelephone); destinationTelephone.enrollRemoteRouter(originTelephone); } } ``` Call `processNextPendingMessage()` and `processNextPendingMessageFromDestination()` to process inbound messages for destination and origin mailboxes respectively. Now, you can make your cross-chain calls from origin to destination and vice-versa: ```solidity theme={null} function testRemoteTelephoneCallFromOrigin() public { // check behavior on origin vm.expectEmit(true, true, true, false); emit TelephoneRinging(destination, TypeCasts.bytes32ToAddress(destinationTelephone), "Hello!"); // example event on origin originTelephone.callRemote(destination, TypeCasts.bytes32ToAddress(destinationTelephone), "Hello!"); // simulating message delivery origin -> destination environment.processNextPendingMessage(); // check behavior on destination assertEq(destinationTelephone.latestMessage(originTelephone) == "Hello!"); } function testRemoteTelephoneCallFromDestination() public { // check behavior on destination vm.expectEmit(true, true, true, false); emit TelephoneRinging(origin, TypeCasts.bytes32ToAddress(originTelephone), "Howdy!"); // example event on destination destinationTelephone.callRemote(origin, TypeCasts.bytes32ToAddress(originTelephone), "Howdy!"); // simulating message delivery destination -> origin environment.processNextPendingMessageFromDestination(); // check behavior on origin assertEq(originTelephone.latestMessage(destinationTelephone) == "Howdy!"); } ``` If you want to use your own ISM for your app, you can override the `defaultIsm` mailbox provides by passing it to the Router's `initialize` method like following: ```solidity theme={null} contract CrosschainAppTest is Test { // origin and destination domains (recommended to be the chainId) uint32 origin = 1; uint32 destination = 2; function setUp() public { ... TestIgp igp = new TestIgp(); // example InterchainGasPaymaster passed as the hook // deploy your own ISM contracts to verify messages between originTelephone and destinationTelephone TelephoneISM originIsm = new TelephoneISM(); // local ISM for origin TelephoneISM destinationIsm = new TelephoneISM(); // local ISM for destination originTelephone.initialize(address(igp), address(originIsm), msg.sender); originTelephone.initialize(address(igp), address(destinationIsm), msg.sender); ... } } ``` You can find examples of our unit testing setup here: [InterchainAccountRouterTest](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/dae8b26ed65383844e4fbed7585deeb52da4e454/solidity/test/InterchainAccountRouter.t.sol#L38). # Hyperlane CLI Source: https://docs.hyperlane.xyz/docs/reference/developer-tools/cli ## Overview[​](#overview "Direct link to Overview") The Hyperlane CLI is the official command-line tool for deploying Hyperlane contracts to new chains. It also includes utilities for interacting with deployed contracts and registries. The published version is available [on NPM](https://www.npmjs.com/package/@hyperlane-xyz/cli). The source is available [on GitHub in the monorepo](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/typescript/cli). ## Setup[​](#setup "Direct link to Setup") [Node 18](https://nodejs.org/en/download) or newer is required To install the CLI globally, use the `npm install -g` command. This will the `hyperlane` command available anywhere in your terminal. ``` # Install with NPM npm install -g @hyperlane-xyz/cli # Or uninstall old versions npm uninstall -g @hyperlane-xyz/cli ``` Alternatively, for running individual commands, you can use `npx` or `dlx`: ``` # Run via NPM's npx command npx @hyperlane-xyz/cli # Or via Yarn's dlx command yarn dlx @hyperlane-xyz/cli ``` ## Usage[​](#usage "Direct link to Usage") To view a list of the available commands and their arguments, run `hyperlane --help`. A few common command options include: * `--version`: Display your current installed version of the CLI * `--registry`: Set the registry URI to use for chain metadata and contract addresses * `--overrides`: Set an additional path for overrides to the canonical registry data * `log`: Set the log format for the CLI (defaults to pretty) * `verbosity`: Set the log level for the CLI (defaults to info) * `key`: Set the key to use for signing transactions (defaults to the HYP\_KEY env var) ## Registries[​](#registries "Direct link to Registries") By default, the CLI will pull chain metadata and contract addresses from the [canonical Hyperlane Registry](https://github.com/hyperlane-xyz/hyperlane-registry) but will write new configs and deployments to your local filesystem. For more information see the [Registries page](/docs/reference/registries). ## Warp Send[​](#warp-send "Direct link to Warp Send") `hyperlane warp send` supports transfers between any combination of supported VMs: | Protocol | Examples | | --------------------- | ---------------------------------- | | Ethereum (EVM) | Ethereum, Arbitrum, Base, Optimism | | Tron | Tron mainnet | | Sealevel (SVM) | Solana, Eclipse | | Cosmos / CosmosNative | Neutron, Injective, Stride | | Starknet | Starknet mainnet | | Radix | Radix mainnet | ### Basic usage ```bash theme={null} # EVM to EVM hyperlane warp send -w ETH/ethereum-arbitrum # EVM to Cosmos (recipient required for non-EVM destinations) hyperlane warp send -w USDC/ethereum-neutron --recipient neutron1abc... # Cosmos to EVM export HYP_KEY_COSMOSNATIVE= hyperlane warp send -w ATOM/neutron-ethereum --amount 1000000 ``` ### Non-EVM destination requirements When the destination chain is non-EVM, the following rules apply: * **`--recipient` is required** — there is no signer-based fallback for non-EVM destinations. Omitting it will error before any transaction is sent. * **`--relay` is skipped** — self-relay only works when both origin and destination are EVM. For non-EVM destinations, run an external [relayer](/docs/operate/relayer/run-relayer) or wait for the Hyperlane relayer network to deliver. * **`--round-trip` requires all-EVM chains** — since non-EVM chains cannot be intermediate hop origins, round-trip mode is restricted to EVM-only routes. * **Delivery confirmation** — for non-EVM destinations, the CLI polls the [Hyperlane Explorer](/docs/reference/explorer/overview) for delivery status instead of checking on-chain. The CLI prints the message ID after a successful send — track delivery at `https://explorer.hyperlane.xyz/message/`. ### Non-EVM origin requirements When sending from a non-EVM origin chain, set the protocol-specific private key: ```bash theme={null} # Cosmos / CosmosNative export HYP_KEY_COSMOSNATIVE= # Sealevel (SVM) — path to Solana keypair file export HYP_KEY_SEALEVEL= # Starknet export HYP_KEY_STARKNET= # Tron export HYP_KEY_TRON= # Radix export HYP_KEY_RADIX= ``` ### Multi-hop transfers In multi-hop transfers, non-EVM chains can only appear as the **final destination**, not as intermediate hops. When no `--origin`/`--destination` is specified, the CLI automatically orders EVM chains first so non-EVM chains become the final destination. ## Warp Route ID Many CLI commands accept a `--warp-route-id` flag to specify which warp route to use. **Aliases:** `-w`, `--id` **Accepts:** * `SYMBOL/id` - full route ID, where `id` is the route's unique identifier (e.g., `ETH/ethereum-arbitrum`, `ETH/viction`) * `SYMBOL` - auto-resolves if unique, prompts if multiple (errors in CI) **Resolution logic:** 1. If input contains `/` → exact match 2. If SYMBOL only → find all routes with that symbol * Single match → use it * Multiple matches + interactive → prompt selection * Multiple matches + CI → error with list of options 3. Commands with `--origin`/`--destination` (e.g., `warp send`) use those to filter route resolution (matching routes that contain both chains) and control transfer direction **Examples:** ```bash theme={null} # Full route ID hyperlane warp check -w ETH/viction # Symbol only - auto-selects if unique hyperlane warp apply --id USDC # Symbol + chain filter (warp send) hyperlane warp send -w ETH --origin ethereum --destination arbitrum ``` # StandardHookMetadata Library Source: https://docs.hyperlane.xyz/docs/reference/developer-tools/libraries/hookmetadata The `StandardHookMetadata` library provides utilities for handling and formatting metadata used in Hyperlane hooks. This library enables you to pack and extract information such as gas limits, refund addresses, and custom metadata for messages. * **Parse Metadata**: Functions like `variant`, `msgValue`, `gasLimit`, and `refundAddress` help you extract specific metadata fields from ABI-encoded data. * **Custom Metadata**: `getCustomMetadata` retrieves any additional metadata beyond the standard fields. * **Format Metadata**: `formatMetadata` lets you construct ABI-encoded metadata with fields like gas limit, refund address, and custom data. ## StandardHookMetadata Library ```solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; /*@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ HYPERLANE @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@*/ /** * Format of metadata: * * [0:1] variant * [2:33] msg.value * [34:65] Gas limit for message (IGP) * [66:85] Refund address for message (IGP) * [86:] Custom metadata */ library StandardHookMetadata { uint8 private constant VARIANT_OFFSET = 0; uint8 private constant MSG_VALUE_OFFSET = 2; uint8 private constant GAS_LIMIT_OFFSET = 34; uint8 private constant REFUND_ADDRESS_OFFSET = 66; uint256 private constant MIN_METADATA_LENGTH = 86; uint16 public constant VARIANT = 1; /** * @notice Returns the variant of the metadata. * @param _metadata ABI encoded global hook metadata. * @return variant of the metadata as uint8. */ function variant(bytes calldata _metadata) internal pure returns (uint16) { if (_metadata.length < VARIANT_OFFSET + 2) return 0; return uint16(bytes2(_metadata[VARIANT_OFFSET:VARIANT_OFFSET + 2])); } /** * @notice Returns the specified value for the message. * @param _metadata ABI encoded global hook metadata. * @param _default Default fallback value. * @return Value for the message as uint256. */ function msgValue( bytes calldata _metadata, uint256 _default ) internal pure returns (uint256) { if (_metadata.length < MSG_VALUE_OFFSET + 32) return _default; return uint256(bytes32(_metadata[MSG_VALUE_OFFSET:MSG_VALUE_OFFSET + 32])); } /** * @notice Returns the specified gas limit for the message. * @param _metadata ABI encoded global hook metadata. * @param _default Default fallback gas limit. * @return Gas limit for the message as uint256. */ function gasLimit( bytes calldata _metadata, uint256 _default ) internal pure returns (uint256) { if (_metadata.length < GAS_LIMIT_OFFSET + 32) return _default; return uint256(bytes32(_metadata[GAS_LIMIT_OFFSET:GAS_LIMIT_OFFSET + 32])); } /** * @notice Returns the specified refund address for the message. * @param _metadata ABI encoded global hook metadata. * @param _default Default fallback refund address. * @return Refund address for the message as address. */ function refundAddress( bytes calldata _metadata, address _default ) internal pure returns (address) { if (_metadata.length < REFUND_ADDRESS_OFFSET + 20) return _default; return address( bytes20( _metadata[REFUND_ADDRESS_OFFSET:REFUND_ADDRESS_OFFSET + 20] ) ); } /** * @notice Returns the specified refund address for the message. * @param _metadata ABI encoded global hook metadata. * @return Refund address for the message as address. */ function getCustomMetadata( bytes calldata _metadata ) internal pure returns (bytes calldata) { if (_metadata.length < MIN_METADATA_LENGTH) return _metadata[0:0]; return _metadata[MIN_METADATA_LENGTH:]; } /** * @notice Formats the specified gas limit and refund address into global hook metadata. * @param _msgValue msg.value for the message. * @param _gasLimit Gas limit for the message. * @param _refundAddress Refund address for the message. * @param _customMetadata Additional metadata to include in the global hook metadata. * @return ABI encoded global hook metadata. */ function formatMetadata( uint256 _msgValue, uint256 _gasLimit, address _refundAddress, bytes memory _customMetadata ) internal pure returns (bytes memory) { return abi.encodePacked( VARIANT, _msgValue, _gasLimit, _refundAddress, _customMetadata ); } /** * @notice Formats the specified gas limit and refund address into global hook metadata. * @param _msgValue msg.value for the message. * @return ABI encoded global hook metadata. */ function formatMetadata( uint256 _msgValue ) internal view returns (bytes memory) { return formatMetadata(_msgValue, uint256(0), msg.sender, ""); } /** * @notice Formats the specified gas limit and refund address into global hook metadata. * @param _gasLimit Gas limit for the message. * @param _refundAddress Refund address for the message. * @return ABI encoded global hook metadata. */ function formatMetadata( uint256 _gasLimit, address _refundAddress ) internal pure returns (bytes memory) { return formatMetadata(uint256(0), _gasLimit, _refundAddress, ""); } } ``` # MailboxClient Library Source: https://docs.hyperlane.xyz/docs/reference/developer-tools/libraries/mailbox-client Inheriting from [`MailboxClient`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/v3/solidity/contracts/client/MailboxClient.sol) is a simple way to ensure your contract knows where to send or receive interchain messages to or from. This mix-in contract maintains a pointers to the three contracts Hyperlane developers may need to interact with: 1. [`Mailbox`](/docs/protocol/core/mailbox) (required) 2. [`IPostDispatchHook`](/docs/protocol/core/post-dispatch-hooks-overview) (optional) 3. [`IInterchainSecurityModule`](/docs/protocol/ISM/modular-security) (optional) `MailboxClient` exposes functions that allow subclasses to easily send messages to the `Mailbox` via the `mailbox` storage variable, and permission message delivery via the `onlyMailbox` modifier. ## MailboxClient Library ```solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; // ============ Internal Imports ============ import {IMailbox} from "../interfaces/IMailbox.sol"; import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; import {IInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol"; import {Message} from "../libs/Message.sol"; // ============ External Imports ============ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; abstract contract MailboxClient is OwnableUpgradeable { using Message for bytes; IMailbox public immutable mailbox; uint32 public immutable localDomain; IPostDispatchHook public hook; IInterchainSecurityModule public interchainSecurityModule; // ============ Modifiers ============ modifier onlyContract(address _contract) { require( Address.isContract(_contract), "MailboxClient: invalid mailbox" ); _; } modifier onlyContractOrNull(address _contract) { require( Address.isContract(_contract) || _contract == address(0), "MailboxClient: invalid contract setting" ); _; } /** * @notice Only accept messages from an Hyperlane Mailbox contract */ modifier onlyMailbox() { require( msg.sender == address(mailbox), "MailboxClient: sender not mailbox" ); _; } constructor(address _mailbox) onlyContract(_mailbox) { mailbox = IMailbox(_mailbox); localDomain = mailbox.localDomain(); _transferOwnership(msg.sender); } /** * @notice Sets the address of the application's custom hook. * @param _hook The address of the hook contract. */ function setHook(address _hook) public onlyContractOrNull(_hook) onlyOwner { hook = IPostDispatchHook(_hook); } /** * @notice Sets the address of the application's custom interchain security module. * @param _module The address of the interchain security module contract. */ function setInterchainSecurityModule( address _module ) public onlyContractOrNull(_module) onlyOwner { interchainSecurityModule = IInterchainSecurityModule(_module); } // ======== Initializer ========= function _MailboxClient_initialize( address _hook, address _interchainSecurityModule, address _owner ) internal onlyInitializing { __Ownable_init(); setHook(_hook); setInterchainSecurityModule(_interchainSecurityModule); _transferOwnership(_owner); } function _isLatestDispatched(bytes32 id) internal view returns (bool) { return mailbox.latestDispatchedId() == id; } function _metadata( uint32 /*_destinationDomain*/ ) internal view virtual returns (bytes memory) { return ""; } function _dispatch( uint32 _destinationDomain, bytes32 _recipient, bytes memory _messageBody ) internal virtual returns (bytes32) { return _dispatch(_destinationDomain, _recipient, msg.value, _messageBody); } function _dispatch( uint32 _destinationDomain, bytes32 _recipient, uint256 _value, bytes memory _messageBody ) internal virtual returns (bytes32) { return mailbox.dispatch{value: _value}( _destinationDomain, _recipient, _messageBody, _metadata(_destinationDomain), hook ); } function _quoteDispatch( uint32 _destinationDomain, bytes32 _recipient, bytes memory _messageBody ) internal view virtual returns (uint256) { return mailbox.quoteDispatch( _destinationDomain, _recipient, _messageBody, _metadata(_destinationDomain), hook ); } } ``` # Message Library Source: https://docs.hyperlane.xyz/docs/reference/developer-tools/libraries/message The `Message` library helps you format and parse interchain messages for use with the Hyperlane `Mailbox` contract. * **Construct Messages**: `formatMessage` lets you pack all the key fields into a single, ready-to-send message. * **Extract Fields**: Functions like `version`, `nonce`, `origin`, `senderAddress`, `recipientAddress`, and `body` help you pull out specific parts of a message for processing. * **Get Message ID**: `id` generates a unique identifier for each message using `keccak256`. ## Message Library ```solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; import {TypeCasts} from "./TypeCasts.sol"; /** * @title Hyperlane Message Library * @notice Library for formatted messages used by Mailbox **/ library Message { using TypeCasts for bytes32; uint256 private constant VERSION_OFFSET = 0; uint256 private constant NONCE_OFFSET = 1; uint256 private constant ORIGIN_OFFSET = 5; uint256 private constant SENDER_OFFSET = 9; uint256 private constant DESTINATION_OFFSET = 41; uint256 private constant RECIPIENT_OFFSET = 45; uint256 private constant BODY_OFFSET = 77; /** * @notice Returns formatted (packed) Hyperlane message with provided fields * @dev This function should only be used in memory message construction. * @param _version The version of the origin and destination Mailboxes * @param _nonce A nonce to uniquely identify the message on its origin chain * @param _originDomain Domain of origin chain * @param _sender Address of sender as bytes32 * @param _destinationDomain Domain of destination chain * @param _recipient Address of recipient on destination chain as bytes32 * @param _messageBody Raw bytes of message body * @return Formatted message */ function formatMessage( uint8 _version, uint32 _nonce, uint32 _originDomain, bytes32 _sender, uint32 _destinationDomain, bytes32 _recipient, bytes calldata _messageBody ) internal pure returns (bytes memory) { return abi.encodePacked( _version, _nonce, _originDomain, _sender, _destinationDomain, _recipient, _messageBody ); } /** * @notice Returns the message ID. * @param _message ABI encoded Hyperlane message. * @return ID of `_message` */ function id(bytes memory _message) internal pure returns (bytes32) { return keccak256(_message); } /** * @notice Returns the message version. * @param _message ABI encoded Hyperlane message. * @return Version of `_message` */ function version(bytes calldata _message) internal pure returns (uint8) { return uint8(bytes1(_message[VERSION_OFFSET:NONCE_OFFSET])); } /** * @notice Returns the message nonce. * @param _message ABI encoded Hyperlane message. * @return Nonce of `_message` */ function nonce(bytes calldata _message) internal pure returns (uint32) { return uint32(bytes4(_message[NONCE_OFFSET:ORIGIN_OFFSET])); } /** * @notice Returns the message origin domain. * @param _message ABI encoded Hyperlane message. * @return Origin domain of `_message` */ function origin(bytes calldata _message) internal pure returns (uint32) { return uint32(bytes4(_message[ORIGIN_OFFSET:SENDER_OFFSET])); } /** * @notice Returns the message sender as bytes32. * @param _message ABI encoded Hyperlane message. * @return Sender of `_message` as bytes32 */ function sender(bytes calldata _message) internal pure returns (bytes32) { return bytes32(_message[SENDER_OFFSET:DESTINATION_OFFSET]); } /** * @notice Returns the message sender as address. * @param _message ABI encoded Hyperlane message. * @return Sender of `_message` as address */ function senderAddress( bytes calldata _message ) internal pure returns (address) { return sender(_message).bytes32ToAddress(); } /** * @notice Returns the message destination domain. * @param _message ABI encoded Hyperlane message. * @return Destination domain of `_message` */ function destination( bytes calldata _message ) internal pure returns (uint32) { return uint32(bytes4(_message[DESTINATION_OFFSET:RECIPIENT_OFFSET])); } /** * @notice Returns the message recipient as bytes32. * @param _message ABI encoded Hyperlane message. * @return Recipient of `_message` as bytes32 */ function recipient( bytes calldata _message ) internal pure returns (bytes32) { return bytes32(_message[RECIPIENT_OFFSET:BODY_OFFSET]); } /** * @notice Returns the message recipient as address. * @param _message ABI encoded Hyperlane message. * @return Recipient of `_message` as address */ function recipientAddress( bytes calldata _message ) internal pure returns (address) { return recipient(_message).bytes32ToAddress(); } /** * @notice Returns the message body. * @param _message ABI encoded Hyperlane message. * @return Body of `_message` */ function body( bytes calldata _message ) internal pure returns (bytes calldata) { return bytes(_message[BODY_OFFSET:]); } } ``` # Router Library Source: https://docs.hyperlane.xyz/docs/reference/developer-tools/libraries/router Application developers looking to write their contracts once and deploy them on multiple chains should consider building with the [`Router`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/v3/solidity/contracts/client/Router.sol) pattern. In this pattern, an instance of the application's contracts is deployed on each application-supported chain. Each instance is made aware of the addresses of instances on other chains. These instances use Hyperlane to communicate information and state to and from instances on remote chains. ```mermaid theme={null} graph BT subgraph "Ethereum" R_E[Router] Mailbox_E[(Mailbox)] Mailbox_E -. "mailbox()" .- R_E end subgraph "Polygon" R_P[Router] Mailbox_P[(Mailbox)] Mailbox_P -. "mailbox()" .- R_P end subgraph "Gnosis" R_G[Router] Mailbox_G[(Mailbox)] Mailbox_G -. "mailbox()" .- R_G end R_E -. "routers()" .- R_P -. "routers()" .- R_G R_G -. "routers()" .- R_E ``` Developers using this pattern can inherit from the `Router` mix-in contract. `Router` is a [`MailboxClient`](./mailbox-client) that tracks the addresses of other `Router` contract addresses on remote chains. This allows `Routers` to send messages directly to others without having to specify addresses. It also allows `Routers` to reject messages sent from other untrusted senders. ## Router Library ```solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; // ============ Internal Imports ============ import {IMessageRecipient} from "../interfaces/IMessageRecipient.sol"; import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; import {IInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol"; import {MailboxClient} from "./MailboxClient.sol"; import {EnumerableMapExtended} from "../libs/EnumerableMapExtended.sol"; import {StandardHookMetadata} from "../hooks/libs/StandardHookMetadata.sol"; // ============ External Imports ============ import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; abstract contract Router is MailboxClient, IMessageRecipient { using EnumerableMapExtended for EnumerableMapExtended.UintToBytes32Map; using Strings for uint32; // ============ Mutable Storage ============ EnumerableMapExtended.UintToBytes32Map internal _routers; uint256[48] private __GAP; // gap for upgrade safety constructor(address _mailbox) MailboxClient(_mailbox) {} // ============ External functions ============ function domains() external view returns (uint32[] memory) { return _routers.uint32Keys(); } /** * @notice Returns the address of the Router contract for the given domain * @param _domain The remote domain ID. * @dev Returns 0 address if no router is enrolled for the given domain * @return router The address of the Router contract for the given domain */ function routers(uint32 _domain) public view virtual returns (bytes32) { (, bytes32 _router) = _routers.tryGet(_domain); return _router; } /** * @notice Unregister the domain * @param _domain The domain of the remote Application Router */ function unenrollRemoteRouter(uint32 _domain) external virtual onlyOwner { _unenrollRemoteRouter(_domain); } /** * @notice Register the address of a Router contract for the same Application on a remote chain * @param _domain The domain of the remote Application Router * @param _router The address of the remote Application Router */ function enrollRemoteRouter( uint32 _domain, bytes32 _router ) external virtual onlyOwner { _enrollRemoteRouter(_domain, _router); } /** * @notice Batch version of `enrollRemoteRouter` * @param _domains The domains of the remote Application Routers * @param _addresses The addresses of the remote Application Routers */ function enrollRemoteRouters( uint32[] calldata _domains, bytes32[] calldata _addresses ) external virtual onlyOwner { require(_domains.length == _addresses.length, "!length"); uint256 length = _domains.length; for (uint256 i = 0; i < length; i += 1) { _enrollRemoteRouter(_domains[i], _addresses[i]); } } /** * @notice Batch version of `unenrollRemoteRouter` * @param _domains The domains of the remote Application Routers */ function unenrollRemoteRouters( uint32[] calldata _domains ) external virtual onlyOwner { uint256 length = _domains.length; for (uint256 i = 0; i < length; i += 1) { _unenrollRemoteRouter(_domains[i]); } } /** * @notice Handles an incoming message * @param _origin The origin domain * @param _sender The sender address * @param _message The message */ function handle( uint32 _origin, bytes32 _sender, bytes calldata _message ) external payable virtual override onlyMailbox { bytes32 _router = _mustHaveRemoteRouter(_origin); require(_router == _sender, "Enrolled router does not match sender"); _handle(_origin, _sender, _message); } // ============ Virtual functions ============ function _handle( uint32 _origin, bytes32 _sender, bytes calldata _message ) internal virtual; // ============ Internal functions ============ /** * @notice Set the router for a given domain * @param _domain The domain * @param _address The new router */ function _enrollRemoteRouter( uint32 _domain, bytes32 _address ) internal virtual { _routers.set(_domain, _address); } /** * @notice Remove the router for a given domain * @param _domain The domain */ function _unenrollRemoteRouter(uint32 _domain) internal virtual { require(_routers.remove(_domain), _domainNotFoundError(_domain)); } /** * @notice Return true if the given domain / router is the address of a remote Application Router * @param _domain The domain of the potential remote Application Router * @param _address The address of the potential remote Application Router */ function _isRemoteRouter( uint32 _domain, bytes32 _address ) internal view returns (bool) { return routers(_domain) == _address; } /** * @notice Assert that the given domain has a Application Router registered and return its address * @param _domain The domain of the chain for which to get the Application Router * @return _router The address of the remote Application Router on _domain */ function _mustHaveRemoteRouter( uint32 _domain ) internal view returns (bytes32) { (bool contained, bytes32 _router) = _routers.tryGet(_domain); require(contained, _domainNotFoundError(_domain)); return _router; } function _domainNotFoundError( uint32 _domain ) internal pure returns (string memory) { return string.concat( "No router enrolled for domain: ", _domain.toString() ); } function _dispatch( uint32 _destinationDomain, bytes memory _messageBody ) internal virtual returns (bytes32) { return _dispatch(_destinationDomain, msg.value, _messageBody); } function _dispatch( uint32 _destinationDomain, uint256 _value, bytes memory _messageBody ) internal virtual returns (bytes32) { bytes32 _router = _mustHaveRemoteRouter(_destinationDomain); return super._dispatch(_destinationDomain, _router, _value, _messageBody); } function _quoteDispatch( uint32 _destinationDomain, bytes memory _messageBody ) internal view virtual returns (uint256) { bytes32 _router = _mustHaveRemoteRouter(_destinationDomain); return super._quoteDispatch(_destinationDomain, _router, _messageBody); } } ``` # Typecasts Library Source: https://docs.hyperlane.xyz/docs/reference/developer-tools/libraries/typecasts The `TypeCasts` library provides simple and efficient functions for converting between `address` and `bytes32` types. This library is useful for cases where you need to work with `bytes32` types in your smart contracts but still need to convert them back to `address` types or vice versa. ## `TypeCasts` library ```solidity theme={null} // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; library TypeCasts { // alignment preserving cast function addressToBytes32(address _addr) internal pure returns (bytes32) { return bytes32(uint256(uint160(_addr))); } // alignment preserving cast function bytes32ToAddress(bytes32 _buf) internal pure returns (address) { return address(uint160(uint256(_buf))); } } ``` # Hyperlane Typescript SDK Source: https://docs.hyperlane.xyz/docs/reference/developer-tools/typescript-sdk/overview For developers looking to further customize the Warp UI for their own projects or build their own interchain applications, we encourage you to explore the [Typescript SDK](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/typescript/sdk). The SDK contains a growing set of an utilities and abstractions for interacting with Hyperlane across different protocols (EVM, Cosmos, Solana). It provides high-level abstractions for working with: * Token transfers across chains * Chain metadata and providers * Core protocol contracts # Message Transfer Fee Calculations Source: https://docs.hyperlane.xyz/docs/reference/developer-tools/typescript-sdk/transfer-fee-calculation For an overview of transfer fees head over to: [GMP Transfer Fees](/docs/protocol/core/fees) ## Estimating Fees To estimate both fees, use `estimateTransferRemoteFees`: ```ts theme={null} const { interchainQuote, localQuote } = await warpCore.estimateTransferRemoteFees({ originToken, destination, sender, }); ``` * `interchainQuote`: Fee to route the message to the destination chain (via IGP) * `localQuote`: Gas cost to send the tx on the origin chain Each is returned as a TokenAmount which includes: * `amount`: The quantity of tokens required * `token`: The token metadata (including chain, decimals, and symbol) ## Using the Fee in Transfers When making a transfer, you can provide the pre-computed fee quote: ```ts theme={null} const txs = await warpCore.getTransferRemoteTxs({ originTokenAmount, destination, sender, recipient, }); ``` **Important Considerations:** * Fees may vary between different chain types * Some chains require additional parameters * Missing or underpaying fees will cause the transaction to revert * Fee tokens may differ from the transfer token ## How It Works Under the hood, the SDK uses [`Mailbox.quoteDispatch()`](/docs/reference/messaging/send#quote-dispatch) to compute the interchain fee. This is the same value that must be passed to `dispatch`. ## Contract-Level Fee Quoting New in version 10.0.0: Warp route contracts now expose a standardized `quoteTransferRemote` function for on-chain fee quoting. For contracts interacting directly with warp routes (without using the TypeScript SDK), you can quote fees on-chain using the `quoteTransferRemote` function: ```solidity theme={null} // Quote fees for a warp route transfer Quote[] memory quotes = warpRoute.quoteTransferRemote( destinationDomain, recipientAddress, amount // Exact amount recipient will receive ); // quotes[0]: Native mailbox dispatch fee (token: address(0)) // quotes[1]: Total token amount including internal fees // quotes[2]: External bridge fees (if any, else 0) ``` The quotes array always contains exactly 3 elements: 1. **Native Fee** (`quotes[0]`): Must be sent as `msg.value` to `transferRemote` 2. **Token Amount** (`quotes[1]`): Total tokens to approve/send, including fees 3. **External Fee** (`quotes[2]`): Additional bridge fees (already included in `quotes[1]`) See the [HWR Interface](/docs/applications/warp-routes/interface#fee-quoting-interface) for detailed documentation and examples. # Domain Identifiers Source: https://docs.hyperlane.xyz/docs/reference/domains ## Core Domains This list includes only the deployments on chains that are managed by Abacus Works (our legal entity). Anybody can deploy Hyperlane on any chain [permissionlessly](/docs/guides/chains/deploy-hyperlane) - we are building a registry to reflect the community's permissionless deployments. Hyperlane uses unique IDs for each Hyperlane-supported chain. When possible Hyperlane domain IDs match EVM chain IDs, but this is **not guaranteed** as we support non-EVM chains as well. Some Hyperlane domain IDs do not match their corresponding EVM chain IDs, such as: * `immutablezkevmmainnet` * `rarichain` * `rootstockmainnet` * `alephzeroevmmainnet` * `chilizmainnet` * `lumiaprism` * `superpositionmainnet` * `flowmainnet` * `metal` * `polynomialfi` Please refer to the table below for the full list of Hyperlane domain IDs. When sending a message, users must provide the domain ID of the destination chain. When [receiving a message](/docs/reference/messaging/receive), the recipient will be passed the domain ID of the origin chain. ## Mainnet | Network | Domain Identifier (uint32) | | --------------------- | -------------------------- | | 0G | 16661 | | Abstract | 2741 | | ADI Chain | 36900 | | Aleo | 1634493807 | | Ancient8 | 888888888 | | ApeChain | 33139 | | AppChain | 466 | | Arbitrum | 42161 | | Arcadia | 4278608 | | Artela | 11820 | | Astar | 592 | | Avalanche | 43114 | | Base | 8453 | | Berachain | 80094 | | Binance Smart Chain | 56 | | Bitlayer | 200901 | | Blast | 81457 | | BOB | 60808 | | Boba Mainnet | 288 | | Botanix | 3637 | | CarrChain | 7667 | | Celestia | 1128614981 | | Celo | 42220 | | Chiliz | 1000088888 | | Citrea | 4114 | | Core | 1116 | | Coti | 2632500 | | Cyber | 7560 | | Eclipse | 1408864445 | | Eden | 714 | | Electroneum | 52014 | | Endurance | 648 | | ENI | 173 | | Ethereum | 1 | | Everclear | 25327 | | EVM on Flow | 1000000747 | | Flare | 14 | | Fluence | 9999999 | | Fluent | 25363 | | Fraxtal | 252 | | Fuse | 122 | | Galactica | 613419 | | Gnosis | 100 | | Gravity Alpha Mainnet | 1625 | | Hashkey | 177 | | Hemi Network | 43111 | | HyperEVM | 999 | | Igra | 38833 | | Immutable zkEVM | 1000013371 | | Incentiv | 24101 | | Ink | 57073 | | Kaia | 8217 | | Katana | 747474 | | Kiichain | 1783 | | Krown | 1983 | | LazAI | 52924 | | Linea | 59144 | | Lisk | 1135 | | Lit Chain | 175200 | | LUKSO | 42 | | Lumia Prism | 1000073017 | | Manta Pacific | 169 | | Mantle | 5000 | | MANTRA | 5888 | | Matchain | 698 | | MegaETH | 4326 | | Metal L2 | 1000001750 | | Metis Andromeda | 1088 | | MilkyWay | 1835625579 | | Miraclechain | 92278 | | Mitosis | 124816 | | Moca Chain | 2288 | | Mode | 34443 | | Molten | 360 | | Monad | 143 | | Morph | 2818 | | Nibiru | 6900 | | Ontology | 58 | | Oort | 970 | | opBNB | 204 | | Optimism | 10 | | Orderly L2 | 291 | | Paradex | 514051890 | | Peaq | 3338 | | Plasma | 9745 | | Plume | 98866 | | Polygon | 137 | | Polynomial | 1000008008 | | Prom | 227 | | PulseChain | 369 | | Radix | 1633970780 | | RARI Chain | 1000012617 | | Reactive Mainnet | 1597 | | Redstone | 690 | | Ronin | 2020 | | Sei | 1329 | | Shibarium | 109 | | Solana | 1399811149 | | Solaxy | 1936682104 | | Somnia | 5031 | | Soneium | 1868 | | Sonic | 146 | | Sonic SVM | 507150715 | | SOON | 50075007 | | Sophon | 50104 | | Stable | 988 | | Starknet | 358974494 | | Subtensor | 964 | | Superseed | 5330 | | Swell | 1923 | | TAC | 239 | | Taiko | 167000 | | Tempo | 4217 | | Torus | 21000 | | Tron | 728126428 | | Unichain | 130 | | Vana | 1480 | | Viction | 88 | | World Chain | 480 | | Xai | 660279 | | XLayer | 196 | | XRPL EVM | 1440000 | | ZetaChain | 7000 | | Zircuit | 48900 | | zkSync | 324 | | Zora | 7777777 | ## Testnet | Network | Domain Identifier (uint32) | | ----------------------- | -------------------------- | | Aleo Testnet | 1617853565 | | Arbitrum Sepolia | 421614 | | Base Sepolia | 84532 | | BSC Testnet | 97 | | Celestia Testnet | 1297040200 | | Celo Sepolia | 11142220 | | Coti Testnet | 7082400 | | Fuji | 43113 | | Hyperliquid EVM Testnet | 998 | | Incentiv Testnet v2 | 28802 | | Mode Testnet | 919 | | Optimism Sepolia | 11155420 | | Paradex Sepolia | 12263410 | | Polygon Amoy | 80002 | | Radix Stokenet | 1280787160 | | Sepolia | 11155111 | | Solana Testnet | 1399811150 | | Somnia Testnet | 50312 | | Sonic SVM Testnet | 15153042 | | Sonic Testnet | 64165 | | Starknet Sepolia | 23448591 | | SUAVE Toliman Testnet | 33626250 | | Tangle Testnet | 3799 | | Tron Testnet | 346621343 | # Configuring New Chains in the Hyperlane Explorer Source: https://docs.hyperlane.xyz/docs/reference/explorer/configuring-pi-chains Hyperlane can be deployed to any chain by anyone, this open access is called Permissionless Interoperability (PI). However the messages on PI chains cannot be identified by the default Hyperlane Agents. To view details about messages from PI chains, first configure the explorer with metadata about that chain. ## Adding Chain Metadata to Hyperlane Explorer 1. On the Explorer’s homepage, click either the Origin or Destination button to open the chain selection. This will open the chain selection modal. From there, click the plus icon in the top-right. 2. On the form that appears, enter the chain’s metadata using JSON or YAML conforming to the [ChainMetadata schema](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/typescript/sdk/src/metadata/chainMetadataTypes.ts). 3. If a valid Etherscan-based block explorer config is provided, the Hyperlane Explorer will utilize it to find the desired messages. If not, it will use the RPC URL. Note, Explorers with API keys (even just free-tier keys), perform faster and more reliably. ### Chain Metadata Examples **A minimal example in JSON:** ```json theme={null} { "chainId": 11155111, "name": "sepolia", "protocol": "ethereum", "rpcUrls": [{ "http": "https://foobar.com" }] } ``` **A more detailed example in YAML:** ```yaml theme={null} # Yaml metadata example blockExplorers: - apiUrl: https://api-sepolia.etherscan.io/api family: etherscan name: Etherscan url: https://sepolia.etherscan.io blocks: confirmations: 1 estimateBlockTime: 13 reorgPeriod: 2 chainId: 11155111 deployer: name: Abacus Works url: https://www.hyperlane.xyz displayName: Sepolia domainId: 11155111 isTestnet: true name: sepolia nativeToken: decimals: 18 name: Ether symbol: ETH protocol: ethereum rpcUrls: - http: https://ethereum-sepolia.publicnode.com - http: https://ethereum-sepolia.blockpi.network/v1/rpc/public ``` If the origin or destination `domainId` of chains in your messages doesn't match their `chainId` then you must include the `domainId` field in your chain config. # Explorer Debugging Source: https://docs.hyperlane.xyz/docs/reference/explorer/explorer-debugging You'll know that a message failed to process because the message status near the top of the page will show as "Error" and the upper right section of the page will specify a reason why the message wasn't able to be processed. If your message was not delivered it can be due to several factors. ### Invalid Destination If the destination domain identifier (`uint32`) is not known to relay clients they will have no way to deliver your message. Refer to the [domains](../../reference/domains) for known domains and the canonical identifiers to use when sending messages to these destinations. ### Invalid Recipient If the recipient address (`bytes32`) is not a contract address that implements the `IMessageRecipient`, the relayer will not be able to deliver your message. ```solidity theme={null} // IMessageRecipient interface interface IMessageRecipient { function handle( uint32 _origin, bytes32 _sender, bytes calldata _message ) external; } ``` EVM addresses (`address`) must be left-padded with zeroes to be compliant. Refer to the [TypeCasts library](/docs/reference/developer-tools/libraries/typecasts) for a `pure addressToBytes32` utility function, and the message [dispatch](../../reference/messaging/send#dispatch) section for other details. ### Unprocessable If the gas estimation of the message recipient's `IMessageRecipient.handle()` function fails, [relayers](../../protocol/agents/relayer) will not be able to deliver the message. Relayers will continue to estimate gas for message delivery, as state changes may allow for successful delivery of a previously undeliverable message. If you have a use case which is not accommodated by this behavior, **please reach out** on [GitHub Discussions](https://github.com/hyperlane-xyz/hyperlane-monorepo/discussions). ### Underfunded An underfunded message implies the [interchain gas payments](../../reference/hooks/interchain-gas) made to deliver this message are insufficient. Relayers use the [`eth_estimateGas`](https://ethereum.github.io/execution-apis/api-documentation/) RPC on the destination chain to determine the absolute cost of relaying a message. If this amount exceeds the total amount of gas paid for on the origin chain, relayers will typically refuse to deliver a message. You can [manually pay for interchain gas](../../reference/hooks/interchain-gas#retrying) to resolve this. ## Using Etherscan You can also look at the [Etherscan](https://etherscan.io/) page of the recipient on the destination chain however be aware that the processing transaction won't show up on list of transactions as you would typically imagine. The reason for that is that relayers actually call the Mailbox contracts which in turn call the `handle` function on the recipient. Thus, you will find evidence of processing under the `Internal Txns` tab instead. # GraphQL API Source: https://docs.hyperlane.xyz/docs/reference/explorer/graphql-api The Hyperlane agents collect useful information about activity on the system, including all messages. That data can be queried via APIs. These APIs are currently available free of charge and without any required authentication. Connect your preferred GraphQL client or library to to query data! ### Example Query The following query will retrieve useful information about a message: ```graphql theme={null} query MyQuery { message_view(limit: 10, where: {msg_id: {_eq: "\xYOUR_MSG_ID"}}) { msg_id nonce sender recipient is_delivered message_body origin_mailbox origin_domain_id origin_chain_id origin_block_id origin_block_height origin_block_hash origin_tx_sender origin_tx_recipient origin_tx_nonce origin_tx_max_priority_fee_per_gas origin_tx_max_fee_per_gas origin_tx_id origin_tx_hash origin_tx_gas_used origin_tx_gas_price origin_tx_gas_limit origin_tx_effective_gas_price origin_tx_cumulative_gas_used destination_block_id destination_block_hash destination_block_height destination_chain_id destination_domain_id destination_mailbox destination_tx_cumulative_gas_used destination_tx_effective_gas_price destination_tx_gas_limit destination_tx_gas_price destination_tx_gas_used destination_tx_hash destination_tx_id destination_tx_max_fee_per_gas destination_tx_max_priority_fee_per_gas destination_tx_nonce destination_tx_recipient destination_tx_sender send_occurred_at delivery_occurred_at delivery_latency num_payments total_payment total_gas_amount } } ``` ### GraphQL Schema Types ````graphql theme={null} type message_view { msg_id: bytea nonce: Int! sender: bytea recipient: bytea is_delivered: Boolean! message_body: bytea origin_mailbox: bytea origin_domain_id: Int! origin_chain_id: Int! origin_block_id: Int! origin_block_height: Int! origin_block_hash: bytea origin_tx_sender: bytea origin_tx_recipient: bytea origin_tx_nonce: Int! origin_tx_max_priority_fee_per_gas: Int! origin_tx_max_fee_per_gas: Int! origin_tx_id: Int! origin_tx_hash: bytea origin_tx_gas_used: Int! origin_tx_gas_price: Int! origin_tx_gas_limit: Int! origin_tx_effective_gas_price: Int! origin_tx_cumulative_gas_used: Int! destination_block_id: Int! destination_block_hash: bytea destination_block_height: Int! destination_chain_id: Int! destination_domain_id: Int! destination_mailbox: bytea destination_tx_cumulative_gas_used: Int! destination_tx_effective_gas_price: Int! destination_tx_gas_limit: Int! destination_tx_gas_price: Int! destination_tx_gas_used: Int! destination_tx_hash: bytea destination_tx_id: Int! destination_tx_max_fee_per_gas: Int! destination_tx_max_priority_fee_per_gas: Int! destination_tx_nonce: Int! destination_tx_recipient: bytea destination_tx_sender: bytea send_occurred_at: timestamp! delivery_occurred_at: timestamp! delivery_latency: Int! num_payments: Int! total_payment: Int! total_gas_amount: Int! } type block { domain: Int! domainByDomain: domain! hash: String! height: bigint! id: bigint! time_created: timestamp! timestamp: timestamp! } type domain { chain_id: bigint id: Int! is_deprecated: Boolean! is_test_net: Boolean! name: String! native_token: String! time_created: timestamp! time_updated: timestamp! } type gas_payment { amount: numeric! domain: Int! domainByDomain: domain! id: bigint! msg_id: String time_created: timestamp! transaction: transaction! tx_id: bigint! } type transaction { block: block! block_id: bigint! checkpoint_updates: [checkpoint_update!]! cumulative_gas_used: float8! delivered_messages: [delivered_message!]! effective_gas_price: float8 gas_limit: float8! gas_payments: [gas_payment!]! gas_price: float8 gas_used: float8! hash: String! id: bigint! max_fee_per_gas: float8 max_priority_fee_per_gas: float8 messages: [message!]! nonce: bigint! recipient: String sender: String! time_created: timestamp! }``` ```` # Overview Source: https://docs.hyperlane.xyz/docs/reference/explorer/overview This guide can be used to find messages on any network with a Hyperlane deployment. Drill down into messages for more details about their properties and status. Messages to/from [core chains](/docs/reference/domains) will be searchable by transaction hash, message ID, or sender/recipient address. For other chains, the explorer can be configured to search for messages by providing it a chain config. ### Searching for messages The [Hyperlane Explorer](https://explorer.hyperlane.xyz/) supports searching for messages using any of the following values: * Hash of the transaction that initiated the message (origin tx) * Hash of the transaction that delivered message (destination tx) * Address of the account that sent the origin transaction * Address of the account that sent the destination transaction * Address of the message sender * Address of the message recipient * ID of the message To search, enter your query into the top search bar. You can use the Origin Chain, Destination Chain, and Time filter options to narrow down your search. Explorer search bar Note, by default the explorer will only find message on [core Hyperlane chains](/docs/reference/domains). To view messages sent to and/or from other chains, see [Configuring PI Chains](/docs/reference/explorer/configuring-pi-chains). ### Permissionless Interoperability[​](#permissionless-interoperability "Direct link to Permissionless Interoperability") The explorer can be configured to search for messages on any chain with a Hyperlane deployment. See [configuring PI Chains](/docs/reference/explorer/configuring-pi-chains) for details. ### Debugging Messages[​](#debugging-messages "Direct link to Debugging Messages") If you're trying to debug a problem with message delivery, the [explorer debugging](/docs/reference/explorer/explorer-debugging) page has useful tips. # Arbitrum L2 to L1 Hook Source: https://docs.hyperlane.xyz/docs/reference/hooks/arbitrum-L2-to-L1 Arbitrum's Outbox system allows for arbitrary L2 to L1 contract calls after the optimistic challenge period, i.e., messages initiated on the L2 chain which eventually resolve in execution on L1. See more details about [here](https://docs.arbitrum.io/how-arbitrum-works/arbos/l2-l1-messaging). Hyperlane can wrap around the Outbox system to leverage the optimistic security of Arbitrum L2 (with a 7-day withdrawal period and operational fraud proofs) to secure L2 to L1 messages from any Arbitrum Nitro rollups. We've implemented the [ArbL2ToL1Hook](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/hooks/ArbL2ToL1Hook.sol) and [ArbL2ToL1Ism](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/isms/hook/ArbL2ToL1Ism.sol). ## How it works Outgoing messages from L2 cannot provide in-protocol automatic L1 execution because Ethereum doesn't offer scheduled execution affordances through the L1 node. The `ArbL2ToL1Hook` sends the encoded function call with the `messageId` to the `ArbSys` precompile on the L2. After waiting for the withdrawal period, you can use the `getOutboxProof()` on the L2 to get a merkle proof of the message. From here, you have two options: * **Option A.** You can call the `ArbL2ToL1Ism`'s verify function via the `mailbox.process()` call with the proof and the other encoded data which in turn calls the `outbox.executeTransaction()` checking for the message sender and message data validity. * **Option B.** You can directly call the `outbox.executeTransaction()` with the proof and the other encoded data. However, you'll need to make a second call to the `ArbL2ToL1Ism`'s verify function to deliver the message. This option also you delivery of message values to the recipient contract. ### Option A ```mermaid theme={null} flowchart TB subgraph Origin L2 Sender M_O[(Mailbox)] Hook[ArbL2ToL1Hook] L_2[(ArbSys)] Sender -- "dispatch(...)" --> M_O M_O -- "postDispatch(message)" --> Hook Hook -- "sendMessage(messageId)" --> L_2 end M_O -. "process (relayer) after 7 days" .-> M_D L_2 -. "executeTransaction(3rd party relayer) after 7 days" .-> L_1 subgraph Destination L1 Recipient M_D[(Mailbox)] ISM{ArbL2ToL1Ism} L_1[(ArbOutbox)] M_D -- "verify(..., message)" --> ISM M_D -- "handle(...)" --> Recipient ISM -. "interchainSecurityModule()" .- Recipient L_1 -- "verifyMessageId(messageId)" --> ISM end style L_1 fill: #162c4f style L_2 fill: #162c4f ``` ### Option B Note: here, the relayer is responsible for encoding the message proof from `arbSys.getOutboxProof()` and calling the `outbox.executeTransaction()` function. ```mermaid theme={null} flowchart TB subgraph Origin L2 Sender M_O[(Mailbox)] Hook[ArbL2ToL1Hook] L_2[(ArbSys)] Sender -- "dispatch(...)" --> M_O M_O -- "postDispatch(message)" --> Hook Hook -- "sendMessage(messageId)" --> L_2 end M_O -. "process(relayer) after 7 days" .-> M_D M_O -. "getOutboxProof()" .-> L_2 subgraph Destination L1 Recipient M_D[(Mailbox)] ISM{ArbL2ToL1Ism} L_1[(ArbOutbox)] M_D -- "verify(..., message)" --> ISM M_D -- "handle(...)" --> Recipient ISM -. "interchainSecurityModule()" .- Recipient L_1 -- "verifyMessageId(messageId)" --> ISM end style L_1 fill: #162c4f style L_2 fill: #162c4f ``` # Post-Dispatch Interchain Gas Source: https://docs.hyperlane.xyz/docs/reference/hooks/interchain-gas Configure gas payments for cross-chain message delivery using InterchainGasPaymaster contracts During the post-dispatch hook, the `InterchainGasPaymaster` contract will revert if payment is insufficient to cover the relayer's *anticipated* costs. The gas quote calculated at `dispatch` time must align with the relayer's anticipated costs. ## Gas Limit The `gasLimit` is set based on the cost of calling `handle` on the destination chain for a given message. This can vary depending on message content and the logic of the handler. The default `gasLimit` for metering the handle call is a static default of `50_000` gas. This is sufficient for simple operations but may not be enough for more complex `handle` functions. If your `handle` function performs complex operations or requires more gas, you must override the [default `gasLimit` in metadata](#metadata) to avoid transaction reverts. Benchmark your [`handle` implementations](../messaging/receive#handle) in unit tests to determine a reasonable `gasLimit` to use. ### Metadata This hook expects metadata in a **packed encoding** of `StandardHookMetadata`. See the Mailbox [dispatch overloads](../messaging/send#overriding-default-hook-metadata) for how to pass metadata overrides. ```solidity theme={null} struct StandardHookMetadata { uint16 variant; uint256 msgValue; uint256 gasLimit; address refundAddress; } ``` The `StandardHookMetadata` struct defines the fields required for metadata encoding: * `variant`: Specifies the metadata format version. * `msgValue`: Amount of native token sent with the message. * `gasLimit`: Gas limit for the `handle` function on the destination chain. Ensure this matches your simulation results. * `refundAddress`: Address to refund unused gas payments. To encode this metadata, use the `StandardHookMetadata.formatMetadata` library function. Direct encoding of the struct with `abi.encodePacked` is not supported in Solidity. #### Example Usage ```solidity theme={null} // Example: Encoding metadata using StandardHookMetadata bytes memory metadata = StandardHookMetadata.formatMetadata( 0, // ETH message value 200000, // Custom gas limit address(this), // Refund address bytes("") // Optional custom metadata ); ``` ### Determine and Override the Gas Limit 1. **Simulate and Benchmark Gas Usage**: * Use tools like Tenderly or Foundry to simulate the `handle` function on your message recipient. Ensure the `from` address is set to the Mailbox contract on your chain. * If gas usage exceeds `50,000` gas, calculate an appropriate `gasLimit` and update your metadata. * Use the [call-to-action in the Hyperlane Explorer](https://github.com/hyperlane-xyz/hyperlane-explorer/blob/03634076049bfce1611b4e41d1aa81910eab2962/src/features/messages/cards/TransactionCard.tsx#L326-L333) to simulate transactions from the message details. 2. **Update Your Metadata**: * Calculate the required `gasLimit` based on the simulation. * Pass the updated `gasLimit` in your metadata to ensure the relayer will deliver your message. ## Destination Gas Config For each remote domain, the InterchainGasPaymaster sets the domain gas config. ```solidity theme={null} struct DomainGasConfig { IGasOracle gasOracle; uint96 gasOverhead; } ``` ### Gas overhead The gas overhead is set as part of the destination gas configuration. This corresponds to the operational cost of processing a message on the destination chain. * You should ensure the `gasOverhead` sufficiently covers the range of ISMs on your destination chain. - As you can configure different ISMs for different message types, you may have different gas overheads for each ISM's `verify` function. ## Gas Oracles Interchain Gas Payment requirements are calculated using oraclized gas prices and exchange rates between the origin and destination chains. IGP contracts may be configured with gas oracles, which are responsible for tracking remote token gas prices and exchange rates. Developers should use the [`quoteDispatch`](/docs/protocol/core/post-dispatch-hooks-overview#quote-dispatch-fees) function on the Mailbox contract to calculate gas fees. The `quoteDispatch` accounts for system-level overhead and ensures accurate fee calculation for the entire `dispatch` process. Exchange rates and gas prices are up to the relayer to decide. A spread may be charged to account for drift and operating costs. Eventually, a relayer will be able to automatically update their gas oracles in order to ensure that their IGP always quotes a fair price for remote gas. ### `getExchangeRateAndGasPrice` ```solidity theme={null} function getExchangeRateAndGasPrice( uint32 destinationDomain ) external view returns (uint128 tokenExchangeRate, uint128 gasPrice); ``` **Parameters** * `destinationDomain`: The message's destination domain **Returns** * `tokenExchangeRate`: The exchange rate between the origin and destination chain's gas tokens * `gasPrice`: The gas price for the destination chain ### `quoteGasPayment` The `quoteGasPayment` function calculates fees for the relayer's anticipated costs. ```solidity theme={null} function quoteGasPayment( uint32 destinationDomain, uint256 gasLimit ) external view returns (uint256 fee); ``` **Parameters** * `destinationDomain`: The message's destination domain * `gasLimit`: The gas limit to meter the `handle` call with **Returns** * `fee`: The payment required for the `postDispatch` to succeed The `quoteGasPayment` gives an estimated fee based on the `destinationDomain` and `gasLimit`. However, it does **not** include extra gas costs added by the Interchain Gas Paymaster (IGP) for the Default ISM payment. To get the full fee, use `quoteDispatch()` from the Mailbox contract. It provides a complete quote that includes these additional costs. 👉 See [Quote Dispatch](/docs/reference/messaging/send#quote-dispatch) for more details. ## Retrying If the `handle` call consumes more gas than quoted, the relayer will not submit a process transaction. This issue often occurs due to insufficient gas payment during the initial `dispatch`. In this case, additional gas can be paid for with the `payForGas` function. ```solidity theme={null} function payForGas( bytes32 messageId, uint32 destinationDomain, uint256 gasAmount, address refundAddress ) external payable; ``` **Parameters** * `messageId`: The message identifier returned from `dispatch` call * `destinationDomain`: The message's destination domain * `gasAmount`: The additional gas amount to pay for * `refundAddress`: The address to refund excess payment to ## Using the Hyperlane Explorer for Debugging The Hyperlane Explorer is a powerful tool to debug cross-chain message issues, including gas payments and relayer behavior. ### Key Features * **Message Status**: View the current status of your message (e.g., "Retry: GasPaymentRequirementNotMet"). * **Gas Payment Details**: Check the gas amount paid (Origin IGP gas amount) and the amount required by the relayer. * **Simulate Calldata**: Use the "View calldata details" option to simulate transactions on tools like Tenderly. ## Troubleshooting This section covers common issues developers encounter with Interchain Gas Payments, along with potential solutions. ### `GasPaymentRequirementNotMet` Warning * **Reason:** This occurs when the gas payment provided during `dispatch` does not meet the relayer's calculated requirement. * **Solution:** * Use `quoteDispatch` to calculate the aggregate fee required for a `dispatch` call to be successful. * Verify that `msg.value` in your metadata covers the relayer's quoted fee. * Check the message status in the Hyperlane Explorer. Look for: `Retry(GasPaymentRequirementNotMet)`. ### Fallback Routing and Overpayment Warning * **Reason:** `msg.value` exceeds the required gas payment, triggering the fallback routing hook. * **Solution:** * Verify that your quoting logic (`quoteDispatch`) matches the relayer's anticipated fees. * Avoid overestimating `gasLimit` values without first benchmarking the `handle` function. * Simulate the transaction to confirm appropriate payment. ### Unexpectedly Large Gas Quotes * **Reason:** A very high `gasLimit` was set, leading to excessively large gas quotes. * **Solution:** * Double-check the `gasLimit` specified in your metadata. * Verify that your quoting logic (`quoteDispatch`) matches the relayer's anticipated fees. * Adjust the `gasLimit` to match the estimated gas consumption of your `handle` function. # OP Stack Hook Source: https://docs.hyperlane.xyz/docs/reference/hooks/op-stack Optimism and other [OP Stack](https://stack.optimism.io/) rollups have their own interface for message passing between L1 and L2 called the `CrossDomainMessenger`. Messages passed via this interface benefit from the security of the rollup [settlement layer](https://stack.optimism.io/docs/understand/landscape/#execution). ```solidity theme={null} interface ICrossDomainMessenger { function sendMessage( address target, bytes calldata message, uint32 gasLimit ) external; } ``` To provide this security as an option in Hyperlane, we created a Hook and ISM combo that can be transparently configured to reuse the native OP Stack interface. See the [addresses](/docs/reference/addresses/deployments/mailbox) page for Hook and ISM addresses. ## How It Works The OPStackHook sends the messageId to the L1CrossDomainMessenger which registers it as an Optimism `TransactionDeposited` event with ETH deposit and message data which gets picked up by the rollup node. The rollup node calls the precompiled contract `L2CrossDomainMessenger`'s relayMessage function which in turn makes calls configured OptimismISM contract, setting the messageId in the verifiedMessageId's mapping to the original L1 sender (ie. the user). The relayer carries just the message with no metadata, waiting for the Optimism node to pick and make a storage write to Optimism and the message delivery is then verified. ```mermaid theme={null} flowchart TB subgraph Origin L1 Sender M_O[(Mailbox)] Hook[OPStackHook] L_1[(L1CrossDomainMessenger)] Sender -- "dispatch(...)" --> M_O M_O -- "postDispatch(message)" --> Hook Hook -- "sendMessage(messageId)" --> L_1 end M_O -. "relay" .-> M_D L_1 -. "rollup node" .-> L_2 subgraph Destination L2 Recipient M_D[(Mailbox)] ISM{OPStackISM} L_2[(L2CrossDomainMessenger)] M_D -- "verify(..., message)" --> ISM M_D -- "handle(...)" --> Recipient ISM -. "interchainSecurityModule()" .- Recipient L_2 -- "verifyMessageId(messageId)" --> ISM end style L_1 fill: #ff0402 style L_2 fill: #ff0402 ``` # Polygon PoS Hook Source: https://docs.hyperlane.xyz/docs/reference/hooks/polygon-pos Polygon PoS has their own interface for message passing between Ethereum and Polygon called the [`fx portal`](https://github.com/0xPolygon/fx-portal). Messages passed via this interface benefit from the security of the Polygon [state sync mechanism](https://docs.polygon.technology/pos/architecture/bor/state-sync/). To provide this security as an option in Hyperlane, we created a Hook and ISM combo that can be transparently configured to reuse the fx-portal interface. See the [addresses](/docs/reference/addresses/deployments/mailbox) page for Hook and ISM addresses. ## How It Works Polygon FX-Portal provide FxChild (FxChild.sol) and FxRoot (FxRoot.sol) as the main contracts on which the bridge works. It calls and passes data to user-defined methods on another chain without needing a mapping. The FxChild/FxRoot contract are provided and maintained by the polygon team. You can find the address of this contract in Polygon's [Fx-Portal repo](https://github.com/0xPolygon/fx-portal). The PolygonPosHook sends payloads with FxRoot. Validators will pick up the message and pass it to the other chain. You can find detailed state sync mechanism in [documentation](https://docs.polygon.technology/pos/how-to/bridging/l1-l2-communication/state-transfer/) `StateReceiver` at `0x0000000000000000000000000000000000001001` is allowed to call `onStateReceive` in FxChild contract. FxChild calls `processMessageFromRoot` in abstract `CrossChainEnabledPolygonChild` on which PolygonPosISM implements. `CrossChainEnabledPolygonChild` is maintained by [OpenZeppelin](https://docs.openzeppelin.com/contracts/4.x/api/crosschain#) ```mermaid theme={null} flowchart TB subgraph Origin Ethereum Sender M_O[(Mailbox)] Hook[PolygonPosHook] Eth[(FxRoot)] Sender -- "dispatch(...)" --> M_O M_O -- "postDispatch(message)" --> Hook Hook -- "sendMessage(messageId)" --> Eth end M_O -. "relay" .-> M_D Eth -. "validator node" .-> Polygon subgraph Destination Polygon PoS Recipient M_D[(Mailbox)] ISM{PolygonPosISM} Polygon[(FxChild)] M_D -- "verify(..., message)" --> ISM M_D -- "handle(...)" --> Recipient ISM -. "interchainSecurityModule()" .- Recipient Polygon -- "verifyMessageId(messageId)" --> ISM end style Eth fill: #ff0402 style Polygon fill: #ff0402 ``` # Receive a message Source: https://docs.hyperlane.xyz/docs/reference/messaging/receive How to handle and verify incoming interchain messages with Hyperlane's Mailbox contract To deliver interchain messages, the [relayer](/docs/operate/relayer/run-relayer) calls `Mailbox.process()`. This function takes as parameters the message to deliver, as well as arbitrary metadata that can be specified by the relayer. The `Mailbox` will pass the message and metadata to the recipient's Interchain Security Module (ISM) for verification. If the ISM successfully verifies the message, the `Mailbox` delivers the message to the recipient by calling `recipient.handle()`. See [`Message.sol`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/solidity/contracts/libs/Message.sol) for more details on Hyperlane message encoding ## Handle This function is called by the `Mailbox` contract when a message is received. To ensure only valid interchain messages are accepted, it is important to restrict [access control](#access-control) to the Mailbox address. ### Solidity ```solidity theme={null} function handle( uint32 _origin, bytes32 _sender, bytes calldata _messageBody ) external; ``` **Parameters** * `origin`: Domain of origin chain * `sender`: Address of sender on origin chain as bytes32 * `messageBody`: Raw bytes content of message body Sender addresses are left-padded to `bytes32` for compatibility with virtual machines that are addressed differently. The following utility is provided in the [`TypeCasts` library](/docs/reference/developer-tools/libraries/typecasts) for convenience. ```solidity theme={null} function bytes32ToAddress(bytes32 _bytes32) internal pure returns (address) { return address(uint160(uint256(_bytes32))); } ``` ### Access Control The `handle` function should be restricted to the Mailbox address if the contract should only accept calls from interchain messages. The following utility is provided in the [`MailboxClient` library](/docs/reference/developer-tools/libraries/mailbox-client) for convenience. ```solidity theme={null} modifier onlyMailbox() { require( msg.sender == address(mailbox), "MailboxClient: sender not mailbox" ); _; } ``` ### Examples ```solidity theme={null} function handle( uint32 _origin, bytes32 _sender, bytes calldata _messageBody ) external override onlyMailbox { lastSender = _sender; lastData = _messageBody; emit ReceivedMessage(_origin, _sender, _messageBody); } ``` ## Verify When a message is received, the Mailbox will verify security with an [Interchain Security Module](/docs/protocol/ISM/modular-security) before calling the message recipient's `handle`. ### Default Security To query the default ISM address, you can call the `defaultIsm` function. ### Modular Security To leverage Hyperlane's modular security, message recipients can specify a custom Interchain Security Module to **verify anything** about incoming messages. The Mailbox will defer to this ISM when specified. # Send a message Source: https://docs.hyperlane.xyz/docs/reference/messaging/send How to send interchain messages using Hyperlane's Mailbox.dispatch() function To send interchain messages, developers call `Mailbox.dispatch()`. This function takes as parameters the message contents, the destination chain ID, and the recipient address. Each message gets inserted as a leaf into an [incremental merkle tree](https://medium.com/@josephdelong/ethereum-2-0-deposit-merkle-tree-13ec8404ca4f) stored by the `Mailbox`. Hyperlane's proof of stake protocol uses this merkle tree to verify fraud proofs. ## Dispatch Calling this function dispatches a message to the destination domain and recipient. Hyperlane can only deliver messages to smart contracts that implement the `handle` function. See the [receive a message](./receive) documentation for more information. Depending on the [post-`dispatch` hook configuration](#post-dispatch-hook-config), some payment may be required. See the [`quoteDispatch`](#quote-dispatch) section for more information. ### Solidity ```solidity theme={null} function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody ) external payable returns (bytes32 messageId); ``` Recipient addresses are left-padded to `bytes32` for compatibility with virtual machines that are addressed differently. The following utility is provided in the [`TypeCasts` library](/docs/reference/developer-tools/libraries/typecasts) for convenience. ```solidity theme={null} function addressToBytes32(address _address) internal pure returns (bytes32) { return bytes32(uint256(uint160(_address))); } ``` ### Examples ```solidity theme={null} // send message from Ethereum to Polygon TestRecipient IMailbox mailbox = IMailbox("0xc005dc82818d67AF737725bD4bf75435d065D239"); bytes32 messageId = mailbox.dispatch{value: msg.value}( 137, "0x000000000000000000000000f90cB82a76492614D07B82a7658917f3aC811Ac1", bytes("Hello World") ); ``` ## Quote Dispatch Fees are often configured to cover Interchain Gas Payments (IGP) as well as protocol costs. These include transaction submission on the destination chain, security provisioning, and maintenance. To receive a quote for a corresponding `dispatch` call, you can query the `quoteDispatch` function. ```mermaid theme={null} flowchart TB subgraph Origin Chain Sender M_O[(Mailbox)] Sender <-- "fee = quoteDispatch(...)" --> M_O Sender -- "dispatch(...){fee}" --> M_O end ``` ### Solidity ```solidity theme={null} function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody ) external view returns (uint256 fee); ``` The quoted `fee` must be passed as value to the `dispatch` call to ensure it does not revert. ### Examples ```solidity theme={null} // quote sending message from Ethereum to Polygon TestRecipient IMailbox mailbox = IMailbox("0xc005dc82818d67AF737725bD4bf75435d065D239"); uint32 destination = 137; bytes32 recipient = "0x000000000000000000000000f90cB82a76492614D07B82a7658917f3aC811Ac1"; bytes memory body = bytes("Hello World"); uint256 fee = mailbox.quoteDispatch(destination, recipient, body); mailbox.dispatch{value: fee}(destination, recipient, body); ``` Underpayment to `dispatch` will revert. If you are composing hooks together, overpayment **may not be refunded** to the message sender. ## Post-Dispatch Hook Config There are two hooks configured on a Mailbox * `required`: invoked for all `dispatch` calls with value that covers the required fee * `default`: invoked (unless overridden) with remaining value after `required` hook ```mermaid theme={null} flowchart LR subgraph Origin Chain Sender M_O[(Mailbox)] R_H[RequiredHook] D_H[DefaultHook] Sender -- "dispatch(...){value}" --> M_O M_O -. "fee = quoteDispatch(...)" .- R_H M_O -- "postDispatch(...)
{fee}" --> R_H M_O -- "postDispatch(...)
{value - fee}" --> D_H end ``` ### Required Hook To query the required hook configuration, you can call the `requiredHook` function. ```solidity theme={null} function requiredHook() external view returns (IPostDispatchHook); ``` ### Default Hook To query the default hook configuration, you can call the `defaultHook` function. ```solidity theme={null} function defaultHook() external view returns (IPostDispatchHook); ``` To override the default hook with a custom hook in the `dispatch` call, see the [Hooks Reference](/docs/reference/hooks/interchain-gas). # Hyperlane Registries Source: https://docs.hyperlane.xyz/docs/reference/registries ## Overview Hyperlane can be deployed anywhere by anyone. But for those deployments to be useful, their details must be well known. Registries are collections of chain metadata, contract addresses, and other useful information for interacting with Hyperlane contracts and tools. There is a [canonical registry](https://github.com/hyperlane-xyz/hyperlane-registry) maintained by the Hyperlane core team. The CLI, the [Explorer](https://explorer.hyperlane.xyz), and other tools can use registry data. ## Canonical registry Metadata and artifacts for deployments done by the Hyperlane core team will be available here: [https://github.com/hyperlane-xyz/hyperlane-registry](https://github.com/hyperlane-xyz/hyperlane-registry) However, community members are encouraged to add their own deployments to this canonical registry. The steps to contribute are as follows: 1. Fork and clone the registry repository 2. Use the CLI and set the `--registry` flag to the local path of the cloned repository 3. Execute your commands as needed 4. Push your changes to your fork and create a pull request ## Custom registries As long as the registry conforms to the same layout and file schemas as the canonical registry, any GitHub repository URL or local file path can be used instead. The CLI has two command line arguments for configuring the registry it uses: * The `--registry` flag sets the primary registry and uses the default GitHub registry if not set * The `--overrides` flag sets an optional additional path which can be useful for forcing specific overrides of the default data, for example to use a different RPC URL in a chain's metadata. Once your custom registry additions/updates are complete and tested, consider opening a pull request to the canonical registry so that others can benefit from your deployments. For more information see the CLI reference page. ## Usage (Javascript & Typescript) ### Install ```bash theme={null} # With npm npm install @hyperlane-xyz/registry # Or with yarn yarn add @hyperlane-xyz/registry ``` ### Get Content #### Via the package (static) The simplest way to access the registry data would be to import the desired parts directly from the package: ```ts theme={null} // Via the base package import { ethereum, ethereumAddresses } from "@hyperlane-xyz/registry"; // Or via sub-exports for more optimal bundles if your bundler allows it import { metadata, addresses } from "@hyperlane-xyz/registry/chains/ethereum"; ``` #### Via the utilities (dynamic) If you need to ensure you have the latest data, registry content can be fetched on-the-fly with the `GithubRegistry` class. ```ts theme={null} import { GithubRegistry } from "@hyperlane-xyz/registry"; const registry = new GithubRegistry(); const chainMetadata = await registry.getMetadata(); ``` # Audits Source: https://docs.hyperlane.xyz/docs/resources/audits ### Hyperlane Q2 2025 Security Audit [Original](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/ChainLight_Hyperlane_2Q_2025_Security_Audit_v1.0.pdf?raw=true) ### HyperToken Audit [Original](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/ChainLight_Hyperlane_HyperToken_Security_Audit_v1.0.pdf?raw=true) ### Yield Routes Audit [Original](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/ChainLight_Hyperlane_PR_5752_5757_Security_Audit_v1.0.pdf?raw=true) ### Compound Staker Rewards Audit [Original](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/Offbeat_Security_Hyperlane_Compound_Staker_Rewards.pdf?raw=true) ### USDT Audit [Original](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/ChainSecurity_Hyperlane_Superchain_USDT_audit_draft.pdf?raw=true) ### CCIP Audit [v5.12.0](https://github.com/hyperlane-xyz/hyperlane-monorepo/releases/tag/%40hyperlane-xyz%2Fcore%405.12.0) [Original](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/ChainLight_Hyperlane_CCIP_Warp_Route_Security_Audit_v1.1.pdf?raw=true) ### Hook and ISM Audit [Mirror](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/chainlight-v3.1-protocol-audit.pdf?raw=true) ### Protocol v3 Audit [Original](https://github.com/trailofbits/publications/blob/master/reviews/2023-09-hyperlane-securityreview.pdf) [Mirror](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/hyperlane-v3-protocol-audit.pdf?raw=true) ### Protocol v2 Audit [Original](https://audits.hacken.io/hyperlane/sca-hyperlane-interchain-message-service-apr2023/) [Mirror](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/hyperlane-v2-protocol-audit.pdf?raw=true) ### Protocol v1 Audit [Original](https://www.fyeo.io/post/fyeo-security-assessment-of-the-hyperlane-formerly-abacus-smart-contracts-in-august-2022) [Mirror](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/hyperlane-v1-protocol-audit.pdf?raw=true) ### Sealevel Protocol Audit [Original](https://github.com/sec3-service/reports/blob/master/reports/sec3_hyperlane-sealevel.pdf) [Mirror](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/sealevel-hyperlane-audit.pdf?raw=true) ### Sealevel Audit - Sherlock [Original](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/sealeval-audit-hyperlane-20250327.pdf?raw=true) ### CosmWasm Protocol Audit [Original](https://github.com/oak-security/audit-reports/blob/main/Hyperlane/2024-02-13%20Audit%20Report%20-%20cw-hyperlane%20v1.0.pdf) [Mirror](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/cw-hyperlane-audit.pdf?raw=true) ### Starknet Protocol Audit [Original](https://github.com/hyperlane-xyz/v4-docs/blob/main/assets/starknet-hyperlane-audit-draft.pdf?raw=true) # Frequently Asked Questions Source: https://docs.hyperlane.xyz/docs/resources/faq ## General Questions **What is Hyperlane?** Hyperlane is the first universal and permissionless interoperability framework built for the modular blockchain stack. Anyone can [deploy Hyperlane](/docs/guides/chains/deploy-hyperlane) to any blockchain environment, whether it is a layer 1, rollup, or app-chain, allowing that chain to communicate seamlessly with any other chain on which Hyperlane has been deployed. **What are the benefits of using Hyperlane for blockchain developers?** Hyperlane offers benefits for both blockchain and dapp developers. * For blockchain developers, a Hyperlane deployment expands accessibility to users, assets, and valuable state from other connected blockchains on which Hyperlane has been deployed. * For dapp developers, Hyperlane provides seamless connectivity across multiple blockchains, allowing developers to create interchain network effects and liquidity and users to interact with applications from their preferred chain. **What is Abacus Works?** Abacus Works is the name of a legal identity working on Hyperlane. You may encounter some references to Abacus in older posts and repositories. Hyperlane rebranded from Abacus to Hyperlane in Fall 2022. **What can I build with Hyperlane?** Hyperlane's [messaging interface](/docs/protocol/core/mailbox) allows dapp developers to send arbitrary bytes between smart contracts on different chains. This can be used to create interchain applications, dapps which span multiple chains. For inspiration, take a look at some of the pre-built applications built on top of Hyperlane, including: * **Hyperlane Warp Routes (HWR)**: Lets users move tokens from one chain to another. * **Interchain Accounts**: Lets users make interchain function calls. * **Interchain Queries**: Lets users make interchain view calls. **I'm a developer. How can my team build with Hyperlane?** If you're reading this FAQ, you've found the docs which is a great place to start. That said, we know that questions arise during implementation, and we're happy to help you on your way. The Hyperlane community is regularly active in [GitHub Discussions](https://github.com/hyperlane-xyz/hyperlane-monorepo/discussions). Feedback from developers directly influences the product roadmap. ## Technical Questions ### Messaging **What happens when I send a message on Hyperlane?** See the [send](/docs/reference/messaging/send) and [receive](/docs/reference/messaging/receive) pages for more details. In summary: 1. An application calls the `dispatch()` function on the origin chain, inserting the message into the Mailbox's Merkle tree. 2. A Hyperlane Relayer observes the dispatched messages and assembles metadata for the recipient's Interchain Security Module (ISM). 3. A relayer delivers the message to the recipient by calling `Mailbox.process()`. 4. The Mailbox verifies the message with the recipient’s ISM and calls `recipient.handle()` to deliver the message. **How can I see the status of a message I have sent?** Paste an address or transaction hash into the search bar of the [Hyperlane Message Explorer](https://explorer.hyperlane.xyz/) to view details about a message’s status and history. If the message has failed to send for some reason, there will be error messages indicating what may have gone wrong. See [Explorer Debugging](/docs/reference/explorer/explorer-debugging) for more information. **Does sending interchain messages with Hyperlane mean live chat & text?** No, Hyperlane is a protocol designed to allow smart contracts on different chains to interact with each other. When we refer to message-passing, it’s the sending of arbitrary bytes between smart contracts rather than peer-to-peer or text messaging. For chat use cases, consider [XMTP](https://xmtp.org/), [Push](https://push.org/), or [Orbis](https://useorbis.com/). **Is Hyperlane a token bridge?** Not exactly. Hyperlane is a general message passing (GMP) protocol that allows communication between blockchains. Token bridges are just one of many types of applications that can be built on top of Hyperlane! ### Deployment **Where is Hyperlane deployed?** A list of known deployments can be found on the [contract addresses](/docs/reference/addresses/deployments/mailbox) page. ### Advanced Topics **How is Hyperlane secured?** Hyperlane is secured by its modular security stack featuring Interchain Security Modules (ISMs). Developers can configure various pre-built ISMs, compose them with each other, or even create custom ISMs based on their application's needs. A modular approach to security ensures that Hyperlane will continue to stay up to the latest industry advances in security models. **How many validators does Hyperlane have, and who operates them?** The number of validators depend on the Interchain Security Module (ISM) configuration. The Default ISM uses a specific validator set, and you can view the details such as threshold, operator and address [here](/docs/reference/addresses/validators/mainnet-default-ism-validators). **How can we ensure message integrity?** Hyperlane's message security is driven by the Interchain Security Module (ISM) configuration. By default, messages rely on the Default ISM's validator set, which requires a quorum of validators to sign for security. In the unlikely event of a validator compromise, the security of messages could be impacted. However, developers have the flexibility to configure their own ISM, enabling them to customize and strengthen the security model to suit their application's needs. **Does the source chain receive confirmation whether the transaction was executed on the destination chain?** Currently, the source chain does not automatically receive a confirmation of execution from the destination chain. However, this functionality can be added by customizing the `handle` function on the destination chain. For more information, refer to the [handle function](/docs/reference/messaging/receive#handle). **Why are outbound message IDs stored in the Merkle tree?** Outbound message IDs are stored in the Merkle tree to efficiently track and verify messages. This mechanism ensures validators can accurately detect and sign new messages as they are created. **`Why do validators call MerkleTreeHook.latestCheckpoint()?`** Validators use the [`MerkleTreeHook.latestCheckpoint()`](https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/5e9b8ba7ab0f54e92b3cf32806fae95eb23ad0f8/solidity/contracts/hooks/MerkleTreeHook.sol#L49) function to determine when new transactions need to be indexed. This polling mechanism ensures validators can immediately start signing new messages without the need to backfill the entire tree. ## Community & Contributions[​](#community--contributions) **How can I join the Hyperlane community?** You can join [GitHub Discussions](https://github.com/hyperlane-xyz/hyperlane-monorepo/discussions) or follow Hyperlane on [Twitter](https://x.com/hyperlane), where you can find a growing community of developers and enthusiasts to chat about the interchain future. **I'm interested in working on Hyperlane. Where can I see job openings?** Check out our open roles [here](https://jobs.lever.co/Hyperlane). **How can I contribute to improve this documentation?** You can make a PR to edit this documentation directly via the [docs repo](https://github.com/hyperlane-xyz/v3-docs). **Where can I get support or ask questions about Hyperlane?** You can get support and ask questions on [GitHub Discussions](https://github.com/hyperlane-xyz/hyperlane-monorepo/discussions), where the community and team are active and ready to assist. # Glossary Source: https://docs.hyperlane.xyz/docs/resources/glossary ## Agent Hyperlane [agents](/docs/protocol/agents) are off-chain actors that read and write Hyperlane smart contract state. Example agents include [Validators](/docs/protocol/agents/validators) and the [Relayer](/docs/protocol/agents/relayer). ## Aggregation ISM The [Aggregation ISM](/docs/protocol/ISM/standard-ISMs/aggregation-ISM) is a type of interchain security module that aggregates security from many [ISMs](/docs/resources/glossary#interchain-security-module) by requiring that `m` of `n` ISMs verify a particular interchain message. ## Checkpoint A checkpoint is a (merkle root, index) tuple, corresponding to the state of the [Mailbox](/docs/resources/glossary#mailbox) incremental merkle tree at a particular point in time. Checkpoints signatures by [Validators](/docs/resources/glossary#validator) are used in [Multisig ISMs](/docs/resources/glossary#multisig-ism). ## Collateral chain For a [Hyperlane Warp Route](/docs/resources/glossary#warp-route), the chain on which the [collateral token](/docs/resources/glossary#collateral-token) is deposited into the Warp Route. ## Collateral token For a [Hyperlane Warp Route](/docs/resources/glossary#warp-route), the token which is deposited on the [collateral chain](/docs/resources/glossary#collateral-chain) to create a wrapped token on a remote [synthetic chain](/docs/resources/glossary#synthetic-chain). ## Default ISM The [Interchain Security Module](/docs/resources/glossary#interchain-security-module) that will be used to verify inbound messages if the message recipient has not specified their own ISM. ## Domain A unique identifier for a particular chain, used by the Hyperlane protocol to determine message origin and destination. Maybe the same as the EVM chain ID, but isn't always. See [domains](/docs/reference/domains/) for a list of known Hyperlane domain IDs. ## Interchain accounts (ICA) A [middleware](/docs/resources/glossary#middleware) smart contract that allows users to make interchain smart contract calls. For example, DAOs can use interchain accounts to own contracts on remote chains. See [Interchain Accounts](docs/applications/interchain-account) for more information. ## Interchain gas paymaster A smart contract deployed by a [Relayer](/docs/resources/glossary#relayer) that accepts payments on an origin chain for message delivery on destination chains. See [interchain gas payments](docs/protocol/core/interchain-gas-payment) for more information ## Interchain queries (IQS) A [middleware](/docs/resources/glossary#middleware) smart contract that allows users to make interchain view calls. For example, smart contracts can use interchain queries to look up oracle exchange rates or token balances from a remote chain. ## Interchain Security Module (ISM)[​](#interchain-security-module-ism "Direct link to Interchain Security Module (ISM)") [Interchain Security Module](/docs/protocol/ISM/modular-security) (ISMs) are smart contracts that provide security to Hyperlane's interchain [Mailbox](/docs/protocol/core/mailbox). ISMs are responsible for verifying that interchain messages being delivered on the destination chain were *actually sent* on the origin chain. ## Mailbox Arguably the most important Hyperlane smart contract, the [mailbox](docs/protocol/core/interchain-gas-payment) exposes an interface that developers can use to [send](/docs/reference/messaging/send) and [receive](/docs/reference/messaging/receive) interchain messages. ## Middleware[​](#middleware "Direct link to Middleware") A smart contract that sends and receives messages, and exposes a developer facing API. Developers are expected to use this API instead of interacting directly with the [mailbox](/docs/resources/glossary#mailbox). Example middlewares include [interchain-accounts-ica](/docs/resources/glossary#interchain-accounts-ica) and [interchain-queries-iqs](/docs/resources/glossary#interchain-queries-iqs). ## Multisig ISM The [Multisig ISM](/docs/protocol/ISM/standard-ISMs/multisig-ISM) is a type of [Interchain Security Module](/docs/resources/glossary#interchain-security-module) that uses `m` of `n` [Validator](/docs/resources/glossary#validator) signatures in order to verify a particular interchain message. ## Permissionless Interoperability[​](#permissionless-interoperability "Direct link to Permissionless Interoperability") Hyperlane can be deployed by anyone to any chain, whether it is a layer 1, rollup, or app-chain, allowing that chain to communicate seamlessly. The open design of the Hyperlane protocol is known as Permissionless Interoperability (PI). Chains deployed by institutions other than the Hyperlane core team are referred to as 'PI chains'. ## Relayer The [Relayer](/docs/protocol/agents/relayer) is a Hyperlane [agent](/docs/resources/glossary#agent) responsible for delivering messages from their origin chain(s) to their destination chain(s). Relayers are untrusted, and anyone can operate a relayer. ## Routing ISM The [Routing ISM](/docs/protocol/ISM/standard-ISMs/routing-ISM) is a type of [Interchain Security Module](/docs/resources/glossary#interchain-security-module) that defers to a different ISM depending on the message being delivered. For example, a Routing ISM could use a different ISM depending on the origin chain from which the message was sent. ## Synthetic chain For a [Hyperlane Warp Route](/docs/resources/glossary#warp-route), a chain on which wrapped tokens are minted. These wrapped tokens are backed by [collateral tokens](/docs/resources/glossary#collateral-token) that have been locked on the [collateral chain](/docs/resources/glossary#collateral-chain). ## Validator [Validators](/docs/protocol/agents/validators) are a Hyperlane [agents](/docs/resources/glossary#agent) responsible for attesting to messages sent from an origin chain. [Multisig ISMs](/docs/resources/glossary#multisig-ism) use validator signatures to provide security for inbound messages. ## Hyperlane Warp Route [Hyperlane Warp Routes](/docs/applications/warp-routes/overview) are Hyperlane's take on the concept of token bridging, allowing you to permissionlessly transfer any ERC20-like asset to any chain via Hyperlane. Read more about how to [deploy a Hyperlane Warp Route](/docs/guides/quickstart/deploy-warp-route). # Message Debugging Source: https://docs.hyperlane.xyz/docs/resources/message-debugging ### * EVM Origin * Cosmos Origin The easiest way is to use the [Hyperlane Explorer](https://explorer.hyperlane.xyz), if your chain is supported. If your chain isn't supported, the message ID can be found by looking at the originating transaction. When viewing the origin transaction on the origin chain's block explorer, navigate to the **Logs** tab. The **`DispatchId`** log contains the message ID as the topic number 1 (the second topic). Sometimes, chain block explorers won't show the human-friendly "DispatchId" name. In this case, you can find the log by it's topic 0: `0x788dbc1b7152732178210e7f4d9d010ef016f9eafbe66786bd7169f56e0c353a`. Example on Arbiscan showing the DispatchId log on an origin transaction. When viewing the origin transaction on the origin chain's block explorer, navigate to the **Event Logs** tab. The **Wasm Mailbox Dispatch Id** log contains the message ID. Example on Mintscan showing the log on an origin transaction. At the moment, the [Hyperlane Explorer](https://explorer.hyperlane.xyz) doesn't support non-EVM chains. To check if your message has been delivered, select the destination chain and input your message ID below: Destination Chain: neutron * [neutron](<#Destination Chain=neutron>) * [injective](<#Destination Chain=injective>) Message ID: 0x... Check if delivered We can debug this with two steps: **Verifying if the funds were received:** * EVM Destination * Cosmos Destination 1. Open the block explorer for the destination chain, and navigate to your expected recipient address. 2. If you expect to receive a token (e.g. an ERC-20), check the Token Transfers tab for the token being transferred to your address. 3. If you expect to receive the native token (e.g. ETH, on Ethereum), check the "Internal Transactions" tab for the native token being transferred to your address. 4. Open the block explorer for the destination chain, and navigate to your expected recipient address. 5. View your "Coins" or "Tokens" tab, and look for the expected balance. 6. If it's not clear if your balance is what you expect, the check the list of transactions. Look for any transactions that include "Process". **Verifying the recipient of your transfer** * EVM Origin * Cosmos Origin When viewing the origin transaction on the origin chain's block explorer, navigate to the **Logs** tab. The **`SentTransferRemote`** log contains the recipient as the topic number 1 (the second topic). Sometimes, chain block explorers won't show the human-friendly "SentTransferRemote" name. In this case, you can find the log by it's topic 0: `0xd229aacb94204188fe8042965fa6b269c62dc5818b21238779ab64bdd17efeec`. The recipient address is the account on the destination chain that will receive the warped tokens. Zeroes are padded to the left of the address if needed. If your destination chain is an EVM chain, the log will display `0x0000000000000000000000ffffffffffffffffffffffffffffffffffffffff` to mean that `0xffffffffffffffffffffffffffffffffffffffff` is the transfer recipient. If your destination chain is a Cosmos chain, you can take the hexadecimal content and convert it to a bech32 address using tools like [this one](https://www.bech32converter.com). Some Cosmos chains have different address lengths, so be conscious of how many characters to copy in. Example on Arbiscan showing the DispatchId log on an origin transaction. When viewing the origin transaction on the origin chain's block explorer, navigate to the **Event Logs** tab. The log including **Transfer Remote** contains the message ID, for example: `Wasm Hpl Warp Native Transfer Remote`. The recipient address is the account on the destination chain that will receive the warped tokens. Zeroes are padded to the left of the address if needed. If your destination chain is an EVM chain, the log will display `0x0000000000000000000000ffffffffffffffffffffffffffffffffffffffff` to mean that `0xffffffffffffffffffffffffffffffffffffffff` is the transfer recipient. If your destination chain is a Cosmos chain, you can take the hexadecimal content and convert it to a bech32 address using tools like [this one](https://www.bech32converter.com). Some Cosmos chains have different address lengths, so be conscious of how many characters to copy in. Example on Mintscan showing the log on an origin transaction. Sometimes browser extension wallets can contend with one another, and the address of a wallet you don't typically use takes precedence over your intended wallet. We've seen this happen a few times with **OKX Wallet**. Please check all your wallet addresses for your recipient address. Using the [Hyperlane CLI](/docs/reference/developer-tools/cli), it's possible to relay your message yourself if it's between two EVM chains. 1. Set up the CLI locally following [these instructions](/docs/reference/developer-tools/cli). 2. Find your message ID following the [above instructions](#finding-a-message-id-from-an-origin-transaction) 3. Obtain a private key for an account with funds on your destination chain. 4. Run the command to relay the message: ``` HYP_KEY= hyperlane status --relay --origin --destination --id ``` For example: ``` HYP_KEY=0xffff00000000000000000000000000000000000000000000000000000000ffff hyperlane status --relay --origin base --destination blast --id 0xabcd00000000000000000000000000000000000000000000000000000000abcd ``` If the above steps haven't helped, you can create a new post in [GitHub Discussions](https://github.com/hyperlane-xyz/hyperlane-monorepo/discussions). # Introduction Source: https://docs.hyperlane.xyz/index Welcome to the Hyperlane Documentation. Explore our tools, guides and references for building cross-chain applications. Hero Dark ## QuickStart Quickly deploy Hyperlane to a new chain Transfer assets across chains Step-by-step guide to running a Hyperlane Validator Explore the components and architecture ## What can you build? Use Hyperlane Warp Routes to bridge between chains Send arbitrary data and function calls across chains. Enable an account on the origin chain to make authenticated calls to contracts on another