feat(solidity): Axelar Hook and ISM (closes #2851)#8913
Draft
Utkarsh-Sinha0 wants to merge 2 commits into
Draft
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat(solidity): Axelar Hook and ISM (closes #2851)
Summary
Adds a message Hook and Interchain Security Module that transport a
Hyperlane message ID over Axelar's General Message Passing (GMP).
AxelarHook(origin chain) — onpostDispatch, pre-pays the Axelar GasService in native tokens and calls
IAxelarGateway.callContract, carrying apayload that invokes
preVerifyMessage(messageId, 0)on the destination ISM.AxelarIsm(destination chain) — inheritsAxelarExecutable; thegateway-validated
executeentrypoint authorizes the delivery by Axelarsource chain + source address, then records verification.
This mirrors the existing
OPStackHook/OPStackIsmpair, reusingAbstractMessageIdAuthHookandAbstractMessageIdAuthorizedIsmso it slotsinto the standard hook/ISM machinery with no Mailbox changes.
Before / After
Condition — before this PR: Hyperlane had no way to transport a message ID
over Axelar GMP. A route that wanted Axelar-secured verification could not be
expressed: there was no Axelar hook to emit the cross-chain call on the origin,
and no Axelar ISM to attest the message on the destination. (Bridge hook/ISM
pairs existed for OP Stack, CCIP, etc. — but not Axelar.)
Condition — after this PR: Dispatching through
AxelarHookpays Axelar gasand emits
gateway.callContract; Axelar relays it;AxelarIsm.executeverifiesthe message on the destination, after which the Mailbox can
processit. Axelarbecomes a usable transport for the standard message-ID auth hook/ISM flow.
AxelarHook+AxelarIsmExternalBridgeTestsuite + Axelar-specific)msgValuerejected)Acceptance conditions (definition of done):
forge buildcompiles onmaintoolchain (solc 0.8.33 / cancun)forge test --match-contract AxelarIsmTestall greenforge coverageshows 100% line + branch onAxelarHookandAxelarIsmDesign
Gas accounting (per the maintainer's suggestion in #2851)
The exact Axelar GMP gas cost cannot be computed on-chain — it depends on
destination gas price and token exchange rates resolved by Axelar's off-chain
gas oracle. Following the maintainer's "over-pay and let Axelar refund" hint,
quoteDispatchreturns0and the caller instead attaches native value whendispatching. The hook forwards the entire attached value to
payNativeGasForContractCall(an over-payment), and Axelar refunds the surplusoff-chain to the metadata refund address. Under-payment does not lose funds — it
simply stalls relaying until more gas is added via the Axelar Gas Service. A
0quote also keeps the hook compatible with the sharedExternalBridgeTestharness (which, like
OPStackHook, assumes a zero protocol-charged quote).Authorization / trust model
AxelarExecutable.executeasks the gateway (validateContractCall) to confirmthe Axelar network approved this exact
(commandId, sourceChain, sourceAddress, payloadHash)delivery.AxelarIsm._executethen enforces:sourceChainequals the configured trusted origin chain (originChainHash);sourceAddressequals the configuredauthorizedHook;preVerifyMessagecall (selector check, defense-in-depth).Because authorization comes from Axelar's validated call arguments rather than
msg.sender,preVerifyMessageis reached via a self-call guarded by atransient
_verifyingflag, so its_isAuthorized()check can only pass insidea gateway-validated, source-authorized
execute. Direct external calls topreVerifyMessagerevert. Source addresses are compared as parsedaddressvalues (not raw strings), making authorization robust to hex casing.
No native-value bridging
Axelar GMP does not deliver native value to the destination contract. To avoid
silently stranding funds, the hook rejects any non-zero
metadata.msgValue, andthe ISM always records
msgValue == 0.Dependencies
Minimal Axelar interfaces (
IAxelarGateway,IAxelarGasService,IAxelarExecutable), a smallAxelarExecutablebase, and theAddressStringlibrary are vendored under
contracts/interfaces/axelar/, consistent withhow this repo vendors other bridge interfaces (e.g.
interfaces/optimism).Function selectors are identical to the canonical
@axelar-network/axelar-gmp-sdk-solidity, so the contracts are ABI-compatiblewith the deployed Axelar contracts. If maintainers prefer the upstream
dependency, the vendored files can be swapped for SDK imports with no change to
AxelarHook/AxelarIsm.Files
contracts/hooks/AxelarHook.solcontracts/isms/hook/AxelarIsm.solcontracts/interfaces/axelar/*contracts/mock/MockAxelar.soltest/isms/AxelarIsm.t.solExternalBridgeTest)script/AxelarHookDeployer.s.sol.changeset/axelar-hook-and-ism.mdTesting
The suite extends
ExternalBridgeTest(the shared hook/ISM harness used byOPStackIsm) and adds Axelar-specific tests covering: constructor validation(hook + ISM),
quoteDispatch/postDispatchvalue rejection, gas-servicepre-payment, gateway-not-approved, untrusted source chain/address, payload
validation (short payload + wrong selector), replay rejection, direct
preVerifyMessagerejection, and theAddressStringround-trip + revert paths.Target: 100% line/branch coverage on the new contracts.
Demo (testnet)
<hash><link>executetx:<hash>Checklist
OPStackhook/ISM conventions@hyperlane-xyz/core)forge test+forge coveragegreen locallyTest results ✅
Toolchain:
forge(Foundry) + solc 0.8.33 / evm cancun (persolidity/foundry.toml).Coverage (
FOUNDRY_PROFILE=coverage forge coverage --match-contract AxelarIsmTest --no-match-coverage "(test|mock|script)/"):All new contracts are at 100% line/statement/branch/function coverage.
Demo (testnet tx hashes) — TODO
Issue #2851 requests a testnet/mainnet demo with tx hashes. These will be
captured via
RUNBOOK_testnet_demo.md(needs funded testnet keys + RPC URLs)and added here before the PR is marked ready for review.