Soroban Contracts

The core contracts for Axelar’s integration with Stellar Soroban can be found at the axelar-cgp-soroban repository.

The Rust based GMP contracts can be thought of similarly to their EVM counterparts.

At the core of there are two main contracts involved in sending a GMP message, these are the Gateway Contract and the Gas Service.

The Gateway facilitates sending and receiving of cross-chain messages to other chains via the Axelar Network.

For sending a GMP message, the callContract() function needs to be triggered.

The callContract function triggers your cross-chain message from Stellar to the Axelar Network. When sending a cross-chain message you must specify the destination of your cross-chain message and a given payload.

💡

Note: In Soroban, you don’t need to pass the env explicitly when writing contract functions; it is automatically provided to the contract entry points

The callContract function takes five parameters.

  1. env: Standard soroban env that provides access to the environment the contract is executing within.
  2. caller: The sender of the contract call.
  3. destination_chain: Name of the chain the message is being sent to.
  4. destination_address: Address on the destination chain the message is being sent to.
  5. payload: A bytes representation of the cross-chain message being sent.
pub fn call_contract(
env: Env,
caller: Address,
destination_chain: String,
destination_address: String,
payload: Bytes,
){}

The Gas Service handles cross-chain gas payment when making a GMP request.

When sending a GMP message before triggering the call_contract() function on the Gateway, the pay_gas_for_contract_call() must be triggered first to pay for the cross-chain transaction.

The pay_gas_for_contract_call() allows users to pay for the entirety of the cross-chain transaction in a given token.

The pay_gas_for_contract_call() takes seven parameters.

  1. env: Standard soroban env that provides access to the environment the contract is executing within.
  2. sender: The sender of the gas payment call.
  3. destination_chain: Name of the chain the message is being sent to.
  4. destination_address: Address on the destination chain the message is being sent to.
  5. payload: A bytes representation of the cross-chain message being sent.
  6. refund_address: An address to be refunded if gas amount was overpaid.
  7. token: The token being used for payment

Note: The expected token is a struct type that requires an address and amount.

pub fn pay_gas_for_contract_call(
env: Env,
sender: Address,
destination_chain: String,
destination_address: String,
payload: Bytes,
refund_address: Address,
token: Token,
) -> Result<(), ContractError> {}

The Executable is a Rust Trait (not an individual contract) that will be used to execute a cross-chain call on a Soroban dapp when Stellar is the receiving chain of a cross-chain message.

The execute() function will be triggered by an Axelar relayer when the cross-chain message arrives. Your contract should implement the execute() function to handle the incoming cross-chain GMP data.

The execute() function takes five parameters.

  1. env: Standard soroban env that provides access to the environment the contract is executing within.
  2. source_chain: The source chain where the gmp message is coming from.
  3. message_id: Identifier for incoming GMP message.
  4. source_address: The address on the source chain where the gmp message is coming from/
  5. payload: A bytes representation of the cross-chain message being sent.
fn execute(
env: Env,
source_chain: String,
message_id: String,
source_address: String,
payload: Bytes,
);

The validate() function on the Executable will trigger the validate_message() that is defined on the Gateway.

The validate() function takes five parameters.

  1. env: Standard soroban env that provides access to the environment the contract is executing within.
  2. source_chain: The source chain where the gmp message is coming from.
  3. message_id: Identifier for incoming GMP message.
  4. source_address: The address on the source chain where the gmp message is coming from/
  5. payload: A bytes representation of the cross-chain message being sent.
fn validate(
env: Env,
source_chain: String,
message_id: String,
source_address: String,
payload: Bytes,
) {}

The validate() function will trigger the validate_message(), this will confirm that the incoming GMP message is an authenticated message that has been verified by the Amplifier Verifiers.

pub fn validate_message(
env: Env,
caller: Address,
source_chain: String,
message_id: String,
source_address: String,
payload_hash: BytesN<32>,
) -> bool {}
  1. env: Standard soroban env that provides access to the environment the contract is executing within.
  2. caller: The intended destination_address of the contract call.
  3. source_chain: The source chain where the gmp message is coming from.
  4. message_id: Identifier for incoming GMP message.
  5. source_address: The address on the source chain where the gmp message is coming from/
  6. payload: A bytes representation of the cross-chain message being sent.

Returns a bool indicating whether the incoming GMP message is valid or not.

Edit on GitHub