ETH Price: $3,327.74 (+2.95%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Claim From Chain217454862025-01-31 15:44:595 hrs ago1738338299IN
0x9274b07A...BC8F79ABD
0 ETH0.0015136615.18330214
Claim From Chain217453872025-01-31 15:25:115 hrs ago1738337111IN
0x9274b07A...BC8F79ABD
0 ETH0.0015913915.9610114
Send To Chain217408502025-01-31 0:11:5920 hrs ago1738282319IN
0x9274b07A...BC8F79ABD
0 ETH0.000308964.31820861
Claim From Chain217407712025-01-30 23:55:4720 hrs ago1738281347IN
0x9274b07A...BC8F79ABD
0 ETH0.000152251.84286429
Claim From Chain217407622025-01-30 23:53:5920 hrs ago1738281239IN
0x9274b07A...BC8F79ABD
0 ETH0.000223112.70103771
Claim From Chain217404282025-01-30 22:46:4722 hrs ago1738277207IN
0x9274b07A...BC8F79ABD
0 ETH0.000350834.2471011
Claim From Chain217404242025-01-30 22:45:5922 hrs ago1738277159IN
0x9274b07A...BC8F79ABD
0 ETH0.000451784.53231833
Claim From Chain217395522025-01-30 19:50:2324 hrs ago1738266623IN
0x9274b07A...BC8F79ABD
0 ETH0.000428995.19331096
Claim From Chain217382162025-01-30 15:21:4729 hrs ago1738250507IN
0x9274b07A...BC8F79ABD
0 ETH0.000719158.70590337
Claim From Chain217345842025-01-30 3:12:2341 hrs ago1738206743IN
0x9274b07A...BC8F79ABD
0 ETH0.000173981.74503206
Send To Chain217345722025-01-30 3:09:5941 hrs ago1738206599IN
0x9274b07A...BC8F79ABD
0 ETH0.000097881.47138715
Send To Chain217345552025-01-30 3:06:3541 hrs ago1738206395IN
0x9274b07A...BC8F79ABD
0 ETH0.000280953.68159638
Send To Chain217345552025-01-30 3:06:3541 hrs ago1738206395IN
0x9274b07A...BC8F79ABD
0 ETH0.00026333.69159638
Send To Chain217345052025-01-30 2:56:2341 hrs ago1738205783IN
0x9274b07A...BC8F79ABD
0 ETH0.000256363.3594452
Send To Chain217258992025-01-28 22:06:352 days ago1738101995IN
0x9274b07A...BC8F79ABD
0 ETH0.0010337313.5459427
Send To Chain217226702025-01-28 11:17:233 days ago1738063043IN
0x9274b07A...BC8F79ABD
0 ETH0.000307444.02804319
Claim From Chain217201642025-01-28 2:52:473 days ago1738032767IN
0x9274b07A...BC8F79ABD
0 ETH0.000485135.87214458
Claim From Chain217201392025-01-28 2:47:473 days ago1738032467IN
0x9274b07A...BC8F79ABD
0 ETH0.00049285.96498632
Send To Chain217189052025-01-27 22:39:593 days ago1738017599IN
0x9274b07A...BC8F79ABD
0 ETH0.000570946.44314555
Claim From Chain217185072025-01-27 21:20:113 days ago1738012811IN
0x9274b07A...BC8F79ABD
0 ETH0.0014599517.67391131
Send To Chain217141952025-01-27 6:53:594 days ago1737960839IN
0x9274b07A...BC8F79ABD
0 ETH0.000577018.09263209
Send To Chain217098062025-01-26 16:12:355 days ago1737907955IN
0x9274b07A...BC8F79ABD
0 ETH0.000607397.95799976
Send To Chain217097792025-01-26 16:07:115 days ago1737907631IN
0x9274b07A...BC8F79ABD
0 ETH0.0008212410.76157191
Claim From Chain216945432025-01-24 13:04:597 days ago1737723899IN
0x9274b07A...BC8F79ABD
0 ETH0.0016247219.66572509
Claim From Chain216923052025-01-24 5:35:357 days ago1737696935IN
0x9274b07A...BC8F79ABD
0 ETH0.0004754.76521435
View all transactions

Latest 2 internal transactions

Advanced mode:
Parent Transaction Hash Block
From
To
180747162023-09-06 3:24:11513 days ago1693970651
0x9274b07A...BC8F79ABD
0.00305381 ETH
180746962023-09-06 3:20:11513 days ago1693970411
0x9274b07A...BC8F79ABD
0.00244106 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
HelloBridge

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
paris EvmVersion
File 1 of 8 : HelloBridge.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {HelloBridgeStore} from "./HelloBridgeStore.sol";
/* -------------------------------------------------------------------------- */
/*                                   errors                                   */
/* -------------------------------------------------------------------------- */

error SignerNotWithdrawSigner();
error NoAmountToWithdraw();
error CannotBridgeToUnsupportedChain();
error Paused();
error NotPaused();
error ZeroAddress();

///@notice The owner will always be a multisig wallet.

/* -------------------------------------------------------------------------- */
/*                                 HelloBridge                                */
/* -------------------------------------------------------------------------- */
/**
 * @title A cross-chain bridge for HelloToken
 * @author 0xSimon
 * @notice It is recommended to use the provided UI to bridge your tokens from chain A to chain B
 * @dev Assumptions:
 *     - On chains that this contract is deployed to (besides the mainnet), the entire supply of HelloToken will be minted and sent to this contract.
 */
contract HelloBridge is Ownable {
    using ECDSA for bytes32;

    /* -------------------------------------------------------------------------- */
    /*                                   events                                   */
    /* -------------------------------------------------------------------------- */
    event Deposit(address indexed sender, uint256 amount, uint256 chainId);
    event Claim(address indexed sender, uint256 totalDepositedOnOtherChain, uint256 otherChainId);
    event SupportedChainChanged(uint256 chainID, bool isSupported);
    event SupportedChainsChanged(uint256[] chainIDs, bool isSupported);
    event WithdrawSigner1Changed(address signer);
    event WithdrawSigner2Changed(address signer);
    event PausedChanged(bool depositPaused, bool claimPaused);
    event BridgeStoreChanged(address store);

    /* -------------------------------------------------------------------------- */
    /*                                  constants                                 */
    /* -------------------------------------------------------------------------- */
    /**
     * @notice The HelloToken contract
     */
    IERC20 public immutable HELLO_TOKEN;

    /* -------------------------------------------------------------------------- */
    /*                                   states                                   */
    /* -------------------------------------------------------------------------- */
    /**
     * @notice The signer providing signatures for claiming tokens on the destination chain
     */
    address public withdrawSigner1;
    address public withdrawSigner2;

    /**
     * @notice Storage contract for deposits and withdrawals numbers
     */
    HelloBridgeStore public store;

    /**
     * @notice A mapping to store which destination chains are supported
     */
    mapping(uint256 => bool) public supportedChains;

    bool public depositPaused;
    bool public claimPaused;

    /**
     * @notice Deploys the contract and saves the HelloToken contract address
     *  @dev `msg.sender` is assigned to the owner, pay attention if this contract is deployed via another contract
     *  @param _helloToken The address of HelloToken
     */
    constructor(address _helloToken) {
        HELLO_TOKEN = IERC20(_helloToken);
    }

    /* -------------------------------------------------------------------------- */
    /*                                  external                                  */
    /* -------------------------------------------------------------------------- */
    /**
     * @notice Bridge HelloToken to another chain. HelloToken will be transferred to this contract.
     * @notice Ensure approvals for HelloToken has been set and the destination chain is supported.
     * @param amount Amount of HelloToken to bridge to another chain
     * @param chainId The chain ID of the destination chain
     * @dev Reverts if the destination chain is not supported
     */
    function sendToChain(uint256 amount, uint256 chainId) external {
        if (depositPaused) _revert(Paused.selector);

        // check chain
        if (!supportedChains[chainId]) _revert(CannotBridgeToUnsupportedChain.selector);

        // update state
        uint256 _currentDepsosit = store.totalCrossChainDeposits(msg.sender, chainId);
        store.setTotalCrossChainDeposits(msg.sender, chainId, _currentDepsosit + amount);

        // transfer tokens
        HELLO_TOKEN.transferFrom(msg.sender, address(this), amount);

        emit Deposit(msg.sender, amount, chainId);
    }

    /**
     * @notice Claims tokens deposited in the source chain. A signature is required.
     * @notice HelloToken will be transferred from this account to the caller.
     * @param totalDepositedOnOtherChain The total amount you have deposited in the source chain
     * @param otherChainId The chain ID of the source chain
     * @param signature The signature signed by `withdrawSigner`
     * @dev Reverts if there's no amount to claim.
     * @dev Reverts if the signature is invalid
     * @dev Assumptions:
     *     - `otherChainId` is supported, a user would not have been able to deposit if the path from `otherChainId` to this chain is not supported
     *     - `totalDepositedOnOtherChain` is checked on chain with ID `otherChainId` before a signature is generated for this transaction
     */
    function claimFromChain(
        uint256 totalDepositedOnOtherChain,
        uint256 otherChainId,
        bytes memory signature,
        bytes memory signature2
    ) external {
        if (claimPaused) _revert(Paused.selector);

        // note: this can never undeflow as the user would not have been able to withdraw if they had no balance
        uint256 amountToWithdraw =
            totalDepositedOnOtherChain - store.totalCrossChainWithdrawals(msg.sender, otherChainId);

        // check amount
        if (amountToWithdraw == 0) _revert(NoAmountToWithdraw.selector);

        // check signature
        bytes32 hash = keccak256(
            abi.encodePacked(msg.sender, totalDepositedOnOtherChain, otherChainId, block.chainid, address(this))
        );

        if (hash.toEthSignedMessageHash().recover(signature) != withdrawSigner1) {
            _revert(SignerNotWithdrawSigner.selector);
        }

        if (hash.toEthSignedMessageHash().recover(signature2) != withdrawSigner2) {
            _revert(SignerNotWithdrawSigner.selector);
        }

        // update state
        store.setTotalCrossChainWithdrawals(msg.sender, otherChainId, totalDepositedOnOtherChain);

        // transfer tokens
        HELLO_TOKEN.transfer(msg.sender, amountToWithdraw);

        emit Claim(msg.sender, totalDepositedOnOtherChain, otherChainId);
    }

    /* -------------------------------------------------------------------------- */
    /*                                   owners                                   */
    /* -------------------------------------------------------------------------- */
    /**
     * @notice Owner only - Updates the address of the withdrawal signer
     * @param _withdrawSigner Address of the withdrawal signer
     */
    function setWithdrawSigner(address _withdrawSigner) external onlyOwner {
        // check
        if (_withdrawSigner == address(0)) {
            _revert(ZeroAddress.selector);
        }

        // set
        withdrawSigner1 = _withdrawSigner;

        // emit
        emit WithdrawSigner1Changed(_withdrawSigner);
    }

    function setWithdrawSigner2(address _withdrawSigner2) external onlyOwner {
        // check
        if (_withdrawSigner2 == address(0)) {
            _revert(ZeroAddress.selector);
        }

        // set
        withdrawSigner2 = _withdrawSigner2;

        // emit
        emit WithdrawSigner2Changed(_withdrawSigner2);
    }

    /**
     * @notice Owner only - Updates a supported destination chain
     * @param chainId Chain ID of a destination chain
     * @param isSupported Whether the destination chain is supported
     */
    function setSupportedChain(uint256 chainId, bool isSupported) external onlyOwner {
        _setSupportedChain(chainId, isSupported);

        emit SupportedChainChanged(chainId, isSupported);
    }

    /**
     * @notice Owner only - Batch update supported destination chains
     * @param chainIds Chain IDs of the destination chains
     * @param isSupported Whether the destination chains are supported
     */
    function setSupportedChains(uint256[] calldata chainIds, bool isSupported) external onlyOwner {
        for (uint256 i; i < chainIds.length;) {
            _setSupportedChain(chainIds[i], isSupported);
            unchecked {
                ++i;
            }
        }

        emit SupportedChainsChanged(chainIds, isSupported);
    }

    /**
     * @notice Pause / unpause deposit & claim
     * @param depositPaused_ Whether to pause deposit
     * @param depositPaused_ Whether to pause claim
     */
    function setPaused(bool depositPaused_, bool claimPaused_) external onlyOwner {
        depositPaused = depositPaused_;
        claimPaused = claimPaused_;

        emit PausedChanged(depositPaused_, claimPaused_);
    }

    function setBridgeStore(address a_) external onlyOwner {
        // check
        if (a_ == address(0)) {
            _revert(ZeroAddress.selector);
        }

        // set
        store = HelloBridgeStore(a_);

        // emit
        emit BridgeStoreChanged(a_);
    }

    /**
     * @notice Migrates the bridge contract to another. Tokens in this contract will be transferred to the new contract.
     * @dev The new bridge contract should use the data stored in `store`.
     * @param bridgeAddress Address of the new contract
     */
    function migrateBridge(address bridgeAddress) external onlyOwner {
        // check zero
        if (bridgeAddress == address(0)) {
            _revert(ZeroAddress.selector);
        }

        // check paused
        if (!depositPaused || !claimPaused) {
            _revert(NotPaused.selector);
        }

        HELLO_TOKEN.transfer(bridgeAddress, HELLO_TOKEN.balanceOf(address(this)));
    }

    /* -------------------------------------------------------------------------- */
    /*                                  internal                                  */
    /* -------------------------------------------------------------------------- */
    function _setSupportedChain(uint256 chainId, bool isSupported) internal {
        supportedChains[chainId] = isSupported;
    }

    function _revert(bytes4 selector) internal pure {
        assembly {
            mstore(0x0, selector)
            revert(0x0, 0x04)
        }
    }
}

File 2 of 8 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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);

    /**
     * @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 `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, 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 `from` to `to` 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 from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 3 of 8 : ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV // Deprecated in v4.8
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

File 4 of 8 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 5 of 8 : HelloBridgeStore.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

///@notice The contract is a storage contract for the bridge contract.
///@notice The owner will always be a multisig wallet.

/* -------------------------------------------------------------------------- */
/*                                   errors                                   */
/* -------------------------------------------------------------------------- */
error SignerNotWithdrawSigner();
error NoAmountToWithdraw();
error CannotBridgeToUnsupportedChain();
error Paused();
error NotPaused();
error ZeroAddress();

contract HelloBridgeStore is Ownable {
    /* -------------------------------------------------------------------------- */
    /*                                   errors                                   */
    /* -------------------------------------------------------------------------- */
    error ErrUnauthorized();
    error ErrZeroAddress();

    /* -------------------------------------------------------------------------- */
    /*                                   events                                   */
    /* -------------------------------------------------------------------------- */
    event BridgeContractChanged(address bridgeContract);

    /* -------------------------------------------------------------------------- */
    /*                                   states                                   */
    /* -------------------------------------------------------------------------- */
    /**
     * @notice A mapping that stores how much HelloToken a user has deposited to bridge to a destination chain
     * @dev Maps from userAddress -> chainID -> amount
     */
    mapping(address => mapping(uint256 => uint256)) public totalCrossChainDeposits;

    /**
     * @notice A mapping that stores how much HelloToken a user has withdrawn from a destination chain
     * @dev Maps from userAddress -> chainID -> amount
     */
    mapping(address => mapping(uint256 => uint256)) public totalCrossChainWithdrawals;

    /**
     * @notice The bridge contract associated with this storage contract.
     * This is the only contract authorized to update `totalCrossChainDeposits` & `totalCrossChainWithdrawals`
     */
    address public bridgeContract;

    /* -------------------------------------------------------------------------- */
    /*                                    owner                                   */
    /* -------------------------------------------------------------------------- */
    /**
     * @notice Updates the bridge contract associated with this storage contract
     */
    function setBridgeContract(address b_) external onlyOwner {
        if (b_ == address(0)) {
            revert ErrZeroAddress();
        }

        bridgeContract = b_;

        emit BridgeContractChanged(b_);
    }

    /* -------------------------------------------------------------------------- */
    /*                                  external                                  */
    /* -------------------------------------------------------------------------- */
    /**
     * @notice Updates totalCrossChainDeposits of a user to a destination chain
     * @param address_ The address to update
     * @param chainID_ The destination chainID of the deposit
     * @param amount_ The amount of token deposited
     */
    function setTotalCrossChainDeposits(address address_, uint256 chainID_, uint256 amount_) external {
        if (msg.sender != bridgeContract) {
            revert ErrUnauthorized();
        }

        totalCrossChainDeposits[address_][chainID_] = amount_;
    }

    /**
     * @notice Updates totalCrossChainWithdrawals of a user from a source chain
     * @param address_ The address to update
     * @param chainID_ The source chainID of the withdrawal
     * @param amount_ The amount of token withdrawn
     */
    function setTotalCrossChainWithdrawals(address address_, uint256 chainID_, uint256 amount_) external {
        if (msg.sender != bridgeContract) {
            revert ErrUnauthorized();
        }

        totalCrossChainWithdrawals[address_][chainID_] = amount_;
    }
}

File 6 of 8 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

import "./math/Math.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

File 7 of 8 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 8 of 8 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

Settings
{
  "remappings": [
    "forge-std/=lib/forge-std/src/",
    "solmate/=lib/solmate/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "closedsea/=lib/closedsea/src/",
    "erc4626-tests/=lib/closedsea/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "erc721a-upgradeable/=lib/closedsea/lib/erc721a-upgradeable/contracts/",
    "erc721a/=lib/erc721a/contracts/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "operator-filter-registry/=lib/closedsea/lib/operator-filter-registry/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_helloToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"store","type":"address"}],"name":"BridgeStoreChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalDepositedOnOtherChain","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"otherChainId","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"depositPaused","type":"bool"},{"indexed":false,"internalType":"bool","name":"claimPaused","type":"bool"}],"name":"PausedChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"chainID","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isSupported","type":"bool"}],"name":"SupportedChainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"chainIDs","type":"uint256[]"},{"indexed":false,"internalType":"bool","name":"isSupported","type":"bool"}],"name":"SupportedChainsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"WithdrawSigner1Changed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"WithdrawSigner2Changed","type":"event"},{"inputs":[],"name":"HELLO_TOKEN","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"totalDepositedOnOtherChain","type":"uint256"},{"internalType":"uint256","name":"otherChainId","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"signature2","type":"bytes"}],"name":"claimFromChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bridgeAddress","type":"address"}],"name":"migrateBridge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"sendToChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"a_","type":"address"}],"name":"setBridgeStore","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"depositPaused_","type":"bool"},{"internalType":"bool","name":"claimPaused_","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"bool","name":"isSupported","type":"bool"}],"name":"setSupportedChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"chainIds","type":"uint256[]"},{"internalType":"bool","name":"isSupported","type":"bool"}],"name":"setSupportedChains","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_withdrawSigner","type":"address"}],"name":"setWithdrawSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_withdrawSigner2","type":"address"}],"name":"setWithdrawSigner2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"store","outputs":[{"internalType":"contract HelloBridgeStore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"supportedChains","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawSigner1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawSigner2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60a060405234801561001057600080fd5b50604051611aa3380380611aa383398101604081905261002f91610099565b61003833610049565b6001600160a01b03166080526100c9565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100ab57600080fd5b81516001600160a01b03811681146100c257600080fd5b9392505050565b6080516119aa6100f9600039600081816101ea0152818161053d01528181610aef0152610fe801526119aa6000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063711c9a37116100cd578063a717640b11610081578063d7f5b35911610066578063d7f5b35914610306578063ebc6ff9d14610319578063f2fde38b1461032c57600080fd5b8063a717640b146102e1578063ab5e124a146102f457600080fd5b80637ccbfe7c116100b25780637ccbfe7c146102905780638da5cb5b146102a3578063975057e7146102c157600080fd5b8063711c9a3714610275578063715018a61461028857600080fd5b8063257f9e7b11610124578063548d496f11610109578063548d496f1461021f5780636426be48146102425780636d3d6a911461025557600080fd5b8063257f9e7b146101e557806346c6f5f41461020c57600080fd5b806302befd241461015657806308eebf9014610178578063170fe86c1461018d5780631a82bd59146101d2575b600080fd5b6005546101639060ff1681565b60405190151581526020015b60405180910390f35b61018b610186366004611579565b61033f565b005b6001546101ad9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161016f565b61018b6101e036600461159b565b610602565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b61018b61021a3660046115e6565b6106c8565b61016361022d366004611616565b60046020526000908152604090205460ff1681565b61018b61025036600461162f565b610747565b6002546101ad9073ffffffffffffffffffffffffffffffffffffffff1681565b61018b61028336600461165d565b6107e5565b61018b61089b565b61018b61029e36600461159b565b6108af565b60005473ffffffffffffffffffffffffffffffffffffffff166101ad565b6003546101ad9073ffffffffffffffffffffffffffffffffffffffff1681565b61018b6102ef36600461159b565b61096e565b60055461016390610100900460ff1681565b61018b61031436600461159b565b610a2d565b61018b6103273660046117bd565b610c11565b61018b61033a36600461159b565b6110b0565b60055460ff1615610373576103737f9e87fac80000000000000000000000000000000000000000000000000000000061116c565b60008181526004602052604090205460ff166103b2576103b27f8ebb6aa50000000000000000000000000000000000000000000000000000000061116c565b6003546040517f74a65b5f0000000000000000000000000000000000000000000000000000000081523360048201526024810183905260009173ffffffffffffffffffffffffffffffffffffffff16906374a65b5f90604401602060405180830381865afa158015610428573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044c9190611834565b60035490915073ffffffffffffffffffffffffffffffffffffffff16636de554c43384610479878661187c565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff909316600484015260248301919091526044820152606401600060405180830381600087803b1580156104ec57600080fd5b505af1158015610500573d6000803e3d6000fd5b50506040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018690527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1692506323b872dd91506064016020604051808303816000875af115801561059d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c1919061188f565b50604080518481526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a2505050565b61060a611176565b73ffffffffffffffffffffffffffffffffffffffff811661064e5761064e7fd92e233d0000000000000000000000000000000000000000000000000000000061116c565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f35e0a7f3c10415eb269af79bbcb131563e1339ee9a581b758f73d0fb80c6348b906020015b60405180910390a150565b6106d0611176565b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168215151790556040805183815282151560208201527fcf8759e93af27d52cf10a12579839840971169859bc59799b2691d6d8f4ecced91015b60405180910390a15050565b61074f611176565b6005805482151561010081027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff8615159081167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090941693909317179092556040805191825260208201929092527fdc08680557789d1cf3e829a8db03ad2cc81a876ec59b82e3405d24d670eb8ecd910161073b565b6107ed611176565b60005b8281101561085a5761085284848381811061080d5761080d6118ac565b6020908102929092013560009081526004909252506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016841515179055565b6001016107f0565b507fb31e572a57abda47b6e0f162af108af158a4e7c040c6fe90ddbd5e73a224d53c83838360405161088e939291906118db565b60405180910390a1505050565b6108a3611176565b6108ad60006111f7565b565b6108b7611176565b73ffffffffffffffffffffffffffffffffffffffff81166108fb576108fb7fd92e233d0000000000000000000000000000000000000000000000000000000061116c565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f1b6903c6fde62e8b98c165679268e2ba4468035ee9722f577391b163680d6edd906020016106bd565b610976611176565b73ffffffffffffffffffffffffffffffffffffffff81166109ba576109ba7fd92e233d0000000000000000000000000000000000000000000000000000000061116c565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fc4e6d54e106b8070ebd1657aef7ed58a60b804c3f421a1d5d48014e8ab391ca3906020016106bd565b610a35611176565b73ffffffffffffffffffffffffffffffffffffffff8116610a7957610a797fd92e233d0000000000000000000000000000000000000000000000000000000061116c565b60055460ff161580610a935750600554610100900460ff16155b15610ac157610ac17f6cd602010000000000000000000000000000000000000000000000000000000061116c565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a9059cbb90839083906370a0823190602401602060405180830381865afa158015610b55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b799190611834565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044016020604051808303816000875af1158015610be9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0d919061188f565b5050565b600554610100900460ff1615610c4a57610c4a7f9e87fac80000000000000000000000000000000000000000000000000000000061116c565b6003546040517fb97c27e20000000000000000000000000000000000000000000000000000000081523360048201526024810185905260009173ffffffffffffffffffffffffffffffffffffffff169063b97c27e290604401602060405180830381865afa158015610cc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce49190611834565b610cee9086611932565b905080600003610d2157610d217f6ac2fea10000000000000000000000000000000000000000000000000000000061116c565b6040517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000033606090811b82166020840152603483018890526054830187905246607484015230901b16609482015260009060a801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012060015490915073ffffffffffffffffffffffffffffffffffffffff16610e2885610e22846040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9061126c565b73ffffffffffffffffffffffffffffffffffffffff1614610e6c57610e6c7f630f5e630000000000000000000000000000000000000000000000000000000061116c565b60025473ffffffffffffffffffffffffffffffffffffffff16610ee084610e22846040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff1614610f2457610f247f630f5e630000000000000000000000000000000000000000000000000000000061116c565b6003546040517f97b6cb91000000000000000000000000000000000000000000000000000000008152336004820152602481018790526044810188905273ffffffffffffffffffffffffffffffffffffffff909116906397b6cb9190606401600060405180830381600087803b158015610f9d57600080fd5b505af1158015610fb1573d6000803e3d6000fd5b50506040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018590527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16925063a9059cbb91506044016020604051808303816000875af1158015611048573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061106c919061188f565b50604080518781526020810187905233917f34fcbac0073d7c3d388e51312faf357774904998eeb8fca628b9e6f65ee1cbf7910160405180910390a2505050505050565b6110b8611176565b73ffffffffffffffffffffffffffffffffffffffff8116611160576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b611169816111f7565b50565b8060005260046000fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146108ad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611157565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080600061127b8585611292565b91509150611288816112d7565b5090505b92915050565b60008082516041036112c85760208301516040840151606085015160001a6112bc8782858561148a565b945094505050506112d0565b506000905060025b9250929050565b60008160048111156112eb576112eb611945565b036112f35750565b600181600481111561130757611307611945565b0361136e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401611157565b600281600481111561138257611382611945565b036113e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401611157565b60038160048111156113fd576113fd611945565b03611169576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401611157565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156114c15750600090506003611570565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611515573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661156957600060019250925050611570565b9150600090505b94509492505050565b6000806040838503121561158c57600080fd5b50508035926020909101359150565b6000602082840312156115ad57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146115d157600080fd5b9392505050565b801515811461116957600080fd5b600080604083850312156115f957600080fd5b82359150602083013561160b816115d8565b809150509250929050565b60006020828403121561162857600080fd5b5035919050565b6000806040838503121561164257600080fd5b823561164d816115d8565b9150602083013561160b816115d8565b60008060006040848603121561167257600080fd5b833567ffffffffffffffff8082111561168a57600080fd5b818601915086601f83011261169e57600080fd5b8135818111156116ad57600080fd5b8760208260051b85010111156116c257600080fd5b602092830195509350508401356116d8816115d8565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261172357600080fd5b813567ffffffffffffffff8082111561173e5761173e6116e3565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611784576117846116e3565b8160405283815286602085880101111561179d57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080608085870312156117d357600080fd5b8435935060208501359250604085013567ffffffffffffffff808211156117f957600080fd5b61180588838901611712565b9350606087013591508082111561181b57600080fd5b5061182887828801611712565b91505092959194509250565b60006020828403121561184657600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561128c5761128c61184d565b6000602082840312156118a157600080fd5b81516115d1816115d8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6040815282604082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84111561191457600080fd5b8360051b808660608501379215156020830152500160600192915050565b8181038181111561128c5761128c61184d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea2646970667358221220151d5cf1eb13139ff5255f4b2481115e7015894b09753c872d2bbc8fcddf250464736f6c63430008130033000000000000000000000000411099c0b413f4feddb10edf6a8be63bd321311c

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101515760003560e01c8063711c9a37116100cd578063a717640b11610081578063d7f5b35911610066578063d7f5b35914610306578063ebc6ff9d14610319578063f2fde38b1461032c57600080fd5b8063a717640b146102e1578063ab5e124a146102f457600080fd5b80637ccbfe7c116100b25780637ccbfe7c146102905780638da5cb5b146102a3578063975057e7146102c157600080fd5b8063711c9a3714610275578063715018a61461028857600080fd5b8063257f9e7b11610124578063548d496f11610109578063548d496f1461021f5780636426be48146102425780636d3d6a911461025557600080fd5b8063257f9e7b146101e557806346c6f5f41461020c57600080fd5b806302befd241461015657806308eebf9014610178578063170fe86c1461018d5780631a82bd59146101d2575b600080fd5b6005546101639060ff1681565b60405190151581526020015b60405180910390f35b61018b610186366004611579565b61033f565b005b6001546101ad9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161016f565b61018b6101e036600461159b565b610602565b6101ad7f000000000000000000000000411099c0b413f4feddb10edf6a8be63bd321311c81565b61018b61021a3660046115e6565b6106c8565b61016361022d366004611616565b60046020526000908152604090205460ff1681565b61018b61025036600461162f565b610747565b6002546101ad9073ffffffffffffffffffffffffffffffffffffffff1681565b61018b61028336600461165d565b6107e5565b61018b61089b565b61018b61029e36600461159b565b6108af565b60005473ffffffffffffffffffffffffffffffffffffffff166101ad565b6003546101ad9073ffffffffffffffffffffffffffffffffffffffff1681565b61018b6102ef36600461159b565b61096e565b60055461016390610100900460ff1681565b61018b61031436600461159b565b610a2d565b61018b6103273660046117bd565b610c11565b61018b61033a36600461159b565b6110b0565b60055460ff1615610373576103737f9e87fac80000000000000000000000000000000000000000000000000000000061116c565b60008181526004602052604090205460ff166103b2576103b27f8ebb6aa50000000000000000000000000000000000000000000000000000000061116c565b6003546040517f74a65b5f0000000000000000000000000000000000000000000000000000000081523360048201526024810183905260009173ffffffffffffffffffffffffffffffffffffffff16906374a65b5f90604401602060405180830381865afa158015610428573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061044c9190611834565b60035490915073ffffffffffffffffffffffffffffffffffffffff16636de554c43384610479878661187c565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff909316600484015260248301919091526044820152606401600060405180830381600087803b1580156104ec57600080fd5b505af1158015610500573d6000803e3d6000fd5b50506040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018690527f000000000000000000000000411099c0b413f4feddb10edf6a8be63bd321311c73ffffffffffffffffffffffffffffffffffffffff1692506323b872dd91506064016020604051808303816000875af115801561059d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c1919061188f565b50604080518481526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a2505050565b61060a611176565b73ffffffffffffffffffffffffffffffffffffffff811661064e5761064e7fd92e233d0000000000000000000000000000000000000000000000000000000061116c565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f35e0a7f3c10415eb269af79bbcb131563e1339ee9a581b758f73d0fb80c6348b906020015b60405180910390a150565b6106d0611176565b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168215151790556040805183815282151560208201527fcf8759e93af27d52cf10a12579839840971169859bc59799b2691d6d8f4ecced91015b60405180910390a15050565b61074f611176565b6005805482151561010081027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff8615159081167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090941693909317179092556040805191825260208201929092527fdc08680557789d1cf3e829a8db03ad2cc81a876ec59b82e3405d24d670eb8ecd910161073b565b6107ed611176565b60005b8281101561085a5761085284848381811061080d5761080d6118ac565b6020908102929092013560009081526004909252506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016841515179055565b6001016107f0565b507fb31e572a57abda47b6e0f162af108af158a4e7c040c6fe90ddbd5e73a224d53c83838360405161088e939291906118db565b60405180910390a1505050565b6108a3611176565b6108ad60006111f7565b565b6108b7611176565b73ffffffffffffffffffffffffffffffffffffffff81166108fb576108fb7fd92e233d0000000000000000000000000000000000000000000000000000000061116c565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f1b6903c6fde62e8b98c165679268e2ba4468035ee9722f577391b163680d6edd906020016106bd565b610976611176565b73ffffffffffffffffffffffffffffffffffffffff81166109ba576109ba7fd92e233d0000000000000000000000000000000000000000000000000000000061116c565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fc4e6d54e106b8070ebd1657aef7ed58a60b804c3f421a1d5d48014e8ab391ca3906020016106bd565b610a35611176565b73ffffffffffffffffffffffffffffffffffffffff8116610a7957610a797fd92e233d0000000000000000000000000000000000000000000000000000000061116c565b60055460ff161580610a935750600554610100900460ff16155b15610ac157610ac17f6cd602010000000000000000000000000000000000000000000000000000000061116c565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000411099c0b413f4feddb10edf6a8be63bd321311c73ffffffffffffffffffffffffffffffffffffffff169063a9059cbb90839083906370a0823190602401602060405180830381865afa158015610b55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b799190611834565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044016020604051808303816000875af1158015610be9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0d919061188f565b5050565b600554610100900460ff1615610c4a57610c4a7f9e87fac80000000000000000000000000000000000000000000000000000000061116c565b6003546040517fb97c27e20000000000000000000000000000000000000000000000000000000081523360048201526024810185905260009173ffffffffffffffffffffffffffffffffffffffff169063b97c27e290604401602060405180830381865afa158015610cc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce49190611834565b610cee9086611932565b905080600003610d2157610d217f6ac2fea10000000000000000000000000000000000000000000000000000000061116c565b6040517fffffffffffffffffffffffffffffffffffffffff00000000000000000000000033606090811b82166020840152603483018890526054830187905246607484015230901b16609482015260009060a801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012060015490915073ffffffffffffffffffffffffffffffffffffffff16610e2885610e22846040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b9061126c565b73ffffffffffffffffffffffffffffffffffffffff1614610e6c57610e6c7f630f5e630000000000000000000000000000000000000000000000000000000061116c565b60025473ffffffffffffffffffffffffffffffffffffffff16610ee084610e22846040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff1614610f2457610f247f630f5e630000000000000000000000000000000000000000000000000000000061116c565b6003546040517f97b6cb91000000000000000000000000000000000000000000000000000000008152336004820152602481018790526044810188905273ffffffffffffffffffffffffffffffffffffffff909116906397b6cb9190606401600060405180830381600087803b158015610f9d57600080fd5b505af1158015610fb1573d6000803e3d6000fd5b50506040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018590527f000000000000000000000000411099c0b413f4feddb10edf6a8be63bd321311c73ffffffffffffffffffffffffffffffffffffffff16925063a9059cbb91506044016020604051808303816000875af1158015611048573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061106c919061188f565b50604080518781526020810187905233917f34fcbac0073d7c3d388e51312faf357774904998eeb8fca628b9e6f65ee1cbf7910160405180910390a2505050505050565b6110b8611176565b73ffffffffffffffffffffffffffffffffffffffff8116611160576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b611169816111f7565b50565b8060005260046000fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146108ad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611157565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080600061127b8585611292565b91509150611288816112d7565b5090505b92915050565b60008082516041036112c85760208301516040840151606085015160001a6112bc8782858561148a565b945094505050506112d0565b506000905060025b9250929050565b60008160048111156112eb576112eb611945565b036112f35750565b600181600481111561130757611307611945565b0361136e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401611157565b600281600481111561138257611382611945565b036113e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401611157565b60038160048111156113fd576113fd611945565b03611169576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401611157565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156114c15750600090506003611570565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611515573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661156957600060019250925050611570565b9150600090505b94509492505050565b6000806040838503121561158c57600080fd5b50508035926020909101359150565b6000602082840312156115ad57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146115d157600080fd5b9392505050565b801515811461116957600080fd5b600080604083850312156115f957600080fd5b82359150602083013561160b816115d8565b809150509250929050565b60006020828403121561162857600080fd5b5035919050565b6000806040838503121561164257600080fd5b823561164d816115d8565b9150602083013561160b816115d8565b60008060006040848603121561167257600080fd5b833567ffffffffffffffff8082111561168a57600080fd5b818601915086601f83011261169e57600080fd5b8135818111156116ad57600080fd5b8760208260051b85010111156116c257600080fd5b602092830195509350508401356116d8816115d8565b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261172357600080fd5b813567ffffffffffffffff8082111561173e5761173e6116e3565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611784576117846116e3565b8160405283815286602085880101111561179d57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080608085870312156117d357600080fd5b8435935060208501359250604085013567ffffffffffffffff808211156117f957600080fd5b61180588838901611712565b9350606087013591508082111561181b57600080fd5b5061182887828801611712565b91505092959194509250565b60006020828403121561184657600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561128c5761128c61184d565b6000602082840312156118a157600080fd5b81516115d1816115d8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6040815282604082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84111561191457600080fd5b8360051b808660608501379215156020830152500160600192915050565b8181038181111561128c5761128c61184d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea2646970667358221220151d5cf1eb13139ff5255f4b2481115e7015894b09753c872d2bbc8fcddf250464736f6c63430008130033

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

000000000000000000000000411099c0b413f4feddb10edf6a8be63bd321311c

-----Decoded View---------------
Arg [0] : _helloToken (address): 0x411099C0b413f4fedDb10Edf6a8be63BD321311C

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000411099c0b413f4feddb10edf6a8be63bd321311c


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
Loading...
Loading
[ Download: CSV Export  ]
[ 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.