// Source: contracts/executable/AxelarExecutableWithToken.sol pragma solidity ^0.8.0; // SPDX-License-Identifier: MIT // File contracts/interfaces/IAxelarGateway.sol /** * @title IAxelarGateway * @dev Interface for the Axelar Gateway that supports general message passing and contract call execution. */ interface IAxelarGateway { /** * @notice Emitted when a contract call is made through the gateway. * @dev Logs the attempt to call a contract on another chain. * @param sender The address of the sender who initiated the contract call. * @param destinationChain The name of the destination chain. * @param destinationContractAddress The address of the contract on the destination chain. * @param payloadHash The keccak256 hash of the sent payload data. * @param payload The payload data used for the contract call. */ event ContractCall( address indexed sender, string destinationChain, string destinationContractAddress, bytes32 indexed payloadHash, bytes payload ); /** * @notice Sends a contract call to another chain. * @dev Initiates a cross-chain contract call through the gateway to the specified destination chain and contract. * @param destinationChain The name of the destination chain. * @param contractAddress The address of the contract on the destination chain. * @param payload The payload data to be used in the contract call. */ function callContract( string calldata destinationChain, string calldata contractAddress, bytes calldata payload ) external; /** * @notice Checks if a contract call is approved. * @dev Determines whether a given contract call, identified by the commandId and payloadHash, is approved. * @param commandId The identifier of the command to check. * @param sourceChain The name of the source chain. * @param sourceAddress The address of the sender on the source chain. * @param contractAddress The address of the contract where the call will be executed. * @param payloadHash The keccak256 hash of the payload data. * @return True if the contract call is approved, false otherwise. */ function isContractCallApproved( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, address contractAddress, bytes32 payloadHash ) external view returns (bool); /** * @notice Validates and approves a contract call. * @dev Validates the given contract call information and marks it as approved if valid. * @param commandId The identifier of the command to validate. * @param sourceChain The name of the source chain. * @param sourceAddress The address of the sender on the source chain. * @param payloadHash The keccak256 hash of the payload data. * @return True if the contract call is validated and approved, false otherwise. */ function validateContractCall( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes32 payloadHash ) external returns (bool); /** * @notice Checks if a command has been executed. * @dev Determines whether a command, identified by the commandId, has been executed. * @param commandId The identifier of the command to check. * @return True if the command has been executed, false otherwise. */ function isCommandExecuted(bytes32 commandId) external view returns (bool); } // File contracts/interfaces/IAxelarExecutable.sol /** * @title IAxelarExecutable * @dev Interface for a contract that is executable by Axelar Gateway's cross-chain message passing. * It defines a standard interface to execute commands sent from another chain. */ interface IAxelarExecutable { /** * @dev Thrown when a function is called with an invalid address. */ error InvalidAddress(); /** * @dev Thrown when the call is not approved by the Axelar Gateway. */ error NotApprovedByGateway(); /** * @notice Returns the address of the AxelarGateway contract. * @return The Axelar Gateway contract associated with this executable contract. */ function gateway() external view returns (IAxelarGateway); /** * @notice Executes the specified command sent from another chain. * @dev This function is called by the Axelar Gateway to carry out cross-chain commands. * Reverts if the call is not approved by the gateway or other checks fail. * @param commandId The identifier of the command to execute. * @param sourceChain The name of the source chain from where the command originated. * @param sourceAddress The address on the source chain that sent the command. * @param payload The payload of the command to be executed. This typically includes the function selector and encoded arguments. */ function execute( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload ) external; } // File contracts/executable/AxelarExecutable.sol /** * @title AxelarExecutable * @dev Abstract contract to be inherited by contracts that need to execute cross-chain commands via Axelar's Gateway. * It implements the IAxelarExecutable interface. */ abstract contract AxelarExecutable is IAxelarExecutable { /// @dev Reference to the Axelar Gateway contract. address internal immutable gatewayAddress; /** * @dev Contract constructor that sets the Axelar Gateway address. * Reverts if the provided address is the zero address. * @param gateway_ The address of the Axelar Gateway contract. */ constructor(address gateway_) { if (gateway_ == address(0)) revert InvalidAddress(); gatewayAddress = gateway_; } /** * @notice Executes the cross-chain command after validating it with the Axelar Gateway. * @dev This function ensures the call is approved by Axelar Gateway before execution. * It uses a hash of the payload for validation and internally calls _execute for the actual command execution. * Reverts if the validation fails. * @param commandId The unique identifier of the cross-chain message being executed. * @param sourceChain The name of the source chain from which the message originated. * @param sourceAddress The address on the source chain that sent the message. * @param payload The payload of the message payload. */ function execute( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload ) external virtual { bytes32 payloadHash = keccak256(payload); if (!gateway().validateContractCall(commandId, sourceChain, sourceAddress, payloadHash)) revert NotApprovedByGateway(); _execute(commandId, sourceChain, sourceAddress, payload); } /** * @dev Internal virtual function to be overridden by child contracts to execute the command. * It allows child contracts to define their custom command execution logic. * @param commandId The identifier of the command to execute. * @param sourceChain The name of the source chain from which the command originated. * @param sourceAddress The address on the source chain that sent the command. * @param payload The payload of the command to be executed. */ function _execute( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload ) internal virtual; /** * @notice Returns the address of the AxelarGateway contract. * @return The Axelar Gateway instance. */ function gateway() public view returns (IAxelarGateway) { return IAxelarGateway(gatewayAddress); } } // File contracts/interfaces/IAxelarExecutableWithToken.sol /** * @title IAxelarExecutableWithToken * @dev Interface for a contract that can execute commands from Axelar Gateway involving token transfers. * It extends IAxelarExecutable to include token-related functionality. */ interface IAxelarExecutableWithToken is IAxelarExecutable { /** * @notice Executes the specified command sent from another chain and includes a token transfer. * @dev This function should be implemented to handle incoming commands that include token transfers. * It will be called by an implementation of `IAxelarGatewayWithToken`. * @param commandId The identifier of the command to execute. * @param sourceChain The name of the source chain from where the command originated. * @param sourceAddress The address on the source chain that sent the command. * @param payload The payload of the command to be executed. * @param tokenSymbol The symbol of the token to be transferred with this command. * @param amount The amount of tokens to be transferred with this command. */ function executeWithToken( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata tokenSymbol, uint256 amount ) external; } // File contracts/interfaces/IAxelarGatewayWithToken.sol /** * @title IAxelarGatewayWithToken * @dev Interface for the Axelar Gateway that supports cross-chain token transfers coupled with general message passing. * It extends IAxelarGateway to include token-related functionality. */ interface IAxelarGatewayWithToken is IAxelarGateway { /** * @notice Emitted when a token is sent to another chain. * @dev Logs the attempt to send tokens to a recipient on another chain. * @param sender The address of the sender who initiated the token transfer. * @param destinationChain The name of the destination chain. * @param destinationAddress The address of the recipient on the destination chain. * @param symbol The symbol of the token being transferred. * @param amount The amount of the tokens being transferred. */ event TokenSent( address indexed sender, string destinationChain, string destinationAddress, string symbol, uint256 amount ); /** * @notice Emitted when a contract call is made through the gateway along with a token transfer. * @dev Logs the attempt to call a contract on another chain with an associated token transfer. * @param sender The address of the sender who initiated the contract call with token. * @param destinationChain The name of the destination chain. * @param destinationContractAddress The address of the contract on the destination chain. * @param payloadHash The keccak256 hash of the sent payload data. * @param payload The payload data used for the contract call. * @param symbol The symbol of the token being transferred. * @param amount The amount of the tokens being transferred. */ event ContractCallWithToken( address indexed sender, string destinationChain, string destinationContractAddress, bytes32 indexed payloadHash, bytes payload, string symbol, uint256 amount ); /** * @notice Emitted when a contract call with a token minting is approved. * @dev Logs the approval of a contract call that originated from another chain and involves a token minting process. * @param commandId The identifier of the command to execute. * @param sourceChain The name of the source chain from whence the command came. * @param sourceAddress The address of the sender on the source chain. * @param contractAddress The address of the contract where the call will be executed. * @param payloadHash The keccak256 hash of the approved payload data. * @param symbol The symbol of the token being minted. * @param amount The amount of the tokens being minted. * @param sourceTxHash The hash of the source transaction on the source chain. * @param sourceEventIndex The index of the event in the source transaction logs. */ event ContractCallApprovedWithMint( bytes32 indexed commandId, string sourceChain, string sourceAddress, address indexed contractAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, bytes32 sourceTxHash, uint256 sourceEventIndex ); /** * @notice Sends tokens to another chain. * @dev Initiates a cross-chain token transfer through the gateway to the specified destination chain and recipient. * @param destinationChain The name of the destination chain. * @param destinationAddress The address of the recipient on the destination chain. * @param symbol The symbol of the token being transferred. * @param amount The amount of the tokens being transferred. */ function sendToken( string calldata destinationChain, string calldata destinationAddress, string calldata symbol, uint256 amount ) external; /** * @notice Makes a contract call on another chain with an associated token transfer. * @dev Initiates a cross-chain contract call through the gateway that includes a token transfer to the specified contract on the destination chain. * @param destinationChain The name of the destination chain. * @param contractAddress The address of the contract on the destination chain. * @param payload The payload data to be used in the contract call. * @param symbol The symbol of the token being transferred. * @param amount The amount of the tokens being transferred. */ function callContractWithToken( string calldata destinationChain, string calldata contractAddress, bytes calldata payload, string calldata symbol, uint256 amount ) external; /** * @notice Checks if a contract call with token minting is approved. * @dev Determines whether a given contract call, identified by the commandId and payloadHash, involving token minting is approved. * @param commandId The identifier of the command to check. * @param sourceChain The name of the source chain. * @param sourceAddress The address of the sender on the source chain. * @param contractAddress The address of the contract where the call will be executed. * @param payloadHash The keccak256 hash of the payload data. * @param symbol The symbol of the token associated with the minting. * @param amount The amount of the tokens to be minted. * @return True if the contract call with token minting is approved, false otherwise. */ function isContractCallAndMintApproved( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, address contractAddress, bytes32 payloadHash, string calldata symbol, uint256 amount ) external view returns (bool); /** * @notice Validates and approves a contract call with token minting. * @dev Validates the given contract call information and marks it as approved if valid. It also involves the minting of tokens. * @param commandId The identifier of the command to validate. * @param sourceChain The name of the source chain. * @param sourceAddress The address of the sender on the source chain. * @param payloadHash The keccak256 hash of the payload data. * @param symbol The symbol of the token associated with the minting. * @param amount The amount of the tokens to be minted. * @return True if the contract call with token minting is validated and approved, false otherwise. */ function validateContractCallAndMint( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes32 payloadHash, string calldata symbol, uint256 amount ) external returns (bool); /** * @notice Retrieves the address of a token given its symbol. * @dev Gets the contract address of the token registered with the given symbol. * @param symbol The symbol of the token to retrieve the address for. * @return The contract address of the token corresponding to the given symbol. */ function tokenAddresses(string memory symbol) external view returns (address); } // File contracts/executable/AxelarExecutableWithToken.sol /** * @title AxelarExecutableWithToken * @dev Abstract contract to be inherited by contracts that need to execute cross-chain commands involving tokens via Axelar's Gateway. * It extends AxelarExecutable and implements the IAxelarExecutableWithToken interface. */ abstract contract AxelarExecutableWithToken is IAxelarExecutableWithToken, AxelarExecutable { /** * @dev Contract constructor that sets the Axelar Gateway With Token address and initializes AxelarExecutable. * @param gateway_ The address of the Axelar Gateway With Token contract. */ constructor(address gateway_) AxelarExecutable(gateway_) {} /** * @notice Executes the cross-chain command with token transfer after validating it with the Axelar Gateway. * @dev This function ensures the call is approved by Axelar Gateway With Token before execution. * It uses a hash of the payload for validation and calls _executeWithToken for the actual command execution. * Reverts if the validation fails. * @param commandId The unique identifier of the cross-chain message being executed. * @param sourceChain The name of the source chain from which the message originated. * @param sourceAddress The address on the source chain that sent the message. * @param payload The payload of the message payload. * @param tokenSymbol The symbol of the token to be transferred. * @param amount The amount of tokens to be transferred. */ function executeWithToken( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata tokenSymbol, uint256 amount ) external virtual { bytes32 payloadHash = keccak256(payload); if ( !gatewayWithToken().validateContractCallAndMint( commandId, sourceChain, sourceAddress, payloadHash, tokenSymbol, amount ) ) revert NotApprovedByGateway(); _executeWithToken(commandId, sourceChain, sourceAddress, payload, tokenSymbol, amount); } /** * @dev Internal virtual function to be overridden by child contracts to execute the command with token transfer. * It allows child contracts to define their custom command execution logic involving tokens. * @param commandId The unique identifier of the cross-chain message being executed. * @param sourceChain The name of the source chain from which the message originated. * @param sourceAddress The address on the source chain that sent the message. * @param payload The payload of the message payload. * @param tokenSymbol The symbol of the token to be transferred. * @param amount The amount of tokens to be transferred. */ function _executeWithToken( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata tokenSymbol, uint256 amount ) internal virtual; /** * @notice Returns the address of the IAxelarGatewayWithToken contract. * @return The Axelar Gateway with Token instance. */ function gatewayWithToken() internal view returns (IAxelarGatewayWithToken) { return IAxelarGatewayWithToken(gatewayAddress); } }