// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol";
import "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./interfaces/IAstrobotNFT.sol";
/**
* @title AstrobotNFTBridgeETH
* @dev Ethereum-side bridge for Astrobot NFTs.
*
* The contract bridges an Astrobot NFT by verifying ownership,
* "burning" the NFT by transferring it to the burn address,
* storing the last sent payload, and sending a cross-chain payload (msg.sender, tokenId).
*/
contract AstrobotNFTBridgeETH is Ownable, AxelarExecutable {
IAxelarGasService public gasService;
IAstrobotNFT public immutable astrobotNFT;
// Destination (Base) chain details.
string public baseChain;
string public baseBridgeAddress;
// Burn address used to simulate NFT burning.
address public constant BURN_ADDRESS = 0x000000000000000000000000000000000000dEaD;
event NFTBridged(
address indexed user,
uint256 indexed tokenId
);
/**
* @param gateway_ The Axelar gateway address.
* @param gasService_ The Axelar Gas Service address.
* @param astrobotNFTAddress_ The Astrobot NFT contract address.
* @param baseChain_ The destination chain name (e.g., "base").
* @param baseBridgeAddress_ The Base bridge contract address (as a hex string).
*/
constructor(
address gateway_,
address gasService_,
address astrobotNFTAddress_,
string memory baseChain_,
string memory baseBridgeAddress_
) AxelarExecutable(gateway_) {
require(astrobotNFTAddress_ != address(0), "Invalid NFT address");
require(bytes(baseChain_).length > 0, "Base chain required");
require(bytes(baseBridgeAddress_).length > 0, "Base bridge address required");
gasService = IAxelarGasService(gasService_);
astrobotNFT = IAstrobotNFT(astrobotNFTAddress_);
baseChain = baseChain_;
baseBridgeAddress = baseBridgeAddress_;
}
/**
* @notice Bridges an Astrobot NFT.
* Checks NFT ownership, "burns" the NFT,
* and sends the cross-chain payload (msg.sender, tokenId).
* @param tokenId The NFT token ID to bridge.
*/
function bridgeNFT(uint256 tokenId) external payable {
// Verify NFT ownership.
require(astrobotNFT.ownerOf(tokenId) == msg.sender, "Caller is not the owner");
// "Burn" the NFT by transferring it to the burn address.
astrobotNFT.safeTransferFrom(msg.sender, BURN_ADDRESS, tokenId);
// Prepare payload: encode (user address, tokenId).
bytes memory payload = abi.encode(msg.sender, tokenId);
// Optionally pay for Axelar gas if msg.value > 0.
if (msg.value > 0) {
gasService.payNativeGasForContractCall{value: msg.value}(
address(this),
baseChain,
baseBridgeAddress,
payload,
msg.sender
);
}
// Send the cross-chain message.
gateway().callContract(baseChain, baseBridgeAddress, payload);
emit NFTBridged(msg.sender, tokenId);
}
/**
* @dev Override _execute to prevent processing incoming cross-chain messages.
*/
function _execute(
bytes32, // commandId
string calldata, // sourceChain
string calldata, // sourceAddress
bytes calldata // payload
) internal pure override {
revert("This contract does not accept cross-chain messages");
}
receive() external payable {}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IAxelarGateway } from '../interfaces/IAxelarGateway.sol';
import { IAxelarExecutable } from '../interfaces/IAxelarExecutable.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);
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title GasEstimationType
* @notice This enum represents the gas estimation types for different chains.
*/
enum GasEstimationType {
Default,
OptimismEcotone,
OptimismBedrock,
Arbitrum,
Scroll
}
/**
* @title GasInfo
* @notice This struct represents the gas pricing information for a specific chain.
* @dev Smaller uint types are used for efficient struct packing to save storage costs.
*/
struct GasInfo {
/// @dev Custom gas pricing rule, such as L1 data fee on L2s
uint64 gasEstimationType;
/// @dev Scalar value needed for specific gas estimation types, expected to be less than 1e10
uint64 l1FeeScalar;
/// @dev Axelar base fee for cross-chain message approval on destination, in terms of source native gas token
uint128 axelarBaseFee;
/// @dev Gas price of destination chain, in terms of the source chain token, i.e dest_gas_price * dest_token_market_price / src_token_market_price
uint128 relativeGasPrice;
/// @dev Needed for specific gas estimation types. Blob base fee of destination chain, in terms of the source chain token, i.e dest_blob_base_fee * dest_token_market_price / src_token_market_price
uint128 relativeBlobBaseFee;
/// @dev Axelar express fee for express execution, in terms of source chain token
uint128 expressFee;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title IAstrobotNFT
* @dev Interface for the Astrobot NFT contract.
*/
interface IAstrobotNFT {
function ownerOf(uint256 tokenId) external view returns (address);
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IAxelarGateway } from './IAxelarGateway.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;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { GasInfo } from '../types/GasEstimationTypes.sol';
import { IInterchainGasEstimation } from './IInterchainGasEstimation.sol';
import { IUpgradable } from './IUpgradable.sol';
/**
* @title IAxelarGasService Interface
* @notice This is an interface for the AxelarGasService contract which manages gas payments
* and refunds for cross-chain communication on the Axelar network.
* @dev This interface inherits IUpgradable
*/
interface IAxelarGasService is IInterchainGasEstimation, IUpgradable {
error InvalidAddress();
error NotCollector();
error InvalidAmounts();
error InvalidGasUpdates();
error InvalidParams();
error InsufficientGasPayment(uint256 required, uint256 provided);
event GasPaidForContractCall(
address indexed sourceAddress,
string destinationChain,
string destinationAddress,
bytes32 indexed payloadHash,
address gasToken,
uint256 gasFeeAmount,
address refundAddress
);
event GasPaidForContractCallWithToken(
address indexed sourceAddress,
string destinationChain,
string destinationAddress,
bytes32 indexed payloadHash,
string symbol,
uint256 amount,
address gasToken,
uint256 gasFeeAmount,
address refundAddress
);
event NativeGasPaidForContractCall(
address indexed sourceAddress,
string destinationChain,
string destinationAddress,
bytes32 indexed payloadHash,
uint256 gasFeeAmount,
address refundAddress
);
event NativeGasPaidForContractCallWithToken(
address indexed sourceAddress,
string destinationChain,
string destinationAddress,
bytes32 indexed payloadHash,
string symbol,
uint256 amount,
uint256 gasFeeAmount,
address refundAddress
);
event GasPaidForExpressCall(
address indexed sourceAddress,
string destinationChain,
string destinationAddress,
bytes32 indexed payloadHash,
address gasToken,
uint256 gasFeeAmount,
address refundAddress
);
event GasPaidForExpressCallWithToken(
address indexed sourceAddress,
string destinationChain,
string destinationAddress,
bytes32 indexed payloadHash,
string symbol,
uint256 amount,
address gasToken,
uint256 gasFeeAmount,
address refundAddress
);
event NativeGasPaidForExpressCall(
address indexed sourceAddress,
string destinationChain,
string destinationAddress,
bytes32 indexed payloadHash,
uint256 gasFeeAmount,
address refundAddress
);
event NativeGasPaidForExpressCallWithToken(
address indexed sourceAddress,
string destinationChain,
string destinationAddress,
bytes32 indexed payloadHash,
string symbol,
uint256 amount,
uint256 gasFeeAmount,
address refundAddress
);
event GasAdded(
bytes32 indexed txHash,
uint256 indexed logIndex,
address gasToken,
uint256 gasFeeAmount,
address refundAddress
);
event NativeGasAdded(bytes32 indexed txHash, uint256 indexed logIndex, uint256 gasFeeAmount, address refundAddress);
event ExpressGasAdded(
bytes32 indexed txHash,
uint256 indexed logIndex,
address gasToken,
uint256 gasFeeAmount,
address refundAddress
);
event NativeExpressGasAdded(
bytes32 indexed txHash,
uint256 indexed logIndex,
uint256 gasFeeAmount,
address refundAddress
);
event Refunded(
bytes32 indexed txHash,
uint256 indexed logIndex,
address payable receiver,
address token,
uint256 amount
);
/**
* @notice Pay for gas for any type of contract execution on a destination chain.
* @dev This function is called on the source chain before calling the gateway to execute a remote contract.
* @dev If estimateOnChain is true, the function will estimate the gas cost and revert if the payment is insufficient.
* @param sender The address making the payment
* @param destinationChain The target chain where the contract call will be made
* @param destinationAddress The target address on the destination chain
* @param payload Data payload for the contract call
* @param executionGasLimit The gas limit for the contract call
* @param estimateOnChain Flag to enable on-chain gas estimation
* @param refundAddress The address where refunds, if any, should be sent
* @param params Additional parameters for gas payment. This can be left empty for normal contract call payments.
*/
function payGas(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
uint256 executionGasLimit,
bool estimateOnChain,
address refundAddress,
bytes calldata params
) external payable;
/**
* @notice Pay for gas using ERC20 tokens for a contract call on a destination chain.
* @dev This function is called on the source chain before calling the gateway to execute a remote contract.
* @param sender The address making the payment
* @param destinationChain The target chain where the contract call will be made
* @param destinationAddress The target address on the destination chain
* @param payload Data payload for the contract call
* @param gasToken The address of the ERC20 token used to pay for gas
* @param gasFeeAmount The amount of tokens to pay for gas
* @param refundAddress The address where refunds, if any, should be sent
*/
function payGasForContractCall(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
address gasToken,
uint256 gasFeeAmount,
address refundAddress
) external;
/**
* @notice Pay for gas using ERC20 tokens for a contract call with tokens on a destination chain.
* @dev This function is called on the source chain before calling the gateway to execute a remote contract.
* @param sender The address making the payment
* @param destinationChain The target chain where the contract call with tokens will be made
* @param destinationAddress The target address on the destination chain
* @param payload Data payload for the contract call with tokens
* @param symbol The symbol of the token to be sent with the call
* @param amount The amount of tokens to be sent with the call
* @param gasToken The address of the ERC20 token used to pay for gas
* @param gasFeeAmount The amount of tokens to pay for gas
* @param refundAddress The address where refunds, if any, should be sent
*/
function payGasForContractCallWithToken(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
string calldata symbol,
uint256 amount,
address gasToken,
uint256 gasFeeAmount,
address refundAddress
) external;
/**
* @notice Pay for gas using native currency for a contract call on a destination chain.
* @dev This function is called on the source chain before calling the gateway to execute a remote contract.
* @param sender The address making the payment
* @param destinationChain The target chain where the contract call will be made
* @param destinationAddress The target address on the destination chain
* @param payload Data payload for the contract call
* @param refundAddress The address where refunds, if any, should be sent
*/
function payNativeGasForContractCall(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
address refundAddress
) external payable;
/**
* @notice Pay for gas using native currency for a contract call with tokens on a destination chain.
* @dev This function is called on the source chain before calling the gateway to execute a remote contract.
* @param sender The address making the payment
* @param destinationChain The target chain where the contract call with tokens will be made
* @param destinationAddress The target address on the destination chain
* @param payload Data payload for the contract call with tokens
* @param symbol The symbol of the token to be sent with the call
* @param amount The amount of tokens to be sent with the call
* @param refundAddress The address where refunds, if any, should be sent
*/
function payNativeGasForContractCallWithToken(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
string calldata symbol,
uint256 amount,
address refundAddress
) external payable;
/**
* @notice Pay for gas using ERC20 tokens for an express contract call on a destination chain.
* @dev This function is called on the source chain before calling the gateway to express execute a remote contract.
* @param sender The address making the payment
* @param destinationChain The target chain where the contract call will be made
* @param destinationAddress The target address on the destination chain
* @param payload Data payload for the contract call
* @param gasToken The address of the ERC20 token used to pay for gas
* @param gasFeeAmount The amount of tokens to pay for gas
* @param refundAddress The address where refunds, if any, should be sent
*/
function payGasForExpressCall(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
address gasToken,
uint256 gasFeeAmount,
address refundAddress
) external;
/**
* @notice Pay for gas using ERC20 tokens for an express contract call with tokens on a destination chain.
* @dev This function is called on the source chain before calling the gateway to express execute a remote contract.
* @param sender The address making the payment
* @param destinationChain The target chain where the contract call with tokens will be made
* @param destinationAddress The target address on the destination chain
* @param payload Data payload for the contract call with tokens
* @param symbol The symbol of the token to be sent with the call
* @param amount The amount of tokens to be sent with the call
* @param gasToken The address of the ERC20 token used to pay for gas
* @param gasFeeAmount The amount of tokens to pay for gas
* @param refundAddress The address where refunds, if any, should be sent
*/
function payGasForExpressCallWithToken(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
string calldata symbol,
uint256 amount,
address gasToken,
uint256 gasFeeAmount,
address refundAddress
) external;
/**
* @notice Pay for gas using native currency for an express contract call on a destination chain.
* @dev This function is called on the source chain before calling the gateway to execute a remote contract.
* @param sender The address making the payment
* @param destinationChain The target chain where the contract call will be made
* @param destinationAddress The target address on the destination chain
* @param payload Data payload for the contract call
* @param refundAddress The address where refunds, if any, should be sent
*/
function payNativeGasForExpressCall(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
address refundAddress
) external payable;
/**
* @notice Pay for gas using native currency for an express contract call with tokens on a destination chain.
* @dev This function is called on the source chain before calling the gateway to execute a remote contract.
* @param sender The address making the payment
* @param destinationChain The target chain where the contract call with tokens will be made
* @param destinationAddress The target address on the destination chain
* @param payload Data payload for the contract call with tokens
* @param symbol The symbol of the token to be sent with the call
* @param amount The amount of tokens to be sent with the call
* @param refundAddress The address where refunds, if any, should be sent
*/
function payNativeGasForExpressCallWithToken(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
string calldata symbol,
uint256 amount,
address refundAddress
) external payable;
/**
* @notice Add additional gas payment using ERC20 tokens after initiating a cross-chain call.
* @dev This function can be called on the source chain after calling the gateway to execute a remote contract.
* @param txHash The transaction hash of the cross-chain call
* @param logIndex The log index for the cross-chain call
* @param gasToken The ERC20 token address used to add gas
* @param gasFeeAmount The amount of tokens to add as gas
* @param refundAddress The address where refunds, if any, should be sent
*/
function addGas(
bytes32 txHash,
uint256 logIndex,
address gasToken,
uint256 gasFeeAmount,
address refundAddress
) external;
/**
* @notice Add additional gas payment using native currency after initiating a cross-chain call.
* @dev This function can be called on the source chain after calling the gateway to execute a remote contract.
* @param txHash The transaction hash of the cross-chain call
* @param logIndex The log index for the cross-chain call
* @param refundAddress The address where refunds, if any, should be sent
*/
function addNativeGas(
bytes32 txHash,
uint256 logIndex,
address refundAddress
) external payable;
/**
* @notice Add additional gas payment using ERC20 tokens after initiating an express cross-chain call.
* @dev This function can be called on the source chain after calling the gateway to express execute a remote contract.
* @param txHash The transaction hash of the cross-chain call
* @param logIndex The log index for the cross-chain call
* @param gasToken The ERC20 token address used to add gas
* @param gasFeeAmount The amount of tokens to add as gas
* @param refundAddress The address where refunds, if any, should be sent
*/
function addExpressGas(
bytes32 txHash,
uint256 logIndex,
address gasToken,
uint256 gasFeeAmount,
address refundAddress
) external;
/**
* @notice Add additional gas payment using native currency after initiating an express cross-chain call.
* @dev This function can be called on the source chain after calling the gateway to express execute a remote contract.
* @param txHash The transaction hash of the cross-chain call
* @param logIndex The log index for the cross-chain call
* @param refundAddress The address where refunds, if any, should be sent
*/
function addNativeExpressGas(
bytes32 txHash,
uint256 logIndex,
address refundAddress
) external payable;
/**
* @notice Updates the gas price for a specific chain.
* @dev This function is called by the gas oracle to update the gas prices for a specific chains.
* @param chains Array of chain names
* @param gasUpdates Array of gas updates
*/
function updateGasInfo(string[] calldata chains, GasInfo[] calldata gasUpdates) external;
/**
* @notice Allows the gasCollector to collect accumulated fees from the contract.
* @dev Use address(0) as the token address for native currency.
* @param receiver The address to receive the collected fees
* @param tokens Array of token addresses to be collected
* @param amounts Array of amounts to be collected for each respective token address
*/
function collectFees(
address payable receiver,
address[] calldata tokens,
uint256[] calldata amounts
) external;
/**
* @notice Refunds gas payment to the receiver in relation to a specific cross-chain transaction.
* @dev Only callable by the gasCollector.
* @dev Use address(0) as the token address to refund native currency.
* @param txHash The transaction hash of the cross-chain call
* @param logIndex The log index for the cross-chain call
* @param receiver The address to receive the refund
* @param token The token address to be refunded
* @param amount The amount to refund
*/
function refund(
bytes32 txHash,
uint256 logIndex,
address payable receiver,
address token,
uint256 amount
) external;
/**
* @notice Returns the address of the designated gas collector.
* @return address of the gas collector
*/
function gasCollector() external returns (address);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @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);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// General interface for upgradable contracts
interface IContractIdentifier {
/**
* @notice Returns the contract ID. It can be used as a check during upgrades.
* @dev Meant to be overridden in derived contracts.
* @return bytes32 The contract ID
*/
function contractId() external pure returns (bytes32);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IContractIdentifier } from './IContractIdentifier.sol';
interface IImplementation is IContractIdentifier {
error NotProxy();
function setup(bytes calldata data) external;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { GasEstimationType, GasInfo } from '../types/GasEstimationTypes.sol';
/**
* @title IInterchainGasEstimation Interface
* @notice This is an interface for the InterchainGasEstimation contract
* which allows for estimating gas fees for cross-chain communication on the Axelar network.
*/
interface IInterchainGasEstimation {
error UnsupportedEstimationType(GasEstimationType gasEstimationType);
/**
* @notice Event emitted when the gas price for a specific chain is updated.
* @param chain The name of the chain
* @param info The gas info for the chain
*/
event GasInfoUpdated(string chain, GasInfo info);
/**
* @notice Returns the gas price for a specific chain.
* @param chain The name of the chain
* @return gasInfo The gas info for the chain
*/
function getGasInfo(string calldata chain) external view returns (GasInfo memory);
/**
* @notice Estimates the gas fee for a cross-chain contract call.
* @param destinationChain Axelar registered name of the destination chain
* @param destinationAddress Destination contract address being called
* @param executionGasLimit The gas limit to be used for the destination contract execution,
* e.g. pass in 200k if your app consumes needs upto 200k for this contract call
* @param params Additional parameters for the gas estimation
* @return gasEstimate The cross-chain gas estimate, in terms of source chain's native gas token that should be forwarded to the gas service.
*/
function estimateGasFee(
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
uint256 executionGasLimit,
bytes calldata params
) external view returns (uint256 gasEstimate);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IOwnable Interface
* @notice IOwnable is an interface that abstracts the implementation of a
* contract with ownership control features. It's commonly used in upgradable
* contracts and includes the functionality to get current owner, transfer
* ownership, and propose and accept ownership.
*/
interface IOwnable {
error NotOwner();
error InvalidOwner();
error InvalidOwnerAddress();
event OwnershipTransferStarted(address indexed newOwner);
event OwnershipTransferred(address indexed newOwner);
/**
* @notice Returns the current owner of the contract.
* @return address The address of the current owner
*/
function owner() external view returns (address);
/**
* @notice Returns the address of the pending owner of the contract.
* @return address The address of the pending owner
*/
function pendingOwner() external view returns (address);
/**
* @notice Transfers ownership of the contract to a new address
* @param newOwner The address to transfer ownership to
*/
function transferOwnership(address newOwner) external;
/**
* @notice Proposes to transfer the contract's ownership to a new address.
* The new owner needs to accept the ownership explicitly.
* @param newOwner The address to transfer ownership to
*/
function proposeOwnership(address newOwner) external;
/**
* @notice Transfers ownership to the pending owner.
* @dev Can only be called by the pending owner
*/
function acceptOwnership() external;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IOwnable } from './IOwnable.sol';
import { IImplementation } from './IImplementation.sol';
// General interface for upgradable contracts
interface IUpgradable is IOwnable, IImplementation {
error InvalidCodeHash();
error InvalidImplementation();
error SetupFailed();
event Upgraded(address indexed newImplementation);
function implementation() external view returns (address);
function upgrade(
address newImplementation,
bytes32 newImplementationCodeHash,
bytes calldata params
) external;
}
// 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);
}
}
{
"compilationTarget": {
"src/periphery/astrobot-bridge/AstrobotBridgeEthereum.sol": "AstrobotNFTBridgeETH"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"gateway_","type":"address"},{"internalType":"address","name":"gasService_","type":"address"},{"internalType":"address","name":"astrobotNFTAddress_","type":"address"},{"internalType":"string","name":"baseChain_","type":"string"},{"internalType":"string","name":"baseBridgeAddress_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"NotApprovedByGateway","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NFTBridged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"BURN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"astrobotNFT","outputs":[{"internalType":"contract IAstrobotNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseBridgeAddress","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseChain","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"bridgeNFT","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"commandId","type":"bytes32"},{"internalType":"string","name":"sourceChain","type":"string"},{"internalType":"string","name":"sourceAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gasService","outputs":[{"internalType":"contract IAxelarGasService","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gateway","outputs":[{"internalType":"contract IAxelarGateway","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]