ETH Price: $2,453.97 (-0.87%)

Contract

0x440B118f34d6224B20b4641835AC9161BD4f0994

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Sponsored

Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
1136527062023-12-18 12:56:29300 days ago1702904189  Contract Creation0 ETH

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
InterchainTokenFactory

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 1000 runs

Other Settings:
london EvmVersion
File 1 of 36 : InterchainTokenFactory.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { AddressBytes } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/libs/AddressBytes.sol';
import { SafeTokenTransfer, SafeTokenTransferFrom, SafeTokenCall } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/libs/SafeTransfer.sol';
import { Multicall } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/utils/Multicall.sol';
import { Upgradable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/upgradable/Upgradable.sol';
import { IAxelarGateway } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol';

import { IInterchainTokenService } from './interfaces/IInterchainTokenService.sol';
import { IInterchainTokenFactory } from './interfaces/IInterchainTokenFactory.sol';
import { ITokenManagerType } from './interfaces/ITokenManagerType.sol';
import { ITokenManager } from './interfaces/ITokenManager.sol';
import { IInterchainToken } from './interfaces/IInterchainToken.sol';

/**
 * @title InterchainTokenFactory
 * @notice This contract is responsible for deploying new interchain tokens and managing their token managers.
 */
contract InterchainTokenFactory is IInterchainTokenFactory, ITokenManagerType, Multicall, Upgradable {
    using AddressBytes for bytes;
    using AddressBytes for address;
    using SafeTokenTransfer for IInterchainToken;
    using SafeTokenTransferFrom for IInterchainToken;
    using SafeTokenCall for IInterchainToken;

    IInterchainTokenService public immutable interchainTokenService;
    bytes32 public immutable chainNameHash;
    IAxelarGateway public immutable gateway;

    bytes32 private constant CONTRACT_ID = keccak256('interchain-token-factory');
    bytes32 internal constant PREFIX_CANONICAL_TOKEN_SALT = keccak256('canonical-token-salt');
    bytes32 internal constant PREFIX_INTERCHAIN_TOKEN_SALT = keccak256('interchain-token-salt');
    address private constant TOKEN_FACTORY_DEPLOYER = address(0);

    /**
     * @notice Constructs the InterchainTokenFactory contract.
     * @param interchainTokenService_ The address of the interchain token service.
     */
    constructor(address interchainTokenService_) {
        if (interchainTokenService_ == address(0)) revert ZeroAddress();

        interchainTokenService = IInterchainTokenService(interchainTokenService_);

        chainNameHash = interchainTokenService.chainNameHash();
        gateway = interchainTokenService.gateway();
    }

    /**
     * @notice Getter for the contract id.
     * @return bytes32 The contract id of this contract.
     */
    function contractId() external pure returns (bytes32) {
        return CONTRACT_ID;
    }

    /**
     * @notice Calculates the salt for an interchain token.
     * @param chainNameHash_ The hash of the chain name.
     * @param deployer The address of the deployer.
     * @param salt A unique identifier to generate the salt.
     * @return bytes32 The calculated salt for the interchain token.
     */
    function interchainTokenSalt(bytes32 chainNameHash_, address deployer, bytes32 salt) public pure returns (bytes32) {
        return keccak256(abi.encode(PREFIX_INTERCHAIN_TOKEN_SALT, chainNameHash_, deployer, salt));
    }

    /**
     * @notice Calculates the salt for a canonical interchain token.
     * @param chainNameHash_ The hash of the chain name.
     * @param tokenAddress The address of the token.
     * @return salt The calculated salt for the interchain token.
     */
    function canonicalInterchainTokenSalt(bytes32 chainNameHash_, address tokenAddress) public pure returns (bytes32 salt) {
        salt = keccak256(abi.encode(PREFIX_CANONICAL_TOKEN_SALT, chainNameHash_, tokenAddress));
    }

    /**
     * @notice Computes the ID for an interchain token based on the deployer and a salt.
     * @param deployer The address that deployed the interchain token.
     * @param salt A unique identifier used in the deployment process.
     * @return tokenId The ID of the interchain token.
     */
    function interchainTokenId(address deployer, bytes32 salt) public view returns (bytes32 tokenId) {
        tokenId = interchainTokenService.interchainTokenId(TOKEN_FACTORY_DEPLOYER, interchainTokenSalt(chainNameHash, deployer, salt));
    }

    /**
     * @notice Computes the ID for a canonical interchain token based on its address.
     * @param tokenAddress The address of the canonical interchain token.
     * @return tokenId The ID of the canonical interchain token.
     */
    function canonicalInterchainTokenId(address tokenAddress) public view returns (bytes32 tokenId) {
        tokenId = interchainTokenService.interchainTokenId(
            TOKEN_FACTORY_DEPLOYER,
            canonicalInterchainTokenSalt(chainNameHash, tokenAddress)
        );
    }

    /**
     * @notice Retrieves the address of an interchain token based on the deployer and a salt.
     * @param deployer The address that deployed the interchain token.
     * @param salt A unique identifier used in the deployment process.
     * @return tokenAddress The address of the interchain token.
     */
    function interchainTokenAddress(address deployer, bytes32 salt) public view returns (address tokenAddress) {
        tokenAddress = interchainTokenService.interchainTokenAddress(interchainTokenId(deployer, salt));
    }

    /**
     * @notice Deploys a new interchain token with specified parameters.
     * @dev Creates a new token and optionally mints an initial amount to a specified minter.
     * @param salt The unique salt for deploying the token.
     * @param name The name of the token.
     * @param symbol The symbol of the token.
     * @param decimals The number of decimals for the token.
     * @param initialSupply The amount of tokens to mint initially (can be zero).
     * @param minter The address to receive the initially minted tokens.
     * @return tokenId The tokenId corresponding to the deployed InterchainToken.
     */
    function deployInterchainToken(
        bytes32 salt,
        string calldata name,
        string calldata symbol,
        uint8 decimals,
        uint256 initialSupply,
        address minter
    ) external payable returns (bytes32 tokenId) {
        address sender = msg.sender;
        salt = interchainTokenSalt(chainNameHash, sender, salt);
        bytes memory minterBytes = new bytes(0);

        if (initialSupply > 0) {
            minterBytes = address(this).toBytes();
        } else if (minter != address(0)) {
            minterBytes = minter.toBytes();
        }

        tokenId = _deployInterchainToken(salt, '', name, symbol, decimals, minterBytes, 0);

        if (initialSupply > 0) {
            IInterchainToken token = IInterchainToken(interchainTokenService.interchainTokenAddress(tokenId));
            ITokenManager tokenManager = ITokenManager(interchainTokenService.tokenManagerAddress(tokenId));

            token.mint(sender, initialSupply);

            token.transferMintership(minter);
            tokenManager.removeFlowLimiter(address(this));

            // If minter == address(0), we still set it as a flow limiter for consistency with the remote token manager.
            tokenManager.addFlowLimiter(minter);

            tokenManager.transferOperatorship(minter);
        }
    }

    /**
     * @notice Deploys a remote interchain token on a specified destination chain.
     * @param originalChainName The name of the chain where the token originally exists.
     * @param salt The unique salt for deploying the token.
     * @param minter The address to distribute the token on the destination chain.
     * @param destinationChain The name of the destination chain.
     * @param gasValue The amount of gas to send for the deployment.
     * @return tokenId The tokenId corresponding to the deployed InterchainToken.
     */
    function deployRemoteInterchainToken(
        string calldata originalChainName,
        bytes32 salt,
        address minter,
        string memory destinationChain,
        uint256 gasValue
    ) external payable returns (bytes32 tokenId) {
        string memory tokenName;
        string memory tokenSymbol;
        uint8 tokenDecimals;
        bytes memory minter_ = new bytes(0);

        {
            bytes32 chainNameHash_;
            if (bytes(originalChainName).length == 0) {
                chainNameHash_ = chainNameHash;
            } else {
                chainNameHash_ = keccak256(bytes(originalChainName));
            }

            address sender = msg.sender;
            salt = interchainTokenSalt(chainNameHash_, sender, salt);
            tokenId = interchainTokenService.interchainTokenId(TOKEN_FACTORY_DEPLOYER, salt);

            IInterchainToken token = IInterchainToken(interchainTokenService.interchainTokenAddress(tokenId));

            tokenName = token.name();
            tokenSymbol = token.symbol();
            tokenDecimals = token.decimals();

            if (minter != address(0)) {
                if (!token.isMinter(minter)) revert NotMinter(minter);

                minter_ = minter.toBytes();
            }
        }

        tokenId = _deployInterchainToken(salt, destinationChain, tokenName, tokenSymbol, tokenDecimals, minter_, gasValue);
    }

    /**
     * @notice Deploys a new interchain token with specified parameters.
     * @param salt The unique salt for deploying the token.
     * @param destinationChain The name of the destination chain.
     * @param tokenName The name of the token.
     * @param tokenSymbol The symbol of the token.
     * @param tokenDecimals The number of decimals for the token.
     * @param minter The address to receive the initially minted tokens.
     * @param gasValue The amount of gas to send for the transfer.
     * @return tokenId The tokenId corresponding to the deployed InterchainToken.
     */
    function _deployInterchainToken(
        bytes32 salt,
        string memory destinationChain,
        string memory tokenName,
        string memory tokenSymbol,
        uint8 tokenDecimals,
        bytes memory minter,
        uint256 gasValue
    ) internal returns (bytes32 tokenId) {
        // slither-disable-next-line arbitrary-send-eth
        tokenId = interchainTokenService.deployInterchainToken{ value: gasValue }(
            salt,
            destinationChain,
            tokenName,
            tokenSymbol,
            tokenDecimals,
            minter,
            gasValue
        );
    }

    /**
     * @notice Registers a canonical token as an interchain token and deploys its token manager.
     * @param tokenAddress The address of the canonical token.
     * @return tokenId The tokenId corresponding to the registered canonical token.
     */
    function registerCanonicalInterchainToken(address tokenAddress) external payable returns (bytes32 tokenId) {
        bytes memory params = abi.encode('', tokenAddress);

        if (_isGatewayToken(tokenAddress)) revert GatewayToken(tokenAddress);

        bytes32 salt = canonicalInterchainTokenSalt(chainNameHash, tokenAddress);
        tokenId = interchainTokenService.deployTokenManager(salt, '', TokenManagerType.LOCK_UNLOCK, params, 0);
    }

    /**
     * @notice Deploys a canonical interchain token on a remote chain.
     * @param originalChain The name of the chain where the token originally exists.
     * @param originalTokenAddress The address of the original token on the original chain.
     * @param destinationChain The name of the chain where the token will be deployed.
     * @param gasValue The gas amount to be sent for deployment.
     * @return tokenId The tokenId corresponding to the deployed InterchainToken.
     */
    function deployRemoteCanonicalInterchainToken(
        string calldata originalChain,
        address originalTokenAddress,
        string calldata destinationChain,
        uint256 gasValue
    ) external payable returns (bytes32 tokenId) {
        bytes32 salt;
        IInterchainToken token;

        {
            bytes32 chainNameHash_;
            if (bytes(originalChain).length == 0) {
                chainNameHash_ = chainNameHash;
            } else {
                chainNameHash_ = keccak256(bytes(originalChain));
            }
            // This ensures that the token manager has been deployed by this address, so it's safe to trust it.
            salt = canonicalInterchainTokenSalt(chainNameHash_, originalTokenAddress);
            tokenId = interchainTokenService.interchainTokenId(TOKEN_FACTORY_DEPLOYER, salt);
            token = IInterchainToken(interchainTokenService.validTokenAddress(tokenId));
        }

        // The 3 lines below will revert if the token does not exist.
        string memory tokenName = token.name();
        string memory tokenSymbol = token.symbol();
        uint8 tokenDecimals = token.decimals();

        tokenId = _deployInterchainToken(salt, destinationChain, tokenName, tokenSymbol, tokenDecimals, '', gasValue);
    }

    /**
     * @notice Checks if a given token is a gateway token.
     * @param token The address of the token to check.
     * @return bool True if the token is a gateway token, false otherwise.
     */
    function _isGatewayToken(address token) internal view returns (bool) {
        string memory symbol = IInterchainToken(token).symbol();
        return token == gateway.tokenAddresses(symbol);
    }
}

File 2 of 36 : IAxelarExecutable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IAxelarGateway } from './IAxelarGateway.sol';

interface IAxelarExecutable {
    error InvalidAddress();
    error NotApprovedByGateway();

    function gateway() external view returns (IAxelarGateway);

    function execute(
        bytes32 commandId,
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes calldata payload
    ) external;

    function executeWithToken(
        bytes32 commandId,
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes calldata payload,
        string calldata tokenSymbol,
        uint256 amount
    ) external;
}

File 3 of 36 : IAxelarExpressExecutable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IAxelarExecutable } from './IAxelarExecutable.sol';

/**
 * @title IAxelarExpressExecutable
 * @notice Interface for the Axelar Express Executable contract.
 */
interface IAxelarExpressExecutable is IAxelarExecutable {
    // Custom errors
    error AlreadyExecuted();
    error InsufficientValue();
    error ExpressExecutorAlreadySet();

    /**
     * @notice Emitted when an express execution is successfully performed.
     * @param commandId The unique identifier for the command.
     * @param sourceChain The source chain.
     * @param sourceAddress The source address.
     * @param payloadHash The hash of the payload.
     * @param expressExecutor The address of the express executor.
     */
    event ExpressExecuted(
        bytes32 indexed commandId,
        string sourceChain,
        string sourceAddress,
        bytes32 payloadHash,
        address indexed expressExecutor
    );

    /**
     * @notice Emitted when an express execution with a token is successfully performed.
     * @param commandId The unique identifier for the command.
     * @param sourceChain The source chain.
     * @param sourceAddress The source address.
     * @param payloadHash The hash of the payload.
     * @param symbol The token symbol.
     * @param amount The amount of tokens.
     * @param expressExecutor The address of the express executor.
     */
    event ExpressExecutedWithToken(
        bytes32 indexed commandId,
        string sourceChain,
        string sourceAddress,
        bytes32 payloadHash,
        string symbol,
        uint256 indexed amount,
        address indexed expressExecutor
    );

    /**
     * @notice Emitted when an express execution is fulfilled.
     * @param commandId The commandId for the contractCall.
     * @param sourceChain The source chain.
     * @param sourceAddress The source address.
     * @param payloadHash The hash of the payload.
     * @param expressExecutor The address of the express executor.
     */
    event ExpressExecutionFulfilled(
        bytes32 indexed commandId,
        string sourceChain,
        string sourceAddress,
        bytes32 payloadHash,
        address indexed expressExecutor
    );

    /**
     * @notice Emitted when an express execution with a token is fulfilled.
     * @param commandId The commandId for the contractCallWithToken.
     * @param sourceChain The source chain.
     * @param sourceAddress The source address.
     * @param payloadHash The hash of the payload.
     * @param symbol The token symbol.
     * @param amount The amount of tokens.
     * @param expressExecutor The address of the express executor.
     */
    event ExpressExecutionWithTokenFulfilled(
        bytes32 indexed commandId,
        string sourceChain,
        string sourceAddress,
        bytes32 payloadHash,
        string symbol,
        uint256 indexed amount,
        address indexed expressExecutor
    );

    /**
     * @notice Returns the express executor for a given command.
     * @param commandId The commandId for the contractCall.
     * @param sourceChain The source chain.
     * @param sourceAddress The source address.
     * @param payloadHash The hash of the payload.
     * @return expressExecutor The address of the express executor.
     */
    function getExpressExecutor(
        bytes32 commandId,
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes32 payloadHash
    ) external view returns (address expressExecutor);

    /**
     * @notice Returns the express executor with token for a given command.
     * @param commandId The commandId for the contractCallWithToken.
     * @param sourceChain The source chain.
     * @param sourceAddress The source address.
     * @param payloadHash The hash of the payload.
     * @param symbol The token symbol.
     * @param amount The amount of tokens.
     * @return expressExecutor The address of the express executor.
     */
    function getExpressExecutorWithToken(
        bytes32 commandId,
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes32 payloadHash,
        string calldata symbol,
        uint256 amount
    ) external view returns (address expressExecutor);

    /**
     * @notice Express executes a contract call.
     * @param commandId The commandId for the contractCall.
     * @param sourceChain The source chain.
     * @param sourceAddress The source address.
     * @param payload The payload data.
     */
    function expressExecute(
        bytes32 commandId,
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes calldata payload
    ) external payable;

    /**
     * @notice Express executes a contract call with token.
     * @param commandId The commandId for the contractCallWithToken.
     * @param sourceChain The source chain.
     * @param sourceAddress The source address.
     * @param payload The payload data.
     * @param symbol The token symbol.
     * @param amount The amount of token.
     */
    function expressExecuteWithToken(
        bytes32 commandId,
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes calldata payload,
        string calldata symbol,
        uint256 amount
    ) external payable;
}

File 4 of 36 : IAxelarGateway.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IGovernable } from './IGovernable.sol';
import { IImplementation } from './IImplementation.sol';

interface IAxelarGateway is IImplementation, IGovernable {
    /**********\
    |* Errors *|
    \**********/

    error NotSelf();
    error InvalidCodeHash();
    error SetupFailed();
    error InvalidAuthModule();
    error InvalidTokenDeployer();
    error InvalidAmount();
    error InvalidChainId();
    error InvalidCommands();
    error TokenDoesNotExist(string symbol);
    error TokenAlreadyExists(string symbol);
    error TokenDeployFailed(string symbol);
    error TokenContractDoesNotExist(address token);
    error BurnFailed(string symbol);
    error MintFailed(string symbol);
    error InvalidSetMintLimitsParams();
    error ExceedMintLimit(string symbol);

    /**********\
    |* Events *|
    \**********/

    event TokenSent(
        address indexed sender,
        string destinationChain,
        string destinationAddress,
        string symbol,
        uint256 amount
    );

    event ContractCall(
        address indexed sender,
        string destinationChain,
        string destinationContractAddress,
        bytes32 indexed payloadHash,
        bytes payload
    );

    event ContractCallWithToken(
        address indexed sender,
        string destinationChain,
        string destinationContractAddress,
        bytes32 indexed payloadHash,
        bytes payload,
        string symbol,
        uint256 amount
    );

    event Executed(bytes32 indexed commandId);

    event TokenDeployed(string symbol, address tokenAddresses);

    event ContractCallApproved(
        bytes32 indexed commandId,
        string sourceChain,
        string sourceAddress,
        address indexed contractAddress,
        bytes32 indexed payloadHash,
        bytes32 sourceTxHash,
        uint256 sourceEventIndex
    );

    event ContractCallApprovedWithMint(
        bytes32 indexed commandId,
        string sourceChain,
        string sourceAddress,
        address indexed contractAddress,
        bytes32 indexed payloadHash,
        string symbol,
        uint256 amount,
        bytes32 sourceTxHash,
        uint256 sourceEventIndex
    );

    event ContractCallExecuted(bytes32 indexed commandId);

    event TokenMintLimitUpdated(string symbol, uint256 limit);

    event OperatorshipTransferred(bytes newOperatorsData);

    event Upgraded(address indexed implementation);

    /********************\
    |* Public Functions *|
    \********************/

    function sendToken(
        string calldata destinationChain,
        string calldata destinationAddress,
        string calldata symbol,
        uint256 amount
    ) external;

    function callContract(
        string calldata destinationChain,
        string calldata contractAddress,
        bytes calldata payload
    ) external;

    function callContractWithToken(
        string calldata destinationChain,
        string calldata contractAddress,
        bytes calldata payload,
        string calldata symbol,
        uint256 amount
    ) external;

    function isContractCallApproved(
        bytes32 commandId,
        string calldata sourceChain,
        string calldata sourceAddress,
        address contractAddress,
        bytes32 payloadHash
    ) external view returns (bool);

    function isContractCallAndMintApproved(
        bytes32 commandId,
        string calldata sourceChain,
        string calldata sourceAddress,
        address contractAddress,
        bytes32 payloadHash,
        string calldata symbol,
        uint256 amount
    ) external view returns (bool);

    function validateContractCall(
        bytes32 commandId,
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes32 payloadHash
    ) external returns (bool);

    function validateContractCallAndMint(
        bytes32 commandId,
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes32 payloadHash,
        string calldata symbol,
        uint256 amount
    ) external returns (bool);

    /***********\
    |* Getters *|
    \***********/

    function authModule() external view returns (address);

    function tokenDeployer() external view returns (address);

    function tokenMintLimit(string memory symbol) external view returns (uint256);

    function tokenMintAmount(string memory symbol) external view returns (uint256);

    function allTokensFrozen() external view returns (bool);

    function implementation() external view returns (address);

    function tokenAddresses(string memory symbol) external view returns (address);

    function tokenFrozen(string memory symbol) external view returns (bool);

    function isCommandExecuted(bytes32 commandId) external view returns (bool);

    /************************\
    |* Governance Functions *|
    \************************/

    function setTokenMintLimits(string[] calldata symbols, uint256[] calldata limits) external;

    function upgrade(
        address newImplementation,
        bytes32 newImplementationCodeHash,
        bytes calldata setupParams
    ) external;

    /**********************\
    |* External Functions *|
    \**********************/

    function execute(bytes calldata input) external;
}

File 5 of 36 : IAxelarValuedExpressExecutable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IAxelarExpressExecutable } from './IAxelarExpressExecutable.sol';

/**
 * @title IAxelarValuedExpressExecutable
 * @dev Interface for the Axelar Valued Express Executable contract.
 */
interface IAxelarValuedExpressExecutable is IAxelarExpressExecutable {
    /**
     * @dev Returns the value (token address and amount) associated with a contract call
     * @param sourceChain The source blockchain.
     * @param sourceAddress The source address.
     * @param payload The payload data.
     * @return tokenAddress The address of the token used.
     * @return value The value associated with the contract call.
     */
    function contractCallValue(
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes calldata payload
    ) external view returns (address tokenAddress, uint256 value);

    /**
     * @dev Returns the value (token address and amount) associated with a contract call with token.
     * @param sourceChain The source blockchain.
     * @param sourceAddress The source address.
     * @param payload The payload data.
     * @param symbol The token symbol.
     * @param amount The amount of tokens.
     * @return tokenAddress The address of the token used.
     * @return value The value associated with the contract call.
     */
    function contractCallWithTokenValue(
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes calldata payload,
        string calldata symbol,
        uint256 amount
    ) external view returns (address tokenAddress, uint256 value);
}

File 6 of 36 : IContractIdentifier.sol
// 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);
}

File 7 of 36 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    error InvalidAccount();

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 8 of 36 : IGovernable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title IGovernable Interface
 * @notice This is an interface used by the AxelarGateway contract to manage governance and mint limiter roles.
 */
interface IGovernable {
    error NotGovernance();
    error NotMintLimiter();
    error InvalidGovernance();
    error InvalidMintLimiter();

    event GovernanceTransferred(address indexed previousGovernance, address indexed newGovernance);
    event MintLimiterTransferred(address indexed previousGovernance, address indexed newGovernance);

    /**
     * @notice Returns the governance address.
     * @return address of the governance
     */
    function governance() external view returns (address);

    /**
     * @notice Returns the mint limiter address.
     * @return address of the mint limiter
     */
    function mintLimiter() external view returns (address);

    /**
     * @notice Transfer the governance role to another address.
     * @param newGovernance The new governance address
     */
    function transferGovernance(address newGovernance) external;

    /**
     * @notice Transfer the mint limiter role to another address.
     * @param newGovernance The new mint limiter address
     */
    function transferMintLimiter(address newGovernance) external;
}

File 9 of 36 : IImplementation.sol
// 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;
}

File 10 of 36 : IInterchainAddressTracker.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IContractIdentifier } from './IContractIdentifier.sol';

/**
 * @title IInterchainAddressTracker
 * @dev Manages trusted addresses by chain, keeps track of addresses supported by the Axelar gateway contract
 */
interface IInterchainAddressTracker {
    error ZeroAddress();
    error LengthMismatch();
    error ZeroStringLength();
    error UntrustedChain();

    event TrustedAddressSet(string chain, string address_);
    event TrustedAddressRemoved(string chain);

    /**
     * @dev Gets the name of the chain this is deployed at
     */
    function chainName() external view returns (string memory);

    /**
     * @dev Gets the trusted address at a remote chain
     * @param chain Chain name of the remote chain
     * @return trustedAddress_ The trusted address for the chain. Returns '' if the chain is untrusted
     */
    function trustedAddress(string memory chain) external view returns (string memory trustedAddress_);

    /**
     * @dev Gets the trusted address hash for a chain
     * @param chain Chain name
     * @return trustedAddressHash_ the hash of the trusted address for that chain
     */
    function trustedAddressHash(string memory chain) external view returns (bytes32 trustedAddressHash_);

    /**
     * @dev Checks whether the interchain sender is a trusted address
     * @param chain Chain name of the sender
     * @param address_ Address of the sender
     * @return bool true if the sender chain/address are trusted, false otherwise
     */
    function isTrustedAddress(string calldata chain, string calldata address_) external view returns (bool);
}

File 11 of 36 : IMulticall.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title IMulticall
 * @notice This contract is a multi-functional smart contract which allows for multiple
 * contract calls in a single transaction.
 */
interface IMulticall {
    error MulticallFailed();

    /**
     * @notice Performs multiple delegate calls and returns the results of all calls as an array
     * @dev This function requires that the contract has sufficient balance for the delegate calls.
     * If any of the calls fail, the function will revert with the failure message.
     * @param data An array of encoded function calls
     * @return results An bytes array with the return data of each function call
     */
    function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
}

File 12 of 36 : IOwnable.sol
// 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;
}

File 13 of 36 : IPausable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title Pausable
 * @notice This contract provides a mechanism to halt the execution of specific functions
 * if a pause condition is activated.
 */
interface IPausable {
    event Paused(address indexed account);
    event Unpaused(address indexed account);

    error Pause();
    error NotPaused();

    /**
     * @notice Check if the contract is paused
     * @return paused A boolean representing the pause status. True if paused, false otherwise.
     */
    function paused() external view returns (bool);
}

File 14 of 36 : IRolesBase.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title IRolesBase Interface
 * @notice IRolesBase is an interface that abstracts the implementation of a
 * contract with role control internal functions.
 */
interface IRolesBase {
    error MissingRole(address account, uint8 role);
    error MissingAllRoles(address account, uint256 accountRoles);
    error MissingAnyOfRoles(address account, uint256 accountRoles);

    error InvalidProposedRoles(address fromAccount, address toAccount, uint256 accountRoles);

    event RolesProposed(address indexed fromAccount, address indexed toAccount, uint256 accountRoles);
    event RolesAdded(address indexed account, uint256 accountRoles);
    event RolesRemoved(address indexed account, uint256 accountRoles);

    /**
     * @notice Checks if an account has a role.
     * @param account The address to check
     * @param role The role to check
     * @return True if the account has the role, false otherwise
     */
    function hasRole(address account, uint8 role) external view returns (bool);
}

File 15 of 36 : IUpgradable.sol
// 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;
}

File 16 of 36 : AddressBytes.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title AddressBytesUtils
 * @dev This library provides utility functions to convert between `address` and `bytes`.
 */
library AddressBytes {
    error InvalidBytesLength(bytes bytesAddress);

    /**
     * @dev Converts a bytes address to an address type.
     * @param bytesAddress The bytes representation of an address
     * @return addr The converted address
     */
    function toAddress(bytes memory bytesAddress) internal pure returns (address addr) {
        if (bytesAddress.length != 20) revert InvalidBytesLength(bytesAddress);

        assembly {
            addr := mload(add(bytesAddress, 20))
        }
    }

    /**
     * @dev Converts an address to bytes.
     * @param addr The address to be converted
     * @return bytesAddress The bytes representation of the address
     */
    function toBytes(address addr) internal pure returns (bytes memory bytesAddress) {
        bytesAddress = new bytes(20);
        // we can test if using a single 32 byte variable that is the address with the length together and using one mstore would be slightly cheaper.
        assembly {
            mstore(add(bytesAddress, 20), addr)
            mstore(bytesAddress, 20)
        }
    }
}

File 17 of 36 : SafeTransfer.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC20 } from '../interfaces/IERC20.sol';

error TokenTransferFailed();

/*
 * @title SafeTokenCall
 * @dev This library is used for performing safe token transfers.
 */
library SafeTokenCall {
    /*
     * @notice Make a safe call to a token contract.
     * @param token The token contract to interact with.
     * @param callData The function call data.
     * @throws TokenTransferFailed error if transfer of token is not successful.
     */
    function safeCall(IERC20 token, bytes memory callData) internal {
        (bool success, bytes memory returnData) = address(token).call(callData);
        bool transferred = success && (returnData.length == uint256(0) || abi.decode(returnData, (bool)));

        if (!transferred || address(token).code.length == 0) revert TokenTransferFailed();
    }
}

/*
 * @title SafeTokenTransfer
 * @dev This library safely transfers tokens from the contract to a recipient.
 */
library SafeTokenTransfer {
    /*
     * @notice Transfer tokens to a recipient.
     * @param token The token contract.
     * @param receiver The recipient of the tokens.
     * @param amount The amount of tokens to transfer.
     */
    function safeTransfer(
        IERC20 token,
        address receiver,
        uint256 amount
    ) internal {
        SafeTokenCall.safeCall(token, abi.encodeWithSelector(IERC20.transfer.selector, receiver, amount));
    }
}

/*
 * @title SafeTokenTransferFrom
 * @dev This library helps to safely transfer tokens on behalf of a token holder.
 */
library SafeTokenTransferFrom {
    /*
     * @notice Transfer tokens on behalf of a token holder.
     * @param token The token contract.
     * @param from The address of the token holder.
     * @param to The address the tokens are to be sent to.
     * @param amount The amount of tokens to be transferred.
     */
    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        SafeTokenCall.safeCall(token, abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, amount));
    }
}

File 18 of 36 : Implementation.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IImplementation } from '../interfaces/IImplementation.sol';

/**
 * @title Implementation
 * @notice This contract serves as a base for other contracts and enforces a proxy-first access restriction.
 * @dev Derived contracts must implement the setup function.
 */
abstract contract Implementation is IImplementation {
    address private immutable implementationAddress;

    /**
     * @dev Contract constructor that sets the implementation address to the address of this contract.
     */
    constructor() {
        implementationAddress = address(this);
    }

    /**
     * @dev Modifier to require the caller to be the proxy contract.
     * Reverts if the caller is the current contract (i.e., the implementation contract itself).
     */
    modifier onlyProxy() {
        if (implementationAddress == address(this)) revert NotProxy();
        _;
    }

    /**
     * @notice Initializes contract parameters.
     * This function is intended to be overridden by derived contracts.
     * The overriding function must have the onlyProxy modifier.
     * @param params The parameters to be used for initialization
     */
    function setup(bytes calldata params) external virtual;
}

File 19 of 36 : Upgradable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IImplementation } from '../interfaces/IImplementation.sol';
import { IUpgradable } from '../interfaces/IUpgradable.sol';
import { Ownable } from '../utils/Ownable.sol';
import { Implementation } from './Implementation.sol';

/**
 * @title Upgradable Contract
 * @notice This contract provides an interface for upgradable smart contracts and includes the functionality to perform upgrades.
 */
abstract contract Upgradable is Ownable, Implementation, IUpgradable {
    // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @notice Constructor sets the implementation address to the address of the contract itself
     * @dev This is used in the onlyProxy modifier to prevent certain functions from being called directly
     * on the implementation contract itself.
     * @dev The owner is initially set as address(1) because the actual owner is set within the proxy. It is not
     * set as the zero address because Ownable is designed to throw an error for ownership transfers to the zero address.
     */
    constructor() Ownable(address(1)) {}

    /**
     * @notice Returns the address of the current implementation
     * @return implementation_ Address of the current implementation
     */
    function implementation() public view returns (address implementation_) {
        assembly {
            implementation_ := sload(_IMPLEMENTATION_SLOT)
        }
    }

    /**
     * @notice Upgrades the contract to a new implementation
     * @param newImplementation The address of the new implementation contract
     * @param newImplementationCodeHash The codehash of the new implementation contract
     * @param params Optional setup parameters for the new implementation contract
     * @dev This function is only callable by the owner.
     */
    function upgrade(
        address newImplementation,
        bytes32 newImplementationCodeHash,
        bytes calldata params
    ) external override onlyOwner {
        if (IUpgradable(newImplementation).contractId() != IUpgradable(implementation()).contractId())
            revert InvalidImplementation();

        if (newImplementationCodeHash != newImplementation.codehash) revert InvalidCodeHash();

        emit Upgraded(newImplementation);

        if (params.length > 0) {
            // slither-disable-next-line controlled-delegatecall
            (bool success, ) = newImplementation.delegatecall(abi.encodeWithSelector(this.setup.selector, params));

            if (!success) revert SetupFailed();
        }

        assembly {
            sstore(_IMPLEMENTATION_SLOT, newImplementation)
        }
    }

    /**
     * @notice Sets up the contract with initial data
     * @param data Initialization data for the contract
     * @dev This function is only callable by the proxy contract.
     */
    function setup(bytes calldata data) external override(IImplementation, Implementation) onlyProxy {
        _setup(data);
    }

    /**
     * @notice Internal function to set up the contract with initial data
     * @param data Initialization data for the contract
     * @dev This function should be implemented in derived contracts.
     */
    function _setup(bytes calldata data) internal virtual {}
}

File 20 of 36 : Multicall.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IMulticall } from '../interfaces/IMulticall.sol';

/**
 * @title Multicall
 * @notice This contract is a multi-functional smart contract which allows for multiple
 * contract calls in a single transaction.
 */
contract Multicall is IMulticall {
    /**
     * @notice Performs multiple delegate calls and returns the results of all calls as an array
     * @dev This function requires that the contract has sufficient balance for the delegate calls.
     * If any of the calls fail, the function will revert with the failure message.
     * @param data An array of encoded function calls
     * @return results An bytes array with the return data of each function call
     */
    function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {
        results = new bytes[](data.length);
        bool success;
        bytes memory result;
        for (uint256 i = 0; i < data.length; ++i) {
            // slither-disable-next-line calls-loop,delegatecall-loop
            (success, result) = address(this).delegatecall(data[i]);

            if (!success) {
                if (result.length == 0) revert MulticallFailed();
                assembly {
                    revert(add(32, result), mload(result))
                }
            }

            results[i] = result;
        }
    }
}

File 21 of 36 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IOwnable } from '../interfaces/IOwnable.sol';

/**
 * @title Ownable
 * @notice A 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.
 *
 * The owner account is set through ownership transfer. This module makes
 * it possible to transfer the ownership of the contract to a new account in one
 * step, as well as to an interim pending owner. In the second flow the ownership does not
 * change until the pending owner accepts the ownership transfer.
 */
abstract contract Ownable is IOwnable {
    // keccak256('owner')
    bytes32 internal constant _OWNER_SLOT = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0;
    // keccak256('ownership-transfer')
    bytes32 internal constant _OWNERSHIP_TRANSFER_SLOT =
        0x9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d1;

    /**
     * @notice Initializes the contract by transferring ownership to the owner parameter.
     * @param _owner Address to set as the initial owner of the contract
     */
    constructor(address _owner) {
        _transferOwnership(_owner);
    }

    /**
     * @notice Modifier that throws an error if called by any account other than the owner.
     */
    modifier onlyOwner() {
        if (owner() != msg.sender) revert NotOwner();

        _;
    }

    /**
     * @notice Returns the current owner of the contract.
     * @return owner_ The current owner of the contract
     */
    function owner() public view returns (address owner_) {
        assembly {
            owner_ := sload(_OWNER_SLOT)
        }
    }

    /**
     * @notice Returns the pending owner of the contract.
     * @return owner_ The pending owner of the contract
     */
    function pendingOwner() public view returns (address owner_) {
        assembly {
            owner_ := sload(_OWNERSHIP_TRANSFER_SLOT)
        }
    }

    /**
     * @notice Transfers ownership of the contract to a new account `newOwner`.
     * @dev Can only be called by the current owner.
     * @param newOwner The address to transfer ownership to
     */
    function transferOwnership(address newOwner) external virtual onlyOwner {
        _transferOwnership(newOwner);
    }

    /**
     * @notice Propose to transfer ownership of the contract to a new account `newOwner`.
     * @dev Can only be called by the current owner. The ownership does not change
     * until the new owner accepts the ownership transfer.
     * @param newOwner The address to transfer ownership to
     */
    function proposeOwnership(address newOwner) external virtual onlyOwner {
        if (newOwner == address(0)) revert InvalidOwnerAddress();

        emit OwnershipTransferStarted(newOwner);

        assembly {
            sstore(_OWNERSHIP_TRANSFER_SLOT, newOwner)
        }
    }

    /**
     * @notice Accepts ownership of the contract.
     * @dev Can only be called by the pending owner
     */
    function acceptOwnership() external virtual {
        address newOwner = pendingOwner();
        if (newOwner != msg.sender) revert InvalidOwner();

        _transferOwnership(newOwner);
    }

    /**
     * @notice Internal function to transfer ownership of the contract to a new account `newOwner`.
     * @dev Called in the constructor to set the initial owner.
     * @param newOwner The address to transfer ownership to
     */
    function _transferOwnership(address newOwner) internal virtual {
        if (newOwner == address(0)) revert InvalidOwnerAddress();

        emit OwnershipTransferred(newOwner);

        assembly {
            sstore(_OWNER_SLOT, newOwner)
            sstore(_OWNERSHIP_TRANSFER_SLOT, 0)
        }
    }
}

File 22 of 36 : IAddressTracker.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IInterchainAddressTracker } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IInterchainAddressTracker.sol';

/**
 * @title IAddressTracker Interface
 * @notice This interface allows setting and removing a trusted address for a specific chain.
 * @dev Extends the IInterchainAddressTracker interface.
 */
interface IAddressTracker is IInterchainAddressTracker {
    /**
     * @notice Sets the trusted address for the specified chain.
     * @param chain Chain name to be trusted.
     * @param address_ Trusted address to be added for the chain.
     */
    function setTrustedAddress(string memory chain, string memory address_) external;

    /**
     * @notice Remove the trusted address of the chain.
     * @param chain Chain name to remove the trusted address for.
     */
    function removeTrustedAddress(string calldata chain) external;
}

File 23 of 36 : IBaseTokenManager.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title IBaseTokenManager
 * @notice This contract is defines the base token manager interface implemented by all token managers.
 */
interface IBaseTokenManager {
    /**
     * @notice A function that returns the token id.
     */
    function interchainTokenId() external view returns (bytes32);

    /**
     * @notice A function that should return the address of the token.
     * Must be overridden in the inheriting contract.
     * @return address address of the token.
     */
    function tokenAddress() external view returns (address);

    /**
     * @notice A function that should return the token address from the init params.
     */
    function getTokenAddressFromParams(bytes calldata params) external pure returns (address);
}

File 24 of 36 : IERC20MintableBurnable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title IERC20MintableBurnable Interface
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20MintableBurnable {
    /**
     * @notice Function to mint new tokens.
     * @dev Can only be called by the minter address.
     * @param to The address that will receive the minted tokens.
     * @param amount The amount of tokens to mint.
     */
    function mint(address to, uint256 amount) external;

    /**
     * @notice Function to burn tokens.
     * @dev Can only be called by the minter address.
     * @param from The address that will have its tokens burnt.
     * @param amount The amount of tokens to burn.
     */
    function burn(address from, uint256 amount) external;
}

File 25 of 36 : IERC20Named.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol';

/**
 * @title IERC20Named Interface
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20Named is IERC20 {
    /**
     * @notice Getter for the name of the token.
     * @return string Name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @notice Getter for the symbol of the token.
     * @return string The symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @notice Getter for the decimals of the token.
     * @return uint8 The decimals of the token.
     */
    function decimals() external view returns (uint8);
}

File 26 of 36 : IFlowLimit.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title FlowLimit Interface
 * @notice Interface for flow limit logic for interchain token transfers.
 */
interface IFlowLimit {
    error FlowLimitExceeded(uint256 limit, uint256 flowAmount, address tokenManager);

    event FlowLimitSet(bytes32 indexed tokenId, address operator, uint256 flowLimit_);

    /**
     * @notice Returns the current flow limit.
     * @return flowLimit_ The current flow limit value.
     */
    function flowLimit() external view returns (uint256 flowLimit_);

    /**
     * @notice Returns the current flow out amount.
     * @return flowOutAmount_ The current flow out amount.
     */
    function flowOutAmount() external view returns (uint256 flowOutAmount_);

    /**
     * @notice Returns the current flow in amount.
     * @return flowInAmount_ The current flow in amount.
     */
    function flowInAmount() external view returns (uint256 flowInAmount_);
}

File 27 of 36 : IInterchainToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IInterchainTokenStandard } from './IInterchainTokenStandard.sol';
import { IMinter } from './IMinter.sol';
import { IERC20MintableBurnable } from './IERC20MintableBurnable.sol';
import { IERC20Named } from './IERC20Named.sol';

/**
 * @title IInterchainToken interface
 * @dev Extends IInterchainTokenStandard and IMinter.
 */
interface IInterchainToken is IInterchainTokenStandard, IMinter, IERC20MintableBurnable, IERC20Named {
    error InterchainTokenServiceAddressZero();
    error TokenIdZero();
    error TokenNameEmpty();
    error TokenSymbolEmpty();
    error AlreadyInitialized();

    /**
     * @notice Getter for the interchain token service contract.
     * @dev Needs to be overwitten.
     * @return interchainTokenServiceAddress The interchain token service address.
     */
    function interchainTokenService() external view returns (address interchainTokenServiceAddress);

    /**
     * @notice Getter for the tokenId used for this token.
     * @dev Needs to be overwitten.
     * @return tokenId_ The tokenId for this token.
     */
    function interchainTokenId() external view returns (bytes32 tokenId_);

    /**
     * @notice Setup function to initialize contract parameters.
     * @param tokenId_ The tokenId of the token.
     * @param minter The address of the token minter.
     * @param tokenName The name of the token.
     * @param tokenSymbol The symbopl of the token.
     * @param tokenDecimals The decimals of the token.
     */
    function init(bytes32 tokenId_, address minter, string calldata tokenName, string calldata tokenSymbol, uint8 tokenDecimals) external;
}

File 28 of 36 : IInterchainTokenFactory.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IMulticall } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IMulticall.sol';
import { IUpgradable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IUpgradable.sol';

import { IInterchainTokenService } from './IInterchainTokenService.sol';

/**
 * @title IInterchainTokenFactory Interface
 * @notice This interface defines functions for deploying new interchain tokens and managing their token managers.
 */
interface IInterchainTokenFactory is IUpgradable, IMulticall {
    error ZeroAddress();
    error InvalidChainName();
    error NotMinter(address minter);
    error NotOperator(address operator);
    error GatewayToken(address tokenAddress);

    /**
     * @notice Returns the address of the interchain token service.
     * @return IInterchainTokenService The address of the interchain token service.
     */
    function interchainTokenService() external view returns (IInterchainTokenService);

    /**
     * @notice Returns the hash of the chain name.
     * @return bytes32 The hash of the chain name.
     */
    function chainNameHash() external view returns (bytes32);

    /**
     * @notice Calculates the salt for an interchain token.
     * @param chainNameHash_ The hash of the chain name.
     * @param deployer The address of the deployer.
     * @param salt A unique identifier to generate the salt.
     * @return bytes32 The calculated salt for the interchain token.
     */
    function interchainTokenSalt(bytes32 chainNameHash_, address deployer, bytes32 salt) external view returns (bytes32);

    /**
     * @notice Computes the ID for an interchain token based on the deployer and a salt.
     * @param deployer The address that deployed the interchain token.
     * @param salt A unique identifier used in the deployment process.
     * @return tokenId The ID of the interchain token.
     */
    function interchainTokenId(address deployer, bytes32 salt) external view returns (bytes32 tokenId);

    /**
     * @notice Retrieves the address of an interchain token based on the deployer and a salt.
     * @param deployer The address that deployed the interchain token.
     * @param salt A unique identifier used in the deployment process.
     * @return tokenAddress The address of the interchain token.
     */
    function interchainTokenAddress(address deployer, bytes32 salt) external view returns (address tokenAddress);

    /**
     * @notice Deploys a new interchain token with specified parameters.
     * @param salt The unique salt for deploying the token.
     * @param name The name of the token.
     * @param symbol The symbol of the token.
     * @param decimals The number of decimals for the token.
     * @param initialSupply The amount of tokens to mint initially (can be zero).
     * @param minter The address to receive the initially minted tokens.
     * @return tokenId The tokenId corresponding to the deployed InterchainToken.
     */
    function deployInterchainToken(
        bytes32 salt,
        string calldata name,
        string calldata symbol,
        uint8 decimals,
        uint256 initialSupply,
        address minter
    ) external payable returns (bytes32 tokenId);

    /**
     * @notice Deploys a remote interchain token on a specified destination chain.
     * @param originalChainName The name of the chain where the token originally exists.
     * @param salt The unique salt for deploying the token.
     * @param minter The address to distribute the token on the destination chain.
     * @param destinationChain The name of the destination chain.
     * @param gasValue The amount of gas to send for the deployment.
     * @return tokenId The tokenId corresponding to the deployed InterchainToken.
     */
    function deployRemoteInterchainToken(
        string calldata originalChainName,
        bytes32 salt,
        address minter,
        string memory destinationChain,
        uint256 gasValue
    ) external payable returns (bytes32 tokenId);

    /**
     * @notice Calculates the salt for a canonical interchain token.
     * @param chainNameHash_ The hash of the chain name.
     * @param tokenAddress The address of the token.
     * @return salt The calculated salt for the interchain token.
     */
    function canonicalInterchainTokenSalt(bytes32 chainNameHash_, address tokenAddress) external view returns (bytes32 salt);

    /**
     * @notice Computes the ID for a canonical interchain token based on its address.
     * @param tokenAddress The address of the canonical interchain token.
     * @return tokenId The ID of the canonical interchain token.
     */
    function canonicalInterchainTokenId(address tokenAddress) external view returns (bytes32 tokenId);

    /**
     * @notice Registers a canonical token as an interchain token and deploys its token manager.
     * @param tokenAddress The address of the canonical token.
     * @return tokenId The tokenId corresponding to the registered canonical token.
     */
    function registerCanonicalInterchainToken(address tokenAddress) external payable returns (bytes32 tokenId);

    /**
     * @notice Deploys a canonical interchain token on a remote chain.
     * @param originalChain The name of the chain where the token originally exists.
     * @param originalTokenAddress The address of the original token on the original chain.
     * @param destinationChain The name of the chain where the token will be deployed.
     * @param gasValue The gas amount to be sent for deployment.
     * @return tokenId The tokenId corresponding to the deployed canonical InterchainToken.
     */
    function deployRemoteCanonicalInterchainToken(
        string calldata originalChain,
        address originalTokenAddress,
        string calldata destinationChain,
        uint256 gasValue
    ) external payable returns (bytes32 tokenId);
}

File 29 of 36 : IInterchainTokenService.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IAxelarValuedExpressExecutable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarValuedExpressExecutable.sol';
import { IMulticall } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IMulticall.sol';
import { IPausable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IPausable.sol';
import { IUpgradable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IUpgradable.sol';

import { ITransmitInterchainToken } from './ITransmitInterchainToken.sol';
import { ITokenManagerType } from './ITokenManagerType.sol';
import { ITokenManagerImplementation } from './ITokenManagerImplementation.sol';
import { IOperator } from './IOperator.sol';
import { IAddressTracker } from './IAddressTracker.sol';

/**
 * @title IInterchainTokenService Interface
 * @notice Interface for the Interchain Token Service
 */
interface IInterchainTokenService is
    ITransmitInterchainToken,
    ITokenManagerType,
    ITokenManagerImplementation,
    IAxelarValuedExpressExecutable,
    IOperator,
    IPausable,
    IMulticall,
    IAddressTracker,
    IUpgradable
{
    error InvalidTokenManagerImplementationType(address implementation);
    error InvalidChainName();
    error NotRemoteService();
    error TokenManagerDoesNotExist(bytes32 tokenId);
    error NotToken(address caller, address token);
    error ExecuteWithInterchainTokenFailed(address contractAddress);
    error ExpressExecuteWithInterchainTokenFailed(address contractAddress);
    error GatewayToken();
    error TokenManagerDeploymentFailed(bytes error);
    error InterchainTokenDeploymentFailed(bytes error);
    error InvalidMessageType(uint256 messageType);
    error InvalidMetadataVersion(uint32 version);
    error ExecuteWithTokenNotSupported();
    error InvalidExpressMessageType(uint256 messageType);
    error TakeTokenFailed(bytes data);
    error GiveTokenFailed(bytes data);
    error TokenHandlerFailed(bytes data);
    error EmptyData();

    event InterchainTransfer(
        bytes32 indexed tokenId,
        address indexed sourceAddress,
        string destinationChain,
        bytes destinationAddress,
        uint256 amount,
        bytes32 indexed dataHash
    );
    event InterchainTransferReceived(
        bytes32 indexed commandId,
        bytes32 indexed tokenId,
        string sourceChain,
        bytes sourceAddress,
        address indexed destinationAddress,
        uint256 amount,
        bytes32 dataHash
    );
    event TokenManagerDeploymentStarted(
        bytes32 indexed tokenId,
        string destinationChain,
        TokenManagerType indexed tokenManagerType,
        bytes params
    );
    event InterchainTokenDeploymentStarted(
        bytes32 indexed tokenId,
        string tokenName,
        string tokenSymbol,
        uint8 tokenDecimals,
        bytes minter,
        string destinationChain
    );
    event TokenManagerDeployed(bytes32 indexed tokenId, address tokenManager, TokenManagerType indexed tokenManagerType, bytes params);
    event InterchainTokenDeployed(
        bytes32 indexed tokenId,
        address tokenAddress,
        address indexed minter,
        string name,
        string symbol,
        uint8 decimals
    );
    event InterchainTokenIdClaimed(bytes32 indexed tokenId, address indexed deployer, bytes32 indexed salt);

    /**
     * @notice Returns the address of the token manager deployer contract.
     * @return tokenManagerDeployerAddress The address of the token manager deployer contract.
     */
    function tokenManagerDeployer() external view returns (address tokenManagerDeployerAddress);

    /**
     * @notice Returns the address of the interchain token deployer contract.
     * @return interchainTokenDeployerAddress The address of the interchain token deployer contract.
     */
    function interchainTokenDeployer() external view returns (address interchainTokenDeployerAddress);

    /**
     * @notice Returns the address of TokenManager implementation.
     * @return tokenManagerAddress_ The address of the token manager contract.
     */
    function tokenManager() external view returns (address tokenManagerAddress_);

    /**
     * @notice Returns the address of TokenHandler implementation.
     * @return tokenHandlerAddress The address of the token handler contract.
     */
    function tokenHandler() external view returns (address tokenHandlerAddress);

    /**
     * @notice Returns the address of the interchain token factory.
     * @return address The address of the interchain token factory.
     */
    function interchainTokenFactory() external view returns (address);

    /**
     * @notice Returns the hash of the chain name.
     * @return bytes32 The hash of the chain name.
     */
    function chainNameHash() external view returns (bytes32);

    /**
     * @notice Returns the address of the token manager associated with the given tokenId.
     * @param tokenId The tokenId of the token manager.
     * @return tokenManagerAddress_ The address of the token manager.
     */
    function tokenManagerAddress(bytes32 tokenId) external view returns (address tokenManagerAddress_);

    /**
     * @notice Returns the address of the valid token manager associated with the given tokenId.
     * @param tokenId The tokenId of the token manager.
     * @return tokenManagerAddress_ The address of the valid token manager.
     */
    function validTokenManagerAddress(bytes32 tokenId) external view returns (address tokenManagerAddress_);

    /**
     * @notice Returns the address of the token that an existing tokenManager points to.
     * @param tokenId The tokenId of the token manager.
     * @return tokenAddress The address of the token.
     */
    function validTokenAddress(bytes32 tokenId) external view returns (address tokenAddress);

    /**
     * @notice Returns the address of the interchain token associated with the given tokenId.
     * @param tokenId The tokenId of the interchain token.
     * @return tokenAddress The address of the interchain token.
     */
    function interchainTokenAddress(bytes32 tokenId) external view returns (address tokenAddress);

    /**
     * @notice Returns the custom tokenId associated with the given operator and salt.
     * @param operator_ The operator address.
     * @param salt The salt used for token id calculation.
     * @return tokenId The custom tokenId associated with the operator and salt.
     */
    function interchainTokenId(address operator_, bytes32 salt) external view returns (bytes32 tokenId);

    /**
     * @notice Deploys a custom token manager contract on a remote chain.
     * @param salt The salt used for token manager deployment.
     * @param destinationChain The name of the destination chain.
     * @param tokenManagerType The type of token manager.
     * @param params The deployment parameters.
     * @param gasValue The gas value for deployment.
     * @return tokenId The tokenId associated with the token manager.
     */
    function deployTokenManager(
        bytes32 salt,
        string calldata destinationChain,
        TokenManagerType tokenManagerType,
        bytes calldata params,
        uint256 gasValue
    ) external payable returns (bytes32 tokenId);

    /**
     * @notice Deploys and registers an interchain token on a remote chain.
     * @param salt The salt used for token deployment.
     * @param destinationChain The name of the destination chain. Use '' for this chain.
     * @param name The name of the interchain tokens.
     * @param symbol The symbol of the interchain tokens.
     * @param decimals The number of decimals for the interchain tokens.
     * @param minter The minter data for mint/burn operations.
     * @param gasValue The gas value for deployment.
     * @return tokenId The tokenId corresponding to the deployed InterchainToken.
     */
    function deployInterchainToken(
        bytes32 salt,
        string calldata destinationChain,
        string memory name,
        string memory symbol,
        uint8 decimals,
        bytes memory minter,
        uint256 gasValue
    ) external payable returns (bytes32 tokenId);

    /**
     * @notice Initiates an interchain transfer of a specified token to a destination chain.
     * @param tokenId The unique identifier of the token to be transferred.
     * @param destinationChain The destination chain to send the tokens to.
     * @param destinationAddress The address on the destination chain to send the tokens to.
     * @param amount The amount of tokens to be transferred.
     * @param metadata Optional metadata for the call for additional effects (such as calling a destination contract).
     */
    function interchainTransfer(
        bytes32 tokenId,
        string calldata destinationChain,
        bytes calldata destinationAddress,
        uint256 amount,
        bytes calldata metadata,
        uint256 gasValue
    ) external payable;

    /**
     * @notice Initiates an interchain call contract with interchain token to a destination chain.
     * @param tokenId The unique identifier of the token to be transferred.
     * @param destinationChain The destination chain to send the tokens to.
     * @param destinationAddress The address on the destination chain to send the tokens to.
     * @param amount The amount of tokens to be transferred.
     * @param data Additional data to be passed along with the transfer.
     */
    function callContractWithInterchainToken(
        bytes32 tokenId,
        string calldata destinationChain,
        bytes calldata destinationAddress,
        uint256 amount,
        bytes calldata data,
        uint256 gasValue
    ) external payable;

    /**
     * @notice Sets the flow limits for multiple tokens.
     * @param tokenIds An array of tokenIds.
     * @param flowLimits An array of flow limits corresponding to the tokenIds.
     */
    function setFlowLimits(bytes32[] calldata tokenIds, uint256[] calldata flowLimits) external;

    /**
     * @notice Returns the flow limit for a specific token.
     * @param tokenId The tokenId of the token.
     * @return flowLimit_ The flow limit for the token.
     */
    function flowLimit(bytes32 tokenId) external view returns (uint256 flowLimit_);

    /**
     * @notice Returns the total amount of outgoing flow for a specific token.
     * @param tokenId The tokenId of the token.
     * @return flowOutAmount_ The total amount of outgoing flow for the token.
     */
    function flowOutAmount(bytes32 tokenId) external view returns (uint256 flowOutAmount_);

    /**
     * @notice Returns the total amount of incoming flow for a specific token.
     * @param tokenId The tokenId of the token.
     * @return flowInAmount_ The total amount of incoming flow for the token.
     */
    function flowInAmount(bytes32 tokenId) external view returns (uint256 flowInAmount_);

    /**
     * @notice Allows the owner to pause/unpause the token service.
     * @param paused whether to pause or unpause.
     */
    function setPauseStatus(bool paused) external;
}

File 30 of 36 : IInterchainTokenStandard.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title IInterchainTokenStandard interface
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IInterchainTokenStandard {
    /**
     * @notice Implementation of the interchainTransfer method.
     * @dev We chose to either pass `metadata` as raw data on a remote contract call, or if no data is passed, just do a transfer.
     * A different implementation could use metadata to specify a function to invoke, or for other purposes as well.
     * @param destinationChain The destination chain identifier.
     * @param recipient The bytes representation of the address of the recipient.
     * @param amount The amount of token to be transferred.
     * @param metadata Optional metadata for the call for additional effects (such as calling a destination contract).
     */
    function interchainTransfer(
        string calldata destinationChain,
        bytes calldata recipient,
        uint256 amount,
        bytes calldata metadata
    ) external payable;

    /**
     * @notice Implementation of the interchainTransferFrom method
     * @dev We chose to either pass `metadata` as raw data on a remote contract call, or, if no data is passed, just do a transfer.
     * A different implementation could use metadata to specify a function to invoke, or for other purposes as well.
     * @param sender The sender of the tokens. They need to have approved `msg.sender` before this is called.
     * @param destinationChain The string representation of the destination chain.
     * @param recipient The bytes representation of the address of the recipient.
     * @param amount The amount of token to be transferred.
     * @param metadata Optional metadata for the call for additional effects (such as calling a destination contract.)
     */
    function interchainTransferFrom(
        address sender,
        string calldata destinationChain,
        bytes calldata recipient,
        uint256 amount,
        bytes calldata metadata
    ) external payable;
}

File 31 of 36 : IMinter.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IRolesBase } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IRolesBase.sol';

/**
 * @title IMinter Interface
 * @notice An interface for a contract module which provides a basic access control mechanism, where
 * there is an account (a minter) that can be granted exclusive access to specific functions.
 */
interface IMinter is IRolesBase {
    /**
     * @notice Change the minter of the contract.
     * @dev Can only be called by the current minter.
     * @param minter_ The address of the new minter.
     */
    function transferMintership(address minter_) external;

    /**
     * @notice Proposed a change of the minter of the contract.
     * @dev Can only be called by the current minter.
     * @param minter_ The address of the new minter.
     */
    function proposeMintership(address minter_) external;

    /**
     * @notice Accept a change of the minter of the contract.
     * @dev Can only be called by the proposed minter.
     * @param fromMinter The previous minter.
     */
    function acceptMintership(address fromMinter) external;

    /**
     * @notice Query if an address is a minter
     * @param addr the address to query for
     * @return bool Boolean value representing whether or not the address is a minter.
     */
    function isMinter(address addr) external view returns (bool);
}

File 32 of 36 : IOperator.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IRolesBase } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IRolesBase.sol';

/**
 * @title IOperator Interface
 * @notice An interface for a contract module which provides a basic access control mechanism, where
 * there is an account (a operator) that can be granted exclusive access to specific functions.
 */
interface IOperator is IRolesBase {
    /**
     * @notice Change the operator of the contract.
     * @dev Can only be called by the current operator.
     * @param operator_ The address of the new operator.
     */
    function transferOperatorship(address operator_) external;

    /**
     * @notice Proposed a change of the operator of the contract.
     * @dev Can only be called by the current operator.
     * @param operator_ The address of the new operator.
     */
    function proposeOperatorship(address operator_) external;

    /**
     * @notice Accept a proposed change of operatorship.
     * @dev Can only be called by the proposed operator.
     * @param fromOperator The previous operator of the contract.
     */
    function acceptOperatorship(address fromOperator) external;

    /**
     * @notice Query if an address is a operator.
     * @param addr The address to query for.
     * @return bool Boolean value representing whether or not the address is an operator.
     */
    function isOperator(address addr) external view returns (bool);
}

File 33 of 36 : ITokenManager.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IImplementation } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IImplementation.sol';

import { IBaseTokenManager } from './IBaseTokenManager.sol';
import { IOperator } from './IOperator.sol';
import { IFlowLimit } from './IFlowLimit.sol';

/**
 * @title ITokenManager Interface
 * @notice This contract is responsible for managing tokens, such as setting locking token balances, or setting flow limits, for interchain transfers.
 */
interface ITokenManager is IBaseTokenManager, IOperator, IFlowLimit, IImplementation {
    error TokenLinkerZeroAddress();
    error NotService(address caller);
    error TakeTokenFailed();
    error GiveTokenFailed();
    error NotToken(address caller);
    error ZeroAddress();
    error AlreadyFlowLimiter(address flowLimiter);
    error NotFlowLimiter(address flowLimiter);
    error NotSupported();

    /**
     * @notice Returns implementation type of this token manager.
     * @return uint256 The implementation type of this token manager.
     */
    function implementationType() external view returns (uint256);

    function addFlowIn(uint256 amount) external;

    function addFlowOut(uint256 amount) external;

    /**
     * @notice This function adds a flow limiter for this TokenManager.
     * @dev Can only be called by the operator.
     * @param flowLimiter the address of the new flow limiter.
     */
    function addFlowLimiter(address flowLimiter) external;

    /**
     * @notice This function removes a flow limiter for this TokenManager.
     * @dev Can only be called by the operator.
     * @param flowLimiter the address of an existing flow limiter.
     */
    function removeFlowLimiter(address flowLimiter) external;

    /**
     * @notice Query if an address is a flow limiter.
     * @param addr The address to query for.
     * @return bool Boolean value representing whether or not the address is a flow limiter.
     */
    function isFlowLimiter(address addr) external view returns (bool);

    /**
     * @notice This function sets the flow limit for this TokenManager.
     * @dev Can only be called by the flow limiters.
     * @param flowLimit_ The maximum difference between the tokens flowing in and/or out at any given interval of time (6h).
     */
    function setFlowLimit(uint256 flowLimit_) external;

    /**
     * @notice A function to renew approval to the service if we need to.
     */
    function approveService() external;

    /**
     * @notice Getter function for the parameters of a lock/unlock TokenManager.
     * @dev This function will be mainly used by frontends.
     * @param operator_ The operator of the TokenManager.
     * @param tokenAddress_ The token to be managed.
     * @return params_ The resulting params to be passed to custom TokenManager deployments.
     */
    function params(bytes calldata operator_, address tokenAddress_) external pure returns (bytes memory params_);
}

File 34 of 36 : ITokenManagerImplementation.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ITokenManagerImplementation Interface
 * @notice Interface for returning the token manager implementation type.
 */
interface ITokenManagerImplementation {
    /**
     * @notice Returns the implementation address for a given token manager type.
     * @param tokenManagerType The type of token manager.
     * @return tokenManagerAddress_ The address of the token manager implementation.
     */
    function tokenManagerImplementation(uint256 tokenManagerType) external view returns (address tokenManagerAddress_);
}

File 35 of 36 : ITokenManagerType.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ITokenManagerType Interface
 * @notice A simple interface that defines all the token manager types.
 */
interface ITokenManagerType {
    enum TokenManagerType {
        MINT_BURN,
        MINT_BURN_FROM,
        LOCK_UNLOCK,
        LOCK_UNLOCK_FEE
    }
}

File 36 of 36 : ITransmitInterchainToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ITransmitInterchainToken Interface
 * @notice Interface for transmiting interchain tokens via the interchain token service
 */
interface ITransmitInterchainToken {
    /**
     * @notice Transmit an interchain transfer for the given tokenId.
     * @dev Only callable by a token registered under a tokenId.
     * @param tokenId The tokenId of the token (which must be the msg.sender).
     * @param sourceAddress The address where the token is coming from.
     * @param destinationChain The name of the chain to send tokens to.
     * @param destinationAddress The destinationAddress for the interchainTransfer.
     * @param amount The amount of token to give.
     * @param metadata Optional metadata for the call for additional effects (such as calling a destination contract).
     */
    function transmitInterchainTransfer(
        bytes32 tokenId,
        address sourceAddress,
        string calldata destinationChain,
        bytes memory destinationAddress,
        uint256 amount,
        bytes calldata metadata
    ) external payable;
}

Settings
{
  "evmVersion": "london",
  "optimizer": {
    "enabled": true,
    "runs": 1000,
    "details": {
      "peephole": true,
      "inliner": true,
      "jumpdestRemover": true,
      "orderLiterals": true,
      "deduplicate": true,
      "cse": true,
      "constantOptimizer": true,
      "yul": true,
      "yulDetails": {
        "stackAllocation": true
      }
    }
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"interchainTokenService_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"GatewayToken","type":"error"},{"inputs":[],"name":"InvalidChainName","type":"error"},{"inputs":[],"name":"InvalidCodeHash","type":"error"},{"inputs":[],"name":"InvalidImplementation","type":"error"},{"inputs":[],"name":"InvalidOwner","type":"error"},{"inputs":[],"name":"InvalidOwnerAddress","type":"error"},{"inputs":[],"name":"MulticallFailed","type":"error"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"NotMinter","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"NotOperator","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"NotProxy","type":"error"},{"inputs":[],"name":"SetupFailed","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newImplementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"canonicalInterchainTokenId","outputs":[{"internalType":"bytes32","name":"tokenId","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"chainNameHash_","type":"bytes32"},{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"canonicalInterchainTokenSalt","outputs":[{"internalType":"bytes32","name":"salt","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"chainNameHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"initialSupply","type":"uint256"},{"internalType":"address","name":"minter","type":"address"}],"name":"deployInterchainToken","outputs":[{"internalType":"bytes32","name":"tokenId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"originalChain","type":"string"},{"internalType":"address","name":"originalTokenAddress","type":"address"},{"internalType":"string","name":"destinationChain","type":"string"},{"internalType":"uint256","name":"gasValue","type":"uint256"}],"name":"deployRemoteCanonicalInterchainToken","outputs":[{"internalType":"bytes32","name":"tokenId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"originalChainName","type":"string"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"minter","type":"address"},{"internalType":"string","name":"destinationChain","type":"string"},{"internalType":"uint256","name":"gasValue","type":"uint256"}],"name":"deployRemoteInterchainToken","outputs":[{"internalType":"bytes32","name":"tokenId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"gateway","outputs":[{"internalType":"contract IAxelarGateway","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"deployer","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"interchainTokenAddress","outputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"deployer","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"interchainTokenId","outputs":[{"internalType":"bytes32","name":"tokenId","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"chainNameHash_","type":"bytes32"},{"internalType":"address","name":"deployer","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"interchainTokenSalt","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"interchainTokenService","outputs":[{"internalType":"contract IInterchainTokenService","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"proposeOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"registerCanonicalInterchainToken","outputs":[{"internalType":"bytes32","name":"tokenId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes32","name":"newImplementationCodeHash","type":"bytes32"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"upgrade","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6101006040523480156200001257600080fd5b5060405162002b8538038062002b8583398101604081905262000035916200021e565b6001620000428162000161565b50306080526001600160a01b0381166200006f5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b03811660a08190526040805163864a0dcf60e01b8152905163864a0dcf916004808201926020929091908290030181865afa158015620000ba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000e0919062000245565b60c0818152505060a0516001600160a01b031663116191b66040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000128573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200014e91906200021e565b6001600160a01b031660e052506200025f565b6001600160a01b0381166200018957604051633649397d60e21b815260040160405180910390fd5b6040516001600160a01b038216907f04dba622d284ed0014ee4b9a6a68386be1a4c08a4913ae272de89199cc68616390600090a27f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05560007f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d155565b6001600160a01b03811681146200021b57600080fd5b50565b6000602082840312156200023157600080fd5b81516200023e8162000205565b9392505050565b6000602082840312156200025857600080fd5b5051919050565b60805160a05160c05160e05161286e62000317600039600081816101dd0152611fa0015260008181610381015281816105a701528181610a960152818161108f015281816117c30152818161195c0152611c2b01526000818161018c015281816106fa015281816107aa01528181610b5001528181610be701528181610e9a01528181611156015281816111fb0152818161181a01528181611a1201528181611bf70152611dbb01526000611411015261286e6000f3fe6080604052600436106101755760003560e01c80638da5cb5b116100cb578063a5269ef11161007f578063b229288811610059578063b229288814610503578063e30c397814610523578063f2fde38b1461055757600080fd5b8063a5269ef1146104b0578063a75483d1146104d0578063ac9650d8146104e357600080fd5b8063993a5b9e116100b0578063993a5b9e1461045d5780639ded06df14610470578063a3499c731461049057600080fd5b80638da5cb5b146103a35780639417bfe1146103d757600080fd5b80635d79c00e1161012d57806379ba50971161010757806379ba5097146103275780638291286c1461033c578063864a0dcf1461036f57600080fd5b80635d79c00e146102d25780637100e6a9146102e5578063710bf3221461030557600080fd5b80633e12f8c51161015e5780633e12f8c5146101ff57806352a3702f146102205780635c60da1b1461029e57600080fd5b806309c6bed91461017a578063116191b6146101cb575b600080fd5b34801561018657600080fd5b506101ae7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101d757600080fd5b506101ae7f000000000000000000000000000000000000000000000000000000000000000081565b61021261020d36600461209f565b610577565b6040519081526020016101c2565b34801561022c57600080fd5b5061021261023b366004612148565b604080517f9ca52083bb00ac0f5bed7edcaabb0534d03efb0719807b54a8029c4d1313630960208201529081018390526001600160a01b038216606082015260009060800160405160208183030381529060405280519060200120905092915050565b3480156102aa57600080fd5b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546101ae565b6102126102e03660046121e7565b610a73565b3480156102f157600080fd5b506101ae6103003660046122ba565b610e96565b34801561031157600080fd5b506103256103203660046122e6565b610f37565b005b34801561033357600080fd5b50610325611006565b34801561034857600080fd5b507f80547d63ed663962b99f8ed432bff3879a35b5418af92258aa171feef14cc3cc610212565b34801561037b57600080fd5b506102127f000000000000000000000000000000000000000000000000000000000000000081565b3480156103af57600080fd5b507f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0546101ae565b3480156103e357600080fd5b506102126103f2366004612303565b604080517ff84d43c32bc607f1bdb175c63a0cf1939bf0cc8cc3565450be225afbb5a1098560208201529081018490526001600160a01b03831660608201526080810182905260009060a0016040516020818303038152906040528051906020012090509392505050565b61021261046b36600461233b565b611080565b34801561047c57600080fd5b5061032561048b3660046123c8565b61140e565b34801561049c57600080fd5b506103256104ab36600461240a565b611474565b3480156104bc57600080fd5b506102126104cb3660046122ba565b611793565b6102126104de3660046122e6565b6118c8565b6104f66104f1366004612466565b611a9a565b6040516101c2919061252b565b34801561050f57600080fd5b5061021261051e3660046122e6565b611bf3565b34801561052f57600080fd5b507f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d1546101ae565b34801561056357600080fd5b506103256105723660046122e6565b611d39565b604080517ff84d43c32bc607f1bdb175c63a0cf1939bf0cc8cc3565450be225afbb5a109856020808301919091527f000000000000000000000000000000000000000000000000000000000000000082840152336060830181905260808084018d90528451808503909101815260a0909301909352815191012060009190604080516000815260208101909152909a50841561061d5761061630611d89565b9050610641565b6001600160a01b038416156106415761063e846001600160a01b0316611d89565b90505b6106d98b604051806020016040528060008152508c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508e93508992509050611db7565b92508415610a6557604051631d05ce3f60e31b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e82e71f890602401602060405180830381865afa158015610749573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076d919061258d565b6040517ff8c8a826000000000000000000000000000000000000000000000000000000008152600481018690529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f8c8a82690602401602060405180830381865afa1580156107f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610815919061258d565b6040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152602482018a9052919250908316906340c10f1990604401600060405180830381600087803b15801561087c57600080fd5b505af1158015610890573d6000803e3d6000fd5b50506040517fcf86a95a0000000000000000000000000000000000000000000000000000000081526001600160a01b0389811660048301528516925063cf86a95a9150602401600060405180830381600087803b1580156108f057600080fd5b505af1158015610904573d6000803e3d6000fd5b50506040517fe915cfd10000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038416925063e915cfd19150602401600060405180830381600087803b15801561096257600080fd5b505af1158015610976573d6000803e3d6000fd5b50506040517f120a63b50000000000000000000000000000000000000000000000000000000081526001600160a01b0389811660048301528416925063120a63b59150602401600060405180830381600087803b1580156109d657600080fd5b505af11580156109ea573d6000803e3d6000fd5b50506040517f4a6a42d80000000000000000000000000000000000000000000000000000000081526001600160a01b03898116600483015284169250634a6a42d89150602401600060405180830381600087803b158015610a4a57600080fd5b505af1158015610a5e573d6000803e3d6000fd5b5050505050505b505098975050505050505050565b604080516000808252602082019092526060908190839060008a8103610aba57507f0000000000000000000000000000000000000000000000000000000000000000610ad5565b8b8b604051610aca9291906125aa565b604051809103902090505b604080517ff84d43c32bc607f1bdb175c63a0cf1939bf0cc8cc3565450be225afbb5a10985602080830191909152818301849052336060830181905260808084018f90528451808503909101815260a0909301909352815191012060405163a5269ef160e01b81526000600482015260248101829052909b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a5269ef190604401602060405180830381865afa158015610b9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc391906125ba565b604051631d05ce3f60e31b8152600481018290529097506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e82e71f890602401602060405180830381865afa158015610c2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c52919061258d565b9050806001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c92573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cba91908101906125d3565b9650806001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610cfa573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d2291908101906125d3565b9550806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d86919061264a565b94506001600160a01b038b1615610e75576040517faa271e1a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c8116600483015282169063aa271e1a90602401602060405180830381865afa158015610df6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1a9190612667565b610e60576040517f361c31f20000000000000000000000000000000000000000000000000000000081526001600160a01b038c1660048201526024015b60405180910390fd5b610e728b6001600160a01b0316611d89565b93505b505050610e878988868686868c611db7565b9b9a5050505050505050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e82e71f8610ed18585611793565b6040518263ffffffff1660e01b8152600401610eef91815260200190565b602060405180830381865afa158015610f0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f30919061258d565b9392505050565b33610f607f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05490565b6001600160a01b031614610f87576040516330cd747160e01b815260040160405180910390fd5b6001600160a01b038116610fae57604051633649397d60e21b815260040160405180910390fd5b6040516001600160a01b038216907fd9be0e8e07417e00f2521db636cb53e316fd288f5051f16d2aa2bf0c3938a87690600090a27f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d155565b60006110307f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d15490565b90506001600160a01b0381163314611074576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61107d81611e61565b50565b60008080808881036110b357507f00000000000000000000000000000000000000000000000000000000000000006110ce565b89896040516110c39291906125aa565b604051809103902090505b6111368189604080517f9ca52083bb00ac0f5bed7edcaabb0534d03efb0719807b54a8029c4d1313630960208201529081018390526001600160a01b038216606082015260009060800160405160208183030381529060405280519060200120905092915050565b60405163a5269ef160e01b815260006004820152602481018290529093507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a5269ef190604401602060405180830381865afa1580156111a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c991906125ba565b6040517f1a083d39000000000000000000000000000000000000000000000000000000008152600481018290529094507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631a083d3990602401602060405180830381865afa15801561124a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126e919061258d565b9150506000816001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156112b1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112d991908101906125d3565b90506000826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801561131b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261134391908101906125d3565b90506000836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611385573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a9919061264a565b90506113fe858a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060408051602081019091529081528993508892508791508d611db7565b9c9b505050505050505050505050565b307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031603611470576040517fbf10dd3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b3361149d7f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05490565b6001600160a01b0316146114c4576040516330cd747160e01b815260040160405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b0316638291286c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611523573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154791906125ba565b846001600160a01b0316638291286c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611585573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a991906125ba565b146115e0576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836001600160a01b03163f8314611623576040517f8f84fb2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038516907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2801561176c576000846001600160a01b0316639ded06df60e01b8484604051602401611684929190612689565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516116ef91906126b8565b600060405180830381855af49150503d806000811461172a576040519150601f19603f3d011682016040523d82523d6000602084013e61172f565b606091505b505090508061176a576040517f97905dfb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b5050507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b604080517ff84d43c32bc607f1bdb175c63a0cf1939bf0cc8cc3565450be225afbb5a109856020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401526001600160a01b03858116606084015260808084018690528451808503909101815260a090930190935281519101206000917f0000000000000000000000000000000000000000000000000000000000000000169063a5269ef19083906040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa1580156118a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3091906125ba565b600080826040516020016118f9919060408082526000908201526001600160a01b0391909116602082015260600190565b604051602081830303815290604052905061191383611f04565b15611955576040517f94a58e2b0000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610e57565b60006119df7f000000000000000000000000000000000000000000000000000000000000000085604080517f9ca52083bb00ac0f5bed7edcaabb0534d03efb0719807b54a8029c4d1313630960208201529081018390526001600160a01b038216606082015260009060800160405160208183030381529060405280519060200120905092915050565b6040517f98d78c820000000000000000000000000000000000000000000000000000000081529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906398d78c8290611a4f90849060029087906000906004016126d4565b6020604051808303816000875af1158015611a6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9291906125ba565b949350505050565b60608167ffffffffffffffff811115611ab557611ab5612178565b604051908082528060200260200182016040528015611ae857816020015b6060815260200190600190039081611ad35790505b5090506000606060005b84811015611bea5730868683818110611b0d57611b0d612730565b9050602002810190611b1f9190612746565b604051611b2d9291906125aa565b600060405180830381855af49150503d8060008114611b68576040519150601f19603f3d011682016040523d82523d6000602084013e611b6d565b606091505b50909350915082611bbb578151600003611bb3576040517f4d6a232800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815182602001fd5b81848281518110611bce57611bce612730565b602002602001018190525080611be39061278d565b9050611af2565b50505092915050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a5269ef16000611cae7f000000000000000000000000000000000000000000000000000000000000000086604080517f9ca52083bb00ac0f5bed7edcaabb0534d03efb0719807b54a8029c4d1313630960208201529081018390526001600160a01b038216606082015260009060800160405160208183030381529060405280519060200120905092915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa158015611d0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d3391906125ba565b92915050565b33611d627f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05490565b6001600160a01b031614611074576040516330cd747160e01b815260040160405180910390fd5b6040805160148082528183019092526060916020820181803683375050506014808201939093529182525090565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e1d40c77838a8a8a8a8a8a8a6040518963ffffffff1660e01b8152600401611e1297969594939291906127b4565b60206040518083038185885af1158015611e30573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611e5591906125ba565b98975050505050505050565b6001600160a01b038116611e8857604051633649397d60e21b815260040160405180910390fd5b6040516001600160a01b038216907f04dba622d284ed0014ee4b9a6a68386be1a4c08a4913ae272de89199cc68616390600090a27f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05560007f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d155565b600080826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611f45573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611f6d91908101906125d3565b6040517f935b13f60000000000000000000000000000000000000000000000000000000081529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063935b13f690611fd5908490600401612825565b602060405180830381865afa158015611ff2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612016919061258d565b6001600160a01b0316836001600160a01b031614915050919050565b60008083601f84011261204457600080fd5b50813567ffffffffffffffff81111561205c57600080fd5b60208301915083602082850101111561207457600080fd5b9250929050565b60ff8116811461107d57600080fd5b6001600160a01b038116811461107d57600080fd5b60008060008060008060008060c0898b0312156120bb57600080fd5b88359750602089013567ffffffffffffffff808211156120da57600080fd5b6120e68c838d01612032565b909950975060408b01359150808211156120ff57600080fd5b5061210c8b828c01612032565b90965094505060608901356121208161207b565b92506080890135915060a08901356121378161208a565b809150509295985092959890939650565b6000806040838503121561215b57600080fd5b82359150602083013561216d8161208a565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156121b7576121b7612178565b604052919050565b600067ffffffffffffffff8211156121d9576121d9612178565b50601f01601f191660200190565b60008060008060008060a0878903121561220057600080fd5b863567ffffffffffffffff8082111561221857600080fd5b6122248a838b01612032565b909850965060208901359550604089013591506122408261208a565b9093506060880135908082111561225657600080fd5b508701601f8101891361226857600080fd5b803561227b612276826121bf565b61218e565b8181528a602083850101111561229057600080fd5b81602084016020830137600060208383010152809450505050608087013590509295509295509295565b600080604083850312156122cd57600080fd5b82356122d88161208a565b946020939093013593505050565b6000602082840312156122f857600080fd5b8135610f308161208a565b60008060006060848603121561231857600080fd5b83359250602084013561232a8161208a565b929592945050506040919091013590565b6000806000806000806080878903121561235457600080fd5b863567ffffffffffffffff8082111561236c57600080fd5b6123788a838b01612032565b90985096506020890135915061238d8261208a565b909450604088013590808211156123a357600080fd5b506123b089828a01612032565b979a9699509497949695606090950135949350505050565b600080602083850312156123db57600080fd5b823567ffffffffffffffff8111156123f257600080fd5b6123fe85828601612032565b90969095509350505050565b6000806000806060858703121561242057600080fd5b843561242b8161208a565b935060208501359250604085013567ffffffffffffffff81111561244e57600080fd5b61245a87828801612032565b95989497509550505050565b6000806020838503121561247957600080fd5b823567ffffffffffffffff8082111561249157600080fd5b818501915085601f8301126124a557600080fd5b8135818111156124b457600080fd5b8660208260051b85010111156124c957600080fd5b60209290920196919550909350505050565b60005b838110156124f65781810151838201526020016124de565b50506000910152565b600081518084526125178160208601602086016124db565b601f01601f19169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561258057603f1988860301845261256e8583516124ff565b94509285019290850190600101612552565b5092979650505050505050565b60006020828403121561259f57600080fd5b8151610f308161208a565b8183823760009101908152919050565b6000602082840312156125cc57600080fd5b5051919050565b6000602082840312156125e557600080fd5b815167ffffffffffffffff8111156125fc57600080fd5b8201601f8101841361260d57600080fd5b805161261b612276826121bf565b81815285602083850101111561263057600080fd5b6126418260208301602086016124db565b95945050505050565b60006020828403121561265c57600080fd5b8151610f308161207b565b60006020828403121561267957600080fd5b81518015158114610f3057600080fd5b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b600082516126ca8184602087016124db565b9190910192915050565b84815260a06020820152600060a082015260006004851061270557634e487b7160e01b600052602160045260246000fd5b84604083015260c0606083015261271f60c08301856124ff565b905082608083015295945050505050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261275d57600080fd5b83018035915067ffffffffffffffff82111561277857600080fd5b60200191503681900382131561207457600080fd5b6000600182016127ad57634e487b7160e01b600052601160045260246000fd5b5060010190565b87815260e0602082015260006127cd60e08301896124ff565b82810360408401526127df81896124ff565b905082810360608401526127f381886124ff565b905060ff8616608084015282810360a084015261281081866124ff565b9150508260c083015298975050505050505050565b602081526000610f3060208301846124ff56fea26469706673582212201dd24b41eec30f006454347e9cdc29f9b6e4f4417fd319013938b3660bd3fc6e64736f6c63430008150033000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c

Deployed Bytecode

0x6080604052600436106101755760003560e01c80638da5cb5b116100cb578063a5269ef11161007f578063b229288811610059578063b229288814610503578063e30c397814610523578063f2fde38b1461055757600080fd5b8063a5269ef1146104b0578063a75483d1146104d0578063ac9650d8146104e357600080fd5b8063993a5b9e116100b0578063993a5b9e1461045d5780639ded06df14610470578063a3499c731461049057600080fd5b80638da5cb5b146103a35780639417bfe1146103d757600080fd5b80635d79c00e1161012d57806379ba50971161010757806379ba5097146103275780638291286c1461033c578063864a0dcf1461036f57600080fd5b80635d79c00e146102d25780637100e6a9146102e5578063710bf3221461030557600080fd5b80633e12f8c51161015e5780633e12f8c5146101ff57806352a3702f146102205780635c60da1b1461029e57600080fd5b806309c6bed91461017a578063116191b6146101cb575b600080fd5b34801561018657600080fd5b506101ae7f000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c81565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101d757600080fd5b506101ae7f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e3181565b61021261020d36600461209f565b610577565b6040519081526020016101c2565b34801561022c57600080fd5b5061021261023b366004612148565b604080517f9ca52083bb00ac0f5bed7edcaabb0534d03efb0719807b54a8029c4d1313630960208201529081018390526001600160a01b038216606082015260009060800160405160208183030381529060405280519060200120905092915050565b3480156102aa57600080fd5b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546101ae565b6102126102e03660046121e7565b610a73565b3480156102f157600080fd5b506101ae6103003660046122ba565b610e96565b34801561031157600080fd5b506103256103203660046122e6565b610f37565b005b34801561033357600080fd5b50610325611006565b34801561034857600080fd5b507f80547d63ed663962b99f8ed432bff3879a35b5418af92258aa171feef14cc3cc610212565b34801561037b57600080fd5b506102127f09d0f27659ee556a8134fa56941e42400e672aecc2d4cfc61cdb0fcea4590e0581565b3480156103af57600080fd5b507f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0546101ae565b3480156103e357600080fd5b506102126103f2366004612303565b604080517ff84d43c32bc607f1bdb175c63a0cf1939bf0cc8cc3565450be225afbb5a1098560208201529081018490526001600160a01b03831660608201526080810182905260009060a0016040516020818303038152906040528051906020012090509392505050565b61021261046b36600461233b565b611080565b34801561047c57600080fd5b5061032561048b3660046123c8565b61140e565b34801561049c57600080fd5b506103256104ab36600461240a565b611474565b3480156104bc57600080fd5b506102126104cb3660046122ba565b611793565b6102126104de3660046122e6565b6118c8565b6104f66104f1366004612466565b611a9a565b6040516101c2919061252b565b34801561050f57600080fd5b5061021261051e3660046122e6565b611bf3565b34801561052f57600080fd5b507f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d1546101ae565b34801561056357600080fd5b506103256105723660046122e6565b611d39565b604080517ff84d43c32bc607f1bdb175c63a0cf1939bf0cc8cc3565450be225afbb5a109856020808301919091527f09d0f27659ee556a8134fa56941e42400e672aecc2d4cfc61cdb0fcea4590e0582840152336060830181905260808084018d90528451808503909101815260a0909301909352815191012060009190604080516000815260208101909152909a50841561061d5761061630611d89565b9050610641565b6001600160a01b038416156106415761063e846001600160a01b0316611d89565b90505b6106d98b604051806020016040528060008152508c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508e93508992509050611db7565b92508415610a6557604051631d05ce3f60e31b8152600481018490526000907f000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c6001600160a01b03169063e82e71f890602401602060405180830381865afa158015610749573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076d919061258d565b6040517ff8c8a826000000000000000000000000000000000000000000000000000000008152600481018690529091506000906001600160a01b037f000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c169063f8c8a82690602401602060405180830381865afa1580156107f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610815919061258d565b6040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152602482018a9052919250908316906340c10f1990604401600060405180830381600087803b15801561087c57600080fd5b505af1158015610890573d6000803e3d6000fd5b50506040517fcf86a95a0000000000000000000000000000000000000000000000000000000081526001600160a01b0389811660048301528516925063cf86a95a9150602401600060405180830381600087803b1580156108f057600080fd5b505af1158015610904573d6000803e3d6000fd5b50506040517fe915cfd10000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038416925063e915cfd19150602401600060405180830381600087803b15801561096257600080fd5b505af1158015610976573d6000803e3d6000fd5b50506040517f120a63b50000000000000000000000000000000000000000000000000000000081526001600160a01b0389811660048301528416925063120a63b59150602401600060405180830381600087803b1580156109d657600080fd5b505af11580156109ea573d6000803e3d6000fd5b50506040517f4a6a42d80000000000000000000000000000000000000000000000000000000081526001600160a01b03898116600483015284169250634a6a42d89150602401600060405180830381600087803b158015610a4a57600080fd5b505af1158015610a5e573d6000803e3d6000fd5b5050505050505b505098975050505050505050565b604080516000808252602082019092526060908190839060008a8103610aba57507f09d0f27659ee556a8134fa56941e42400e672aecc2d4cfc61cdb0fcea4590e05610ad5565b8b8b604051610aca9291906125aa565b604051809103902090505b604080517ff84d43c32bc607f1bdb175c63a0cf1939bf0cc8cc3565450be225afbb5a10985602080830191909152818301849052336060830181905260808084018f90528451808503909101815260a0909301909352815191012060405163a5269ef160e01b81526000600482015260248101829052909b507f000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c6001600160a01b03169063a5269ef190604401602060405180830381865afa158015610b9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc391906125ba565b604051631d05ce3f60e31b8152600481018290529097506000906001600160a01b037f000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c169063e82e71f890602401602060405180830381865afa158015610c2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c52919061258d565b9050806001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c92573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cba91908101906125d3565b9650806001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610cfa573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d2291908101906125d3565b9550806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d86919061264a565b94506001600160a01b038b1615610e75576040517faa271e1a0000000000000000000000000000000000000000000000000000000081526001600160a01b038c8116600483015282169063aa271e1a90602401602060405180830381865afa158015610df6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1a9190612667565b610e60576040517f361c31f20000000000000000000000000000000000000000000000000000000081526001600160a01b038c1660048201526024015b60405180910390fd5b610e728b6001600160a01b0316611d89565b93505b505050610e878988868686868c611db7565b9b9a5050505050505050505050565b60007f000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c6001600160a01b031663e82e71f8610ed18585611793565b6040518263ffffffff1660e01b8152600401610eef91815260200190565b602060405180830381865afa158015610f0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f30919061258d565b9392505050565b33610f607f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05490565b6001600160a01b031614610f87576040516330cd747160e01b815260040160405180910390fd5b6001600160a01b038116610fae57604051633649397d60e21b815260040160405180910390fd5b6040516001600160a01b038216907fd9be0e8e07417e00f2521db636cb53e316fd288f5051f16d2aa2bf0c3938a87690600090a27f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d155565b60006110307f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d15490565b90506001600160a01b0381163314611074576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61107d81611e61565b50565b60008080808881036110b357507f09d0f27659ee556a8134fa56941e42400e672aecc2d4cfc61cdb0fcea4590e056110ce565b89896040516110c39291906125aa565b604051809103902090505b6111368189604080517f9ca52083bb00ac0f5bed7edcaabb0534d03efb0719807b54a8029c4d1313630960208201529081018390526001600160a01b038216606082015260009060800160405160208183030381529060405280519060200120905092915050565b60405163a5269ef160e01b815260006004820152602481018290529093507f000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c6001600160a01b03169063a5269ef190604401602060405180830381865afa1580156111a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c991906125ba565b6040517f1a083d39000000000000000000000000000000000000000000000000000000008152600481018290529094507f000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c6001600160a01b031690631a083d3990602401602060405180830381865afa15801561124a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126e919061258d565b9150506000816001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa1580156112b1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112d991908101906125d3565b90506000826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801561131b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261134391908101906125d3565b90506000836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611385573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a9919061264a565b90506113fe858a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060408051602081019091529081528993508892508791508d611db7565b9c9b505050505050505050505050565b307f000000000000000000000000440b118f34d6224b20b4641835ac9161bd4f09946001600160a01b031603611470576040517fbf10dd3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b3361149d7f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05490565b6001600160a01b0316146114c4576040516330cd747160e01b815260040160405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b0316638291286c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611523573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154791906125ba565b846001600160a01b0316638291286c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611585573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a991906125ba565b146115e0576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836001600160a01b03163f8314611623576040517f8f84fb2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038516907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a2801561176c576000846001600160a01b0316639ded06df60e01b8484604051602401611684929190612689565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516116ef91906126b8565b600060405180830381855af49150503d806000811461172a576040519150601f19603f3d011682016040523d82523d6000602084013e61172f565b606091505b505090508061176a576040517f97905dfb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b5050507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b604080517ff84d43c32bc607f1bdb175c63a0cf1939bf0cc8cc3565450be225afbb5a109856020808301919091527f09d0f27659ee556a8134fa56941e42400e672aecc2d4cfc61cdb0fcea4590e05828401526001600160a01b03858116606084015260808084018690528451808503909101815260a090930190935281519101206000917f000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c169063a5269ef19083906040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa1580156118a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3091906125ba565b600080826040516020016118f9919060408082526000908201526001600160a01b0391909116602082015260600190565b604051602081830303815290604052905061191383611f04565b15611955576040517f94a58e2b0000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610e57565b60006119df7f09d0f27659ee556a8134fa56941e42400e672aecc2d4cfc61cdb0fcea4590e0585604080517f9ca52083bb00ac0f5bed7edcaabb0534d03efb0719807b54a8029c4d1313630960208201529081018390526001600160a01b038216606082015260009060800160405160208183030381529060405280519060200120905092915050565b6040517f98d78c820000000000000000000000000000000000000000000000000000000081529091506001600160a01b037f000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c16906398d78c8290611a4f90849060029087906000906004016126d4565b6020604051808303816000875af1158015611a6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9291906125ba565b949350505050565b60608167ffffffffffffffff811115611ab557611ab5612178565b604051908082528060200260200182016040528015611ae857816020015b6060815260200190600190039081611ad35790505b5090506000606060005b84811015611bea5730868683818110611b0d57611b0d612730565b9050602002810190611b1f9190612746565b604051611b2d9291906125aa565b600060405180830381855af49150503d8060008114611b68576040519150601f19603f3d011682016040523d82523d6000602084013e611b6d565b606091505b50909350915082611bbb578151600003611bb3576040517f4d6a232800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815182602001fd5b81848281518110611bce57611bce612730565b602002602001018190525080611be39061278d565b9050611af2565b50505092915050565b60007f000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c6001600160a01b031663a5269ef16000611cae7f09d0f27659ee556a8134fa56941e42400e672aecc2d4cfc61cdb0fcea4590e0586604080517f9ca52083bb00ac0f5bed7edcaabb0534d03efb0719807b54a8029c4d1313630960208201529081018390526001600160a01b038216606082015260009060800160405160208183030381529060405280519060200120905092915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa158015611d0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d3391906125ba565b92915050565b33611d627f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05490565b6001600160a01b031614611074576040516330cd747160e01b815260040160405180910390fd5b6040805160148082528183019092526060916020820181803683375050506014808201939093529182525090565b60007f000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c6001600160a01b031663e1d40c77838a8a8a8a8a8a8a6040518963ffffffff1660e01b8152600401611e1297969594939291906127b4565b60206040518083038185885af1158015611e30573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611e5591906125ba565b98975050505050505050565b6001600160a01b038116611e8857604051633649397d60e21b815260040160405180910390fd5b6040516001600160a01b038216907f04dba622d284ed0014ee4b9a6a68386be1a4c08a4913ae272de89199cc68616390600090a27f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05560007f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d155565b600080826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611f45573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611f6d91908101906125d3565b6040517f935b13f60000000000000000000000000000000000000000000000000000000081529091506001600160a01b037f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31169063935b13f690611fd5908490600401612825565b602060405180830381865afa158015611ff2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612016919061258d565b6001600160a01b0316836001600160a01b031614915050919050565b60008083601f84011261204457600080fd5b50813567ffffffffffffffff81111561205c57600080fd5b60208301915083602082850101111561207457600080fd5b9250929050565b60ff8116811461107d57600080fd5b6001600160a01b038116811461107d57600080fd5b60008060008060008060008060c0898b0312156120bb57600080fd5b88359750602089013567ffffffffffffffff808211156120da57600080fd5b6120e68c838d01612032565b909950975060408b01359150808211156120ff57600080fd5b5061210c8b828c01612032565b90965094505060608901356121208161207b565b92506080890135915060a08901356121378161208a565b809150509295985092959890939650565b6000806040838503121561215b57600080fd5b82359150602083013561216d8161208a565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156121b7576121b7612178565b604052919050565b600067ffffffffffffffff8211156121d9576121d9612178565b50601f01601f191660200190565b60008060008060008060a0878903121561220057600080fd5b863567ffffffffffffffff8082111561221857600080fd5b6122248a838b01612032565b909850965060208901359550604089013591506122408261208a565b9093506060880135908082111561225657600080fd5b508701601f8101891361226857600080fd5b803561227b612276826121bf565b61218e565b8181528a602083850101111561229057600080fd5b81602084016020830137600060208383010152809450505050608087013590509295509295509295565b600080604083850312156122cd57600080fd5b82356122d88161208a565b946020939093013593505050565b6000602082840312156122f857600080fd5b8135610f308161208a565b60008060006060848603121561231857600080fd5b83359250602084013561232a8161208a565b929592945050506040919091013590565b6000806000806000806080878903121561235457600080fd5b863567ffffffffffffffff8082111561236c57600080fd5b6123788a838b01612032565b90985096506020890135915061238d8261208a565b909450604088013590808211156123a357600080fd5b506123b089828a01612032565b979a9699509497949695606090950135949350505050565b600080602083850312156123db57600080fd5b823567ffffffffffffffff8111156123f257600080fd5b6123fe85828601612032565b90969095509350505050565b6000806000806060858703121561242057600080fd5b843561242b8161208a565b935060208501359250604085013567ffffffffffffffff81111561244e57600080fd5b61245a87828801612032565b95989497509550505050565b6000806020838503121561247957600080fd5b823567ffffffffffffffff8082111561249157600080fd5b818501915085601f8301126124a557600080fd5b8135818111156124b457600080fd5b8660208260051b85010111156124c957600080fd5b60209290920196919550909350505050565b60005b838110156124f65781810151838201526020016124de565b50506000910152565b600081518084526125178160208601602086016124db565b601f01601f19169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561258057603f1988860301845261256e8583516124ff565b94509285019290850190600101612552565b5092979650505050505050565b60006020828403121561259f57600080fd5b8151610f308161208a565b8183823760009101908152919050565b6000602082840312156125cc57600080fd5b5051919050565b6000602082840312156125e557600080fd5b815167ffffffffffffffff8111156125fc57600080fd5b8201601f8101841361260d57600080fd5b805161261b612276826121bf565b81815285602083850101111561263057600080fd5b6126418260208301602086016124db565b95945050505050565b60006020828403121561265c57600080fd5b8151610f308161207b565b60006020828403121561267957600080fd5b81518015158114610f3057600080fd5b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b600082516126ca8184602087016124db565b9190910192915050565b84815260a06020820152600060a082015260006004851061270557634e487b7160e01b600052602160045260246000fd5b84604083015260c0606083015261271f60c08301856124ff565b905082608083015295945050505050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261275d57600080fd5b83018035915067ffffffffffffffff82111561277857600080fd5b60200191503681900382131561207457600080fd5b6000600182016127ad57634e487b7160e01b600052601160045260246000fd5b5060010190565b87815260e0602082015260006127cd60e08301896124ff565b82810360408401526127df81896124ff565b905082810360608401526127f381886124ff565b905060ff8616608084015282810360a084015261281081866124ff565b9150508260c083015298975050505050505050565b602081526000610f3060208301846124ff56fea26469706673582212201dd24b41eec30f006454347e9cdc29f9b6e4f4417fd319013938b3660bd3fc6e64736f6c63430008150033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c

-----Decoded View---------------
Arg [0] : interchainTokenService_ (address): 0xB5FB4BE02232B1bBA4dC8f81dc24C26980dE9e3C

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000b5fb4be02232b1bba4dc8f81dc24c26980de9e3c


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.