Call a contract on chain B from chain A

To call a contract on chain B from chain A, the user needs to call callContract on the gateway of chain A, specifying:

  • The destination chain, which must be an EVM chain from Chain names.
  • The destination contract address, which must inherit from AxelarExecutable defined in AxelarExecutable.sol.
  • The payload bytes to pass to the destination contract.

🚨

NOTE: The security of your contracts is limited to the security of the chains they integrate with. Since blockchains can have different security practices, we recommend doing due diligence on all chains your contract will be deployed to.

If you want to try this out directly on the blockchain, you can use Remix to try out Axelar’s GMP.

function callContract(
string memory destinationChain,
string memory contractAddress,
bytes memory payload
) external;

AxelarExecutable has an execute function that will be triggered by the Axelar network on the destination chain after the callContract function has been executed on the source chain. This will validate the contract call and then invoke your _execute method, where you should write any custom logic.

function _execute(
bytes32 commandId,
string memory sourceChain,
string memory sourceAddress,
bytes calldata payload
) internal virtual {}

ℹ️

Ensure the payload is encoded bytes!

The payload passed to callContract (and ultimately to _execute and _executeWithToken) has type bytes. Use the ABI encoder/decoder convert your data to bytes.

Example of payload encoding in JavaScript (using ethers.js):

const { ethers } = require("ethers");
// encoding a string
const payload = ethers.utils.defaultAbiCoder.encode(
["string"],
["Hello from contract A"],
);

Example of payload decoding in Solidity:

function _execute(
bytes32 commandId,
string memory sourceChain,
string memory sourceAddress,
bytes calldata payload
) internal override {
// decoding a string
string memory _message = abi.decode(payload, (string));
}

Learn More: For a detailed tutorial on building a full-stack interchain decentralized application with Next.js, Solidity, and Axelar’s General Message Passing callContract to send messages between blockchains, check out our comprehensive guide: Build a Full-Stack Interchain Application With Next.js, Solidity & Axelar.

If you are implementing any underlying token transfer capabilities, you should import the InterchainTransferSent or InterchainTransferReceived interfaces and emit events as appropriate so that these events can be tracked.

interface IInterchainTransferSent {
/**
* @dev Emitted when a GMP transfer is sent, providing details for volume tracking.
* @param destinationChain The Axelar chain identifier of the destination chain.
* @param destinationContractAddress The address of the contract on the destination chain that receives the transfer.
* @param recipient The address of the final recipient of the transferred assets on the destination chain.
* @param token The address of the token contract on the source chain.
* @param amount The amount (in atomic units) of tokens transferred.
*/
event InterchainTransferSent(
string destinationChain,
string destinationContractAddress,
address indexed sender,
bytes recipient,
address indexed token,
uint256 amount
);
}
/**
* @title IInterchainTransferReceived
* @dev Interface for tracking asset value transfers using General Message Passing (GMP) calls in the Axelar Network.
* This interface defines an event that should be emitted when a GMP transfer is received,
* allowing for standardized volume tracking across different implementations.
*/
interface IInterchainTransferReceived {
/**
* @dev Emitted when an interchain transfer is received, providing details for volume tracking.
* @param sourceChain The Axelar chain identifier of the source chain.
* @param sourceAddress The address of the contract that initiated the transfer on the source chain.
* @param sender The address of the sender in case it is different from the source contract address
* @param recipient The address of the final recipient of the transferred assets on the destination chain.
* @param token The address of the token contract on the destination chain.
* @param amount The amount (in atomic units) of tokens received.
*/
event InterchainTransferReceived(
string sourceChain,
string sourceAddress,
bytes sender,
address indexed recipient,
address indexed token,
uint256 amount
);
}

Edit on GitHub