Contract Name:
GlacisClientSample
Contract Source Code:
<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;
import {GlacisCommons} from "../commons/GlacisCommons.sol";
import {IGlacisAccessControlClient} from "../interfaces/IGlacisAccessControlClient.sol";
/// @title Glacis Access Control Client
/// @dev This contract encapsulates Glacis Access Control client logic. Contracts inheriting this will have access to
/// Glacis Access control features
abstract contract GlacisAccessControlClient is GlacisCommons, IGlacisAccessControlClient {
mapping(uint256 => mapping(bytes32 => mapping(address => bool))) public allowedRoutes;
bytes32 constant internal WILD_BYTES = bytes32(uint256(WILDCARD));
address constant internal WILD_ADDR = address(WILDCARD);
/// @notice Adds an allowed route for this client
/// @param route Route to be added
function _addAllowedRoute(
GlacisRoute memory route
) internal {
allowedRoutes[route.fromChainId][route.fromAddress][route.fromAdapter] = true;
}
/// @notice Removes an allowed route for this client
/// @param route Allowed route to be removed
function _removeAllowedRoute(
GlacisRoute calldata route
) internal {
allowedRoutes[route.fromChainId][route.fromAddress][route.fromAdapter] = false;
}
/// @notice Queries if a route from path GMP+Chain+Address is allowed for this client
/// @param route_ Incoming message route
/// @return True if route is allowed, false otherwise
function isAllowedRoute(
GlacisRoute memory route_,
bytes memory // payload
) public view override returns (bool) {
return
allowedRoutes[route_.fromChainId][route_.fromAddress][route_.fromAdapter] ||
allowedRoutes[WILDCARD][route_.fromAddress][route_.fromAdapter] ||
allowedRoutes[WILDCARD][WILD_BYTES][route_.fromAdapter] ||
allowedRoutes[route_.fromChainId][WILD_BYTES][route_.fromAdapter] ||
(uint160(route_.fromAdapter) <= GLACIS_RESERVED_IDS && (
allowedRoutes[route_.fromChainId][route_.fromAddress][WILD_ADDR] ||
allowedRoutes[route_.fromChainId][WILD_BYTES][WILD_ADDR] ||
allowedRoutes[WILDCARD][WILD_BYTES][WILD_ADDR]
));
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;
import {IGlacisRouter} from "../interfaces/IGlacisRouter.sol";
import {IGlacisClient} from "../interfaces/IGlacisClient.sol";
import {GlacisAccessControlClient} from "../client/GlacisAccessControlClient.sol";
error GlacisClient__CanOnlyBeCalledByRouter();
error GlacisClient__InvalidRouterAddress();
/// @title Glacis Client
/// @dev This contract encapsulates Glacis client side logic, contracts inheriting this will have access to all
/// Glacis features
abstract contract GlacisClient is GlacisAccessControlClient, IGlacisClient {
address public immutable GLACIS_ROUTER;
event GlacisClient__MessageRouted(
bytes32 indexed messageId,
uint256 toChainId,
bytes32 to
);
event GlacisClient__MessageArrived(
address[] fromAdapters,
uint256 fromChainId,
bytes32 fromAddress
);
/// @param _glacisRouter This chain's deployment of the GlacisRouter
/// @param _quorum The initial default quorum for this client. If dynamic quorum is to be implemented (depending on payload)
/// this value can be ignored and set to 0
constructor(
address _glacisRouter,
uint256 _quorum
) GlacisAccessControlClient() IGlacisClient(_quorum) {
if (_glacisRouter == address(0))
revert GlacisClient__InvalidRouterAddress();
GLACIS_ROUTER = _glacisRouter;
}
/// @notice Routes the payload to the specific address on destination chain through GlacisRouter using a single specified GMP
/// @param chainId Destination chain (Glacis chain ID)
/// @param to Destination address on remote chain
/// @param payload Payload to be routed
/// @param adapter Glacis ID of the GMP to be used for the routing
/// @param refundAddress Address to refund excess gas payment
/// @param gasPayment Amount of gas to cover source and destination gas fees (excess will be refunded)
function _routeSingle(
uint256 chainId,
bytes32 to,
bytes memory payload,
address adapter,
address refundAddress,
uint256 gasPayment
) internal returns (bytes32) {
address[] memory adapters = new address[](1);
adapters[0] = adapter;
CrossChainGas[] memory fees = new CrossChainGas[](1);
fees[0] = CrossChainGas({
gasLimit: 0,
nativeCurrencyValue: uint128(gasPayment)
});
(bytes32 messageId,) = IGlacisRouter(GLACIS_ROUTER).route{
value: gasPayment
}(chainId, to, payload, adapters, fees, refundAddress, false);
emit GlacisClient__MessageRouted(messageId, chainId, to);
return messageId;
}
/// @notice Routes the payload to the specific address on destination chain through GlacisRouter using
/// specified GMPs.
/// @param chainId Destination chain (Glacis chain ID)
/// @param to Destination address on remote chain
/// @param payload Payload to be routed
/// @param adapters The adapters to use for redundant routing
/// @param fees Payment for each GMP to cover source and destination gas fees (excess will be refunded)
/// @param refundAddress Address to refund excess gas payment
/// @param gasPayment Amount of gas to cover source and destination gas fees (excess will be refunded)
function _routeRedundant(
uint256 chainId,
bytes32 to,
bytes memory payload,
address[] memory adapters,
CrossChainGas[] memory fees,
address refundAddress,
uint256 gasPayment
) internal returns (bytes32) {
(bytes32 messageId,) = IGlacisRouter(GLACIS_ROUTER).route{
value: gasPayment
}(chainId, to, payload, adapters, fees, refundAddress, false);
emit GlacisClient__MessageRouted(messageId, chainId, to);
return messageId;
}
/// @notice Routes the payload to the specific address on destination chain through GlacisRouter using GMPs
/// specified in gmps array
/// @param chainId Destination chain (Glacis chain ID)
/// @param to Destination address on remote chain
/// @param payload Payload to be routed
/// @param adapters An array of custom adapters to be used for the routing
/// @param fees Payment for each GMP to cover source and destination gas fees (excess will be refunded)
/// @param refundAddress Address to refund excess gas payment
/// @param retryable True to enable retry feature for this message
/// @param gasPayment Amount of gas to cover source and destination gas fees (excess will be refunded)
function _route(
uint256 chainId,
bytes32 to,
bytes memory payload,
address[] memory adapters,
CrossChainGas[] memory fees,
address refundAddress,
bool retryable,
uint256 gasPayment
) internal returns (bytes32,uint256) {
(bytes32 messageId,uint256 nonce) = IGlacisRouter(GLACIS_ROUTER).route{
value: gasPayment
}(chainId, to, payload, adapters, fees, refundAddress, retryable);
emit GlacisClient__MessageRouted(messageId, chainId, to);
return (messageId,nonce);
}
/// @notice Routes the payload to the specific address on destination chain through GlacisRouter using GMPs
/// specified in gmps array
/// @param chainId Destination chain (Glacis chain ID)
/// @param to Destination address on remote chain
/// @param payload Payload to be routed
/// @param adapters An array of adapters to be used for the routing
/// @param fees Payment for each GMP to cover source and destination gas fees (excess will be refunded)
/// @param refundAddress Address to refund excess gas payment
/// @param messageId The message ID of the message to retry
/// @param nonce The nonce emitted by the original sent message
/// @param gasPayment Amount of gas to cover source and destination gas fees (excess will be refunded)
function _retryRoute(
uint256 chainId,
bytes32 to,
bytes memory payload,
address[] memory adapters,
CrossChainGas[] memory fees,
address refundAddress,
bytes32 messageId,
uint256 nonce,
uint256 gasPayment
) internal returns (bytes32) {
IGlacisRouter(GLACIS_ROUTER).routeRetry{value: gasPayment}(
chainId,
to,
payload,
adapters,
fees,
refundAddress,
messageId,
nonce
);
emit GlacisClient__MessageRouted(messageId, chainId, to);
return messageId;
}
/// @notice Receives message from GMP(s) through GlacisRouter
/// @param fromAdapters addresses of the adapters sent this message (that reached quorum requirements)
/// @param fromChainId Source chain (Glacis chain ID)
/// @param fromAddress Source address on source chain
/// @param payload Routed payload
function receiveMessage(
address[] memory fromAdapters,
uint256 fromChainId,
bytes32 fromAddress,
bytes memory payload
) external virtual override {
if (msg.sender != GLACIS_ROUTER)
revert GlacisClient__CanOnlyBeCalledByRouter();
_receiveMessage(fromAdapters, fromChainId, fromAddress, payload);
emit GlacisClient__MessageArrived(fromAdapters, fromChainId, fromAddress);
}
/// @notice Receives message from GMP(s) through GlacisRouter
/// @param fromAdapters Adapter addresses
/// @param fromChainId Source chain (Glacis chain ID)
/// @param fromAddress Source address on source chain
/// @param payload Routed payload
function _receiveMessage(
address[] memory fromAdapters,
uint256 fromChainId,
bytes32 fromAddress,
bytes memory payload
) internal virtual {}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;
import {GlacisClient} from "./GlacisClient.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {GlacisCommons} from "../commons/GlacisCommons.sol";
/// @title Glacis Ownable Client
/// @dev This contract encapsulates Glacis client side logic, contracts inheriting this will have access to all
/// Glacis features
/// @notice This contract is ownable
abstract contract GlacisClientOwnable is GlacisClient, Ownable {
/// @param _glacisRouter This chain's deployment of the GlacisRouter
/// @param _quorum The default quorum that you would like. If you implement dynamic quorum, this value can be ignored and
/// set to 0
/// @param _owner The owner of this contract
constructor(
address _glacisRouter,
uint256 _quorum,
address _owner
) GlacisClient(_glacisRouter, _quorum) {
_transferOwnership(_owner);
}
/// @notice Add an allowed route for this client
/// @param allowedRoute Route to be added
function addAllowedRoute(
GlacisCommons.GlacisRoute memory allowedRoute
) external onlyOwner {
_addAllowedRoute(allowedRoute);
}
/// @notice Removes an allowed route for this client
/// @param route Allowed route to be removed
function removeAllowedRoute(
GlacisCommons.GlacisRoute calldata route
) external onlyOwner {
_removeAllowedRoute(route);
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;
/// @title Glacis Commons
/// @dev Contract for utility functions and structures common to Glacis Client and Infrastructure
contract GlacisCommons {
struct GlacisData {
bytes32 messageId;
uint256 nonce;
bytes32 originalFrom;
bytes32 originalTo;
}
struct GlacisTokenData {
address glacisToken;
uint256 glacisTokenAmount;
}
struct GlacisRoute {
uint256 fromChainId; // WILDCARD means any chain
bytes32 fromAddress; // WILDCARD means any address
address fromAdapter; // WILDCARD means any GMP, can also hold address
}
struct CrossChainGas {
uint128 gasLimit;
uint128 nativeCurrencyValue;
}
uint160 constant public WILDCARD = type(uint160).max;
uint256 constant public GLACIS_RESERVED_IDS = 248;
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;
import {GlacisCommons} from "../commons/GlacisCommons.sol";
/// @title IGlacisAccessControlClient
/// @notice An interface that determines Glacis' required access control
interface IGlacisAccessControlClient {
/// @notice Adds an allowed route for this client
/// @notice Queries if a route from path GMP+Chain+Address is allowed for this client
/// @param route The origin route for the message
/// @param payload The payload of a message
/// @return True if route is allowed, false otherwise
function isAllowedRoute(
GlacisCommons.GlacisRoute memory route,
bytes memory payload
) external view returns (bool);
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;
import {GlacisCommons} from "../commons/GlacisCommons.sol";
import {IGlacisAccessControlClient} from "../interfaces/IGlacisAccessControlClient.sol";
/// @title IGlacisClient
/// @notice An interface that defines the GMP modules (adapters) that the GlacisRouter interacts with.
abstract contract IGlacisClient is IGlacisAccessControlClient {
uint256 private immutable DEFAULT_QUORUM;
/// @param _defaultQuorum The default quorum that you would like. If you implement dynamic quorum, this value can be ignored
/// and set to 0
constructor(uint256 _defaultQuorum) {
DEFAULT_QUORUM = _defaultQuorum;
}
/// @notice Receives message from GMP(s) through GlacisRouter
/// @param fromAdapters Used adapters that sent this message (that reached quorum requirements)
/// @param fromChainId Source chain (Glacis chain ID)
/// @param fromAddress Source address on source chain
/// @param payload Routed payload
function receiveMessage(
address[] calldata fromAdapters,
uint256 fromChainId,
bytes32 fromAddress,
bytes calldata payload
) external virtual;
/// @notice The quorum of messages that the contract expects with a specific message
function getQuorum(
GlacisCommons.GlacisData memory, // glacis data
bytes memory, // payload
uint256 // unique messages received so far (for dynamic quorum, usually unused)
) public view virtual returns (uint256) {
return DEFAULT_QUORUM;
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;
import {GlacisCommons} from "../commons/GlacisCommons.sol";
/// @title IGlacisRouterEvents
/// @notice An interface that defines a GlacisRouter's events
abstract contract IGlacisRouterEvents is GlacisCommons
{
event GlacisAbstractRouter__MessageIdCreated(
bytes32 indexed messageId,
bytes32 indexed sender,
uint256 nonce
);
event GlacisAbstractRouter__AdapterRegistered(
uint8 indexed gmpId,
address indexed adapterAddress,
address indexed previousAddress
);
event GlacisAbstractRouter__AdapterUnregistered(
uint8 indexed gmpId,
address indexed adapterAddress
);
event GlacisRouter__ReceivedMessage(
bytes32 indexed messageId,
bytes32 indexed from,
uint256 indexed fromChainId,
address adapter,
bytes32 to
);
event GlacisRouter__ExecutedMessage(
bytes32 indexed messageId,
bytes32 indexed from,
uint256 indexed fromChainId,
address adapter,
bytes32 to
);
event GlacisRouter__MessageDispatched(
bytes32 indexed messageId,
bytes32 indexed from,
uint256 indexed toChainId,
bytes32 to,
bytes data,
address[] adapters,
CrossChainGas[] fees,
address refundAddress,
bool retryable
);
event GlacisRouter__MessageRetried(
bytes32 indexed messageId,
bytes32 indexed from,
uint256 indexed toChainId,
bytes32 to,
bytes data,
address[] adapters,
CrossChainGas[] fees,
address refundAddress
);
}
/// @title IGlacisRouter
/// @notice An interface that defines an interface that sends and receives messages across chains
interface IGlacisRouter {
/// @notice Routes the payload to the specific address on the destination chain
/// using specified adapters
/// @param chainId Destination chain (EIP-155)
/// @param to Destination address on remote chain
/// @param payload Payload to be routed
/// @param adapters An array of adapters to be used for the routing (addresses 0x01-0xF8 for Glacis adapters
/// or specific addresses for custom adapters)
/// @param fees Array of fees to be sent to each GMP & custom adapter for routing (must be same length as gmps)
/// @param refundAddress An address for native currency to be sent to that are greater than fees charged. If it is a
/// contract it needs to support receive function, reverted otherwise
/// @param retryable True if this message could pottentially be retried
/// @return A tuple with a bytes32 messageId and a uint256 nonce
function route(
uint256 chainId,
bytes32 to,
bytes memory payload,
address[] memory adapters,
GlacisCommons.CrossChainGas[] memory fees,
address refundAddress,
bool retryable
) external payable returns (bytes32, uint256);
/// @notice Retries routing the payload to the specific address on destination chain
/// using specified GMPs and quorum
/// @param chainId Destination chain (EIP-155)
/// @param to Destination address on remote chain
/// @param payload Payload to be routed
/// @param adapters An array of adapters to be used for the routing (addresses 0x01-0xF8 for Glacis adapters
/// or specific addresses for custom adapters)
/// @param fees Array of fees to be sent to each GMP & custom adapter for routing (must be same length as gmps)
/// @param refundAddress An address for native currency to be sent to that are greater than fees charged. If it is a
/// contract it needs to support receive function, tx will revert otherwise
/// @param messageId The messageId to retry
/// @param nonce Unique value for this message routing
/// @return A tuple with a bytes32 messageId and a uint256 nonce
function routeRetry(
uint256 chainId,
bytes32 to,
bytes memory payload,
address[] memory adapters,
GlacisCommons.CrossChainGas[] memory fees,
address refundAddress,
bytes32 messageId,
uint256 nonce
) external payable returns (bytes32, uint256);
/// @notice Receives a cross chain message from an IGlacisAdapter.
/// @param fromChainId Source chain (EIP-155)
/// @param glacisPayload Received payload with embedded GlacisData
function receiveMessage(
uint256 fromChainId,
bytes memory glacisPayload
) external;
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;
import {GlacisClientOwnable} from "../../../contracts/client/GlacisClientOwnable.sol";
import {GlacisCommons} from "../../../contracts/commons/GlacisCommons.sol";
contract GlacisClientSample is GlacisClientOwnable {
uint256 public value;
constructor(
address glacisRouter_,
address owner_
) GlacisClientOwnable(glacisRouter_, 1, owner_) {}
function setRemoteValue__execute(
uint256 toChainId,
bytes32 to,
address adapter,
bytes calldata payload
) external payable returns (bytes32) {
return _routeSingle(toChainId, to, payload, adapter, msg.sender, msg.value);
}
function setRemoteValue__redundancy(
uint256 toChainId,
bytes32 to,
address[] memory adapters,
CrossChainGas[] memory fees,
bytes calldata payload
) external payable returns (bytes32) {
return
_routeRedundant(
toChainId,
to,
payload,
adapters,
fees,
msg.sender,
msg.value
);
}
function setRemoteValue__retriable(
uint256 chainId,
bytes32 to,
address[] memory adapters,
CrossChainGas[] memory fees,
bytes memory payload
) external payable returns (bytes32,uint256) {
return
_route(
chainId,
to,
payload,
adapters,
fees,
msg.sender,
true,
msg.value
);
}
function setRemoteValue(
uint256 chainId,
bytes32 to,
bytes memory payload,
address[] memory adapters,
CrossChainGas[] memory fees,
address refundAddress,
bool retryable,
uint256 gasPayment
) external payable returns (bytes32,uint256 ) {
return
_route(
chainId,
to,
payload,
adapters,
fees,
refundAddress,
retryable,
gasPayment
);
}
function setRemoteValue__retry(
uint256 chainId,
bytes32 to,
address[] memory adapters,
CrossChainGas[] memory fees,
bytes memory payload,
bytes32 messageId,
uint256 nonce
) external payable returns (bytes32) {
return
_retryRoute(
chainId,
to,
payload,
adapters,
fees,
msg.sender,
messageId,
nonce,
msg.value
);
}
event ValueChanged(uint256 indexed value);
function _receiveMessage(
address[] memory, // fromGmpId,
uint256, // fromChainId,
bytes32, // fromAddress,
bytes memory payload
) internal override {
// NOTE: changed += to test for redundant messages
if (payload.length > 0) (value) += abi.decode(payload, (uint256));
}
// Setup of custom quorum (for testing purposes)
uint256 internal customQuorum = 1;
function setQuorum(uint256 q) external onlyOwner {
customQuorum = q;
}
function getQuorum(
GlacisCommons.GlacisData memory,
bytes memory,
uint256
) public view override returns (uint256) {
return customQuorum;
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.18;
import {GlacisClientOwnable} from "../../../contracts/client/GlacisClientOwnable.sol";
import {GlacisCommons} from "../../../contracts/commons/GlacisCommons.sol";
contract GlacisClientTextSample is GlacisClientOwnable {
string public value;
constructor(
address glacisRouter_,
address owner_
) GlacisClientOwnable(glacisRouter_, 0, owner_) {}
function setRemoteValue__execute(
uint256 toChainId,
bytes32 to,
address adapter,
bytes calldata payload
) external payable returns (bytes32) {
return _routeSingle(toChainId, to, payload, adapter, msg.sender, msg.value);
}
function setRemoteValue__redundancy(
uint256 toChainId,
bytes32 to,
address[] memory adapters,
CrossChainGas[] memory fees,
bytes calldata payload
) external payable returns (bytes32) {
return
_routeRedundant(
toChainId,
to,
payload,
adapters,
fees,
msg.sender,
msg.value
);
}
function setRemoteValue__retriable(
uint256 chainId,
bytes32 to,
address[] memory adapters,
CrossChainGas[] memory fees,
bytes memory payload
) external payable returns (bytes32,uint256) {
return
_route(
chainId,
to,
payload,
adapters,
fees,
msg.sender,
true,
msg.value
);
}
function setRemoteValue(
uint256 chainId,
bytes32 to,
bytes memory payload,
address[] memory adapters,
CrossChainGas[] memory fees,
address refundAddress,
bool retryable,
uint256 gasPayment
) external payable returns (bytes32,uint256) {
return
_route(
chainId,
to,
payload,
adapters,
fees,
refundAddress,
retryable,
gasPayment
);
}
function setRemoteValue__retry(
uint256 chainId,
bytes32 to,
address[] memory adapters,
CrossChainGas[] memory fees,
bytes memory payload,
bytes32 messageId,
uint256 nonce
) external payable returns (bytes32) {
return
_retryRoute(
chainId,
to,
payload,
adapters,
fees,
msg.sender,
messageId,
nonce,
msg.value
);
}
function _receiveMessage(
address[] memory, // fromGmpId,
uint256, // fromChainId,
bytes32, // fromAddress,
bytes memory payload
) internal override {
(value) = abi.decode(payload, (string));
}
// Setup of custom quorum (for testing purposes)
uint256 internal customQuorum = 1;
function setQuorum(uint256 q) external onlyOwner {
customQuorum = q;
}
function getQuorum(
GlacisCommons.GlacisData memory,
bytes memory,
uint256
) public view override returns (uint256) {
return customQuorum;
}
}