axelar-gmp
Axelar General Message Passing (GMP) on Hedera. Use when sending or receiving cross-chain contract calls via Axelar Gateway (callContract, payNativeGasForContractCall), building AxelarExecutable receivers, wiring Hedera↔EVM destinations, or separating bridge transport from destination handlers (orchestrated / scheduled flows).
How do I install this agent skill?
npx skills add https://github.com/hedera-dev/hedera-skills --skill axelar-gmpIs this agent skill safe to install?
- Gen Agent Trust Hubpass
This skill provides architectural guidance and code patterns for implementing Axelar General Message Passing (GMP) on the Hedera network. It includes security-focused instructions for cross-chain contract calls, gas payment, and receiver authorization. The skill utilizes the official Axelar Solidity SDK and interacts with standard Hedera system contracts. No malicious patterns or security risks were detected.
- Socketpass
No alerts
- Snykwarn
Risk: MEDIUM · 2 issues
What does this agent skill do?
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
| Piece | Role |
|---|---|
IAxelarGateway | callContract(destChain, destAddress, payload) |
IAxelarGasService | payNativeGasForContractCall{value} before the gateway call |
AxelarExecutable | Destination base; override _execute(...) |
| Chain names | Axelar string IDs — e.g. "hedera", "ethereum-sepolia" (not numeric chain IDs) |
| Addresses | EVM 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
| Side | Guard |
|---|---|
| Source sender | Only authorizedCaller (orchestrator) may send |
| Destination receiver | Validate srcChain + srcAddress (case-insensitive) before handling |
| Destination handler | Only 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 / …)
- Deploy handler first (no bridge knowledge).
- Deploy receiver with gateway + expected source + handler.
- Deploy sender with gateway + gas service + destination chain/address.
- Deploy orchestrator with sender address; authorize orchestrator on sender.
- Wire after both deploys: set destination on sender; set expected source on receiver.
- 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:
- Enforce interval / plan active
- Call the bridge sender with native value for Axelar gas
- 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
- references/examples.md — sender / receiver / allowlist sketches
- references/hedera-axelar.md — chain names vs IDs, SDK imports
- Axelar GMP overview
- axelar-gmp-sdk-solidity
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/hedera-dev/hedera-skills/axelar-gmp">View axelar-gmp on skillZs</a>