mcpField
A
axelar-gmp

axelar-gmp

github.com/hedera-devDevelopment28474 installsUpdated 8w ago
Repository

About axelar-gmp

axelar-gmp is an implementation guide for Hedera smart contract developers building with Axelar GMP. It covers cross-chain messaging and authorization, and separates bridge transport from business logic while describing coordination with HSS.

Key features

  1. 01Axelar GMP send and receive flow
  2. 02Pay native gas before Gateway calls
  3. 03Source chain and address allowlisting
  4. 04Separate transport from business logic
  5. 05Coordinate with Hedera HSS scheduling

Use cases

  1. 01Implement cross-chain messaging for Hedera contracts
  2. 02Validate source chains and addresses at receivers
  3. 03Build HSS-scheduled recurring bridge tasks

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/hedera-dev/hedera-skills --skill axelar-gmp

After installing, type/axelar-gmpin Claude Code to confirm it loaded.

Bundled filesreferences/examples.mdreferences/hedera-axelar.md

Details

From the project README

Axelar GMP (Hedera)

GMP pattern: encode a payload on the source chain, pay Axelar gas in native token, call the Gateway, then decode and act on the destination behind an allowlisted source.

Source app → BridgeSender (pay gas + gateway.callContract)
                 → Axelar relayers
                      → AxelarExecutable._execute → Handler

On Hedera, orchestration often pairs GMP with HSS (0x16b) so a contract can self-reschedule and dispatch each cycle. Keep bridge transport behind a thin sender interface so the orchestrator stays bridge-agnostic.

Quick Reference

PieceRole
IAxelarGatewaycallContract(destChain, destAddress, payload)
IAxelarGasServicepayNativeGasForContractCall{value} before the gateway call
AxelarExecutableDestination base; override _execute(...)
Chain namesAxelar string IDs — e.g. "hedera", "ethereum-sepolia" (not numeric chain IDs)
AddressesEVM string form of the peer contract (checksummed 0x…)

See references/hedera-axelar.md for chain-name conventions and SDK imports. See references/examples.md for sender / receiver sketches.

Critical: Gas Then Gateway

Always pay gas before callContract. Use msg.value > 0 for relay fees; refund address should be the funded orchestrator (or plan owner), not a random EOA.

gasService.payNativeGasForContractCall{ value: msg.value }(
    address(this),       // sender contract
    destinationChain,    // Axelar name string
    destinationAddress,  // receiver 0x… as string
    payload,
    refundAddress        // usually authorizedCaller / orchestrator
);
gateway.callContract(destinationChain, destinationAddress, payload);

Critical: Authorize And Allowlist

SideGuard
Source senderOnly authorizedCaller (orchestrator) may send
Destination receiverValidate srcChain + srcAddress (case-insensitive) before handling
Destination handlerOnly the receiver may call business logic (authorizedCaller)

Compare Axelar chain/address strings with a shared lowercase hash — Axelar may vary casing.

require(
    keccak256(bytes(_toLower(srcChain))) == keccak256(bytes(_toLower(expectedSourceChain))),
    "invalid source chain"
);
require(
    keccak256(bytes(_toLower(srcAddress))) == keccak256(bytes(_toLower(expectedSourceAddress))),
    "invalid source address"
);

Architecture: Split Transport From Business Logic

Source chain                    Destination chain
─────────────────────────────   ─────────────────────────────
Orchestrator ──send──►          MessageReceiver (_execute)
     │ BridgeSender iface              │ Handler iface
BridgeSender                    Handler (swap / settle / …)
  1. Deploy handler first (no bridge knowledge).
  2. Deploy receiver with gateway + expected source + handler.
  3. Deploy sender with gateway + gas service + destination chain/address.
  4. Deploy orchestrator with sender address; authorize orchestrator on sender.
  5. Wire after both deploys: set destination on sender; set expected source on receiver.
  6. Fund orchestrator (native for Axelar gas) and handler (tokens/capital for destination work).

Payload Contract

Agree a single ABI encode/decode on both sides. Keep payloads versionable if you evolve fields — mismatched decode bricks the route.

bytes memory payload = abi.encode(/* agreed fields… */);
// receiver:
(/* fields… */) = abi.decode(payload, (/* matching types… */));

Hedera Orchestration Hook (HSS)

When the source app schedules itself via HSS (0x16b), each cycle should:

  1. Enforce interval / plan active
  2. Call the bridge sender with native value for Axelar gas
  3. Reschedule next expiry with hasScheduleCapacity + scheduleCall (SUCCESS = 22)

If scheduling fails, mark a recovery flag and expose a manual reschedule for the plan owner.

Checklist

  • Gas paid with native value before callContract
  • Destination chain name matches Axelar’s ID (string, not numeric chain ID)
  • Peer addresses set after both contracts deploy (wire step)
  • Source allowlist + authorized callers on both ends
  • Payload encode/decode identical
  • Orchestrator funded for relay gas; destination handler funded for work
  • Demo vs production: clarify who owns destination proceeds

References

Comments

Markdown supported