GlacisClient

The base of your cross-chain contracts.

GlacisClient is a smart contract base that can be used by developers to interact with the features that Glacis has to offer. By inheriting from GlacisClient, a smart contract is able to send and receive messages across chains with Glacis features. You can discover the source smart contract GlacisClient.sol in this repository. There is also an Ownable variant, GlacisClientOwnable.sol.

These are the constructor arguments for GlacisClient:

  • The address of GlacisRouter

  • The default GMP quorum for this contract to effectively receive a message

    constructor(address glacisRouter_, uint256 quorum) IGlacisClient(quorum) {
        if (glacisRouter_ == address(0))
            revert GlacisClient__InvalidRouterAddress();
        GLACIS_ROUTER = glacisRouter_;
    }

The Route Function

GlacisClient has multiple internal route functions that mirror the route functions that GlacisRouter provides, each which return a bytes32 message ID:

_route(
        uint256 chainId,
        bytes32 to,
        bytes memory payload,
        address[] memory adapters,
        CrossChainGas[] memory fees,
        address refundAddress,
        bool retryable,
        uint256 gasPayment) 
returns (bytes32,uint256)
_routeSingle(
        uint256 chainId,
        bytes32 to,
        bytes memory payload,
        address adapter,
        address refundAddress,
        uint256 gasPayment)
returns(bytes32)
_routeRedundant(
        uint256 chainId,
        bytes32 to,
        bytes memory payload,
        address[] memory adapters,
        CrossChainGas[] memory fees,
        address refundAddress,
        uint256 gasPayment)
returns (bytes32)

Each of these 3 varieties perform the same function: sending an original cross-chain message. _route is the encompassing route function that allows for complete configuration of all Glacis features. _routeSingle allows you to easily route through a single GMP. _routeRedundant allows you to easily route redundant messages (each message has the same ID and data) through multiple GMPs.

The following parameters are applicable to each of these route functions, similar to GlacisRouter:

Parameter NameParameter Description

uint256 chainId

The Glacis chain ID of the blockchain that you wish to send a message to

bytes32 to

The address of the destination contract that you are sending a message to

bytes memory payload

The payload of data that you wish to send to the destination contract

address[] memory adapters

An array of adapters to send the message over, such as an Axelar adapter. Can be an address if you wish to use an adapter that Glacis does not use, otherwise it can be a GMP ID stored as an address

uint8 adapter

A single adapter for the message to send over, used in lieu of the adapters parameter for conveniently defining a single GMP route

GlacisRouter.CrossChainGas[] memory fees

An array of fees that correspond to the amount provided to each adapter. This is a parallel array to the adapters parameter. Its rules are the same as in the GlacisRouter

address refundAddress

The address to which excess native currency is sent to if an adapter deems that the user overpaid

bool retryable

Whether to allow the message to be retried (stores owner of the message ID on-chain, slightly more gas expensive)

uint256 gasPayment

The amount of native currency to forward to the GlacisRouter to pay for cross-chain gas fees

Each of the routing functions returns a bytes32, which is the Glacis message ID for the routing. The more verbose route function also returns a uint256 nonce.

The Retry Route

An additional route is provided within GlacisClient, which doesn't send a new message. Instead, it resends a previous message so long as it receives identical input.

_routeRetry(
        uint256 chainId,
        bytes32 to,
        bytes memory payload,
        address[] memory adapters,
        CrossChainGas[] memory fees,
        address refundAddress,
        bytes32 messageId,
        uint256 nonce,
        uint256 gasPayment)
returns(bytes32)

Two additional parameters are required with this function:

Parameter NameParameter Description

bytes32 messageId

The Glacis message ID of the original message

uint256 nonce

The nonce of the message, which can be retrieved in the original message's event log

Keep in mind that in the GlacisRouter, only the original sender can retry routes. If this internal function is exposed publicly, anyone can retry on your smart contract's behalf.

The Receive Message Function

The GlacisRouter will call the receiveMessage function within your GlacisClient whenever there is a message sent to your smart contract. You must override the following internal function to react to cross-chain messages:

_receiveMessage(
        address[] memory fromAdapters,
        uint256 fromChainId,
        bytes32 fromAddress,
        bytes memory payload)

The parameters involved with this function are:

Parameter NameParameter Description

address[] fromAdapters

The adapters through which the messages were received

uint256 sourceChain

The Glacis chain ID of the message's source/origin

bytes32 sourceAddress

The address of the message's source/origin

bytes calldata payload

The generic bytes payload of the message, which can be decoded to your liking

Adding Routes for Access Control

You must set up routes within your instance of GlacisClient before it can receive messages. To do so, use the following function:

  • addAllowedRoute(GlacisRoute memory allowedRoute)

The GlacisRoute struct is defined as:

    struct GlacisRoute {
        uint256 fromChainId;    // WILDCARD means any chain
        address fromAddress;    // WILDCARD means any address
        address fromAdapter;    // WILDCARD means any official Glacis adapter
    }
    
    uint160 constant public WILDCARD = type(uint160).max;

Leaving any value as WILDCARD indicates that it is a wildcard route.

You can have multiple routes at a time. To remove a route, use the following function:

  • removeAllowedRoute(GlacisRoute calldata route)

Setting Quorum

Quorum is an important concept for Glacis, as it defines how many times a message with a specific message ID must be received before glacis calls your receiveMessage function. It is most likely that this number should be 1, but you can increase this number if you intend to have greater security through higher redundancy.

You can set the quorum's default value in the constructor by setting the quorum value.

If you wish to instead manually handle quorum per message, override the getQuorum function:

function getQuorum(
        GlacisCommons.GlacisData memory,    // glacis data
        bytes memory,                       // payload
        uint256                             // unique messages received so far (for dynamic quorum, usually unused)
) returns (uint256)

The parameters involved with this function are:

Parameter NameParameter Description

GlacisCommons.GlacisData memory glacisData

The Glacis metadata surrounding the message, found within GlacisCommons

bytes memory payload

The generic payload data associated with the function

uint256 uniqueMessagesReceived

The number of messages received so far, in case quorum must change in real-time (very rarely used)

Read-Only

These are some of the read-only functions in GlacisClient:

  • glacisRouter() returns(address) — returns the address set as the GlacisRouter, which was set in the constructor

  • isAllowedRoute(GlacisRoute memory accessRoute) returns(bool) — returns true if the provided route is available, false otherwise. Used by the GlacisRouter to verify access

Errors

GlacisClient includes the following errors, which you might encounter:

Error NameError Description

GlacisClient__CanOnlyBeCalledByRouter

Occurs when an address that is not the GlacisRouter attempts to call the receiveMessage function

GlacisClient__InvalidRouterAddress

Occurs when constructing the GlacisClient with an empty value for the GlacisRouter

Last updated