Contract 0xfe7de3c1e1bd252c67667b56347cabfc6df08df4 4

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x4e6e81d0399a9d841ef4141129dfdb2c97ea029cd0e54deff3905f5f7efc0143Initialize157782462022-06-03 4:01:0830 days 19 hrs ago0xb779daead6031ef189cad4ac438c991efe7635a7 IN 0xfe7de3c1e1bd252c67667b56347cabfc6df08df40 HT0.00025668675 2.25
0x2d726b42d2d769bfbe0a59896fe20408c9714da56fa8e2acc6dd8d8daff45ce50x60806040109230652021-12-16 14:00:27199 days 9 hrs ago0xd6f0dabbbccd143f7d526a82ca176b5395ccc844 IN  Create: SignatureVerifier0 HT0.00431486 2.5
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SignatureVerifier

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 12 : SignatureVerifier.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.7;

import "./OraclesManager.sol";
import "../interfaces/ISignatureVerifier.sol";
import "../libraries/SignatureUtil.sol";

/// @dev It's used to verify that a transfer is signed by oracles.
contract SignatureVerifier is OraclesManager, ISignatureVerifier {
    using SignatureUtil for bytes;
    using SignatureUtil for bytes32;

    /* ========== STATE VARIABLES ========== */
    /// @dev Number of required confirmations per block after the extra check is enabled
    uint8 public confirmationThreshold;
    /// @dev submissions count in current block
    uint40 public submissionsInBlock;
    /// @dev Current block
    uint40 public currentBlock;

    /// @dev Debridge gate address
    address public debridgeAddress;

    /* ========== ERRORS ========== */

    error DeBridgeGateBadRole();
    error NotConfirmedByRequiredOracles();
    error NotConfirmedThreshold();
    error SubmissionNotConfirmed();
    error DuplicateSignatures();

    /* ========== MODIFIERS ========== */

    modifier onlyDeBridgeGate() {
        if (msg.sender != debridgeAddress) revert DeBridgeGateBadRole();
        _;
    }

    /* ========== CONSTRUCTOR  ========== */

    /// @dev Constructor that initializes the most important configurations.
    /// @param _minConfirmations Common confirmations count.
    /// @param _confirmationThreshold Confirmations per block after the extra check is enabled.
    /// @param _excessConfirmations Confirmations count in case of excess activity.
    function initialize(
        uint8 _minConfirmations,
        uint8 _confirmationThreshold,
        uint8 _excessConfirmations,
        address _debridgeAddress
    ) public initializer {
        OraclesManager.initialize(_minConfirmations, _excessConfirmations);
        confirmationThreshold = _confirmationThreshold;
        debridgeAddress = _debridgeAddress;
    }


    /// @inheritdoc ISignatureVerifier
    function submit(
        bytes32 _submissionId,
        bytes memory _signatures,
        uint8 _excessConfirmations
    ) external override onlyDeBridgeGate {
        //Need confirmation to confirm submission
        uint8 needConfirmations = _excessConfirmations > minConfirmations
            ? _excessConfirmations
            : minConfirmations;
        // Count of required(DSRM) oracles confirmation
        uint256 currentRequiredOraclesCount;
        // stack variable to aggregate confirmations and write to storage once
        uint8 confirmations;
        uint256 signaturesCount = _countSignatures(_signatures);
        address[] memory validators = new address[](signaturesCount);
        for (uint256 i = 0; i < signaturesCount; i++) {
            (bytes32 r, bytes32 s, uint8 v) = _signatures.parseSignature(i * 65);
            address oracle = ecrecover(_submissionId.getUnsignedMsg(), v, r, s);
            if (getOracleInfo[oracle].isValid) {
                for (uint256 k = 0; k < i; k++) {
                    if (validators[k] == oracle) revert DuplicateSignatures();
                }
                validators[i] = oracle;

                confirmations += 1;
                emit Confirmed(_submissionId, oracle);
                if (getOracleInfo[oracle].required) {
                    currentRequiredOraclesCount += 1;
                }
                if (
                    confirmations >= needConfirmations &&
                    currentRequiredOraclesCount >= requiredOraclesCount
                ) {
                    break;
                }
            }
        }

        if (currentRequiredOraclesCount != requiredOraclesCount)
            revert NotConfirmedByRequiredOracles();

        if (confirmations >= minConfirmations) {
            if (currentBlock == uint40(block.number)) {
                submissionsInBlock += 1;
            } else {
                currentBlock = uint40(block.number);
                submissionsInBlock = 1;
            }
            emit SubmissionApproved(_submissionId);
        }

        if (submissionsInBlock > confirmationThreshold) {
            if (confirmations < excessConfirmations) revert NotConfirmedThreshold();
        }

        if (confirmations < needConfirmations) revert SubmissionNotConfirmed();
    }

    /* ========== ADMIN ========== */

    /// @dev Sets minimal required confirmations.
    /// @param _confirmationThreshold Confirmation info.
    function setThreshold(uint8 _confirmationThreshold) external onlyAdmin {
        if (_confirmationThreshold == 0) revert WrongArgument();
        confirmationThreshold = _confirmationThreshold;
    }

    /// @dev Sets core debridge conrtact address.
    /// @param _debridgeAddress Debridge address.
    function setDebridgeAddress(address _debridgeAddress) external onlyAdmin {
        debridgeAddress = _debridgeAddress;
    }

    /* ========== VIEW ========== */

    /// @dev Check is valid signature
    /// @param _submissionId Submission identifier.
    /// @param _signature signature by oracle.
    function isValidSignature(bytes32 _submissionId, bytes memory _signature)
        external
        view
        returns (bool)
    {
        (bytes32 r, bytes32 s, uint8 v) = _signature.splitSignature();
        address oracle = ecrecover(_submissionId.getUnsignedMsg(), v, r, s);
        return getOracleInfo[oracle].isValid;
    }

    /* ========== INTERNAL ========== */

    function _countSignatures(bytes memory _signatures) internal pure returns (uint256) {
        return _signatures.length % 65 == 0 ? _signatures.length / 65 : 0;
    }

    // ============ Version Control ============
    /// @dev Get this contract's version
    function version() external pure returns (uint256) {
        return 201; // 2.0.1
    }
}

File 2 of 12 : OraclesManager.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.7;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "../interfaces/IOraclesManager.sol";

/// @dev The base contract for oracles management. Allows adding/removing oracles,
/// managing the minimal required amount of confirmations.
contract OraclesManager is Initializable, AccessControlUpgradeable, IOraclesManager {
    /* ========== STATE VARIABLES ========== */

    /// @dev Minimal required confirmations
    uint8 public minConfirmations;
    /// @dev Minimal required confirmations in case of too many confirmations
    uint8 public excessConfirmations;
    /// @dev Count of required oracles
    uint8 public requiredOraclesCount;
    /// @dev Oracle addresses
    address[] public oracleAddresses;
    /// @dev Maps an oracle address to the oracle details
    mapping(address => OracleInfo) public getOracleInfo;

    /* ========== ERRORS ========== */

    error AdminBadRole();
    error OracleBadRole();

    error OracleAlreadyExist();
    error OracleNotFound();

    error WrongArgument();
    error LowMinConfirmations();


    /* ========== MODIFIERS ========== */

    modifier onlyAdmin() {
        if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert AdminBadRole();
        _;
    }
    modifier onlyOracle() {
        if (!getOracleInfo[msg.sender].isValid) revert OracleBadRole();
        _;
    }

    /* ========== CONSTRUCTOR  ========== */

    /// @dev Constructor that initializes the most important configurations.
    /// @param _minConfirmations Minimal required confirmations.
    /// @param _excessConfirmations Minimal required confirmations in case of too many confirmations.
    function initialize(uint8 _minConfirmations, uint8 _excessConfirmations) internal {
        if (_minConfirmations == 0 || _excessConfirmations < _minConfirmations) revert LowMinConfirmations();
        minConfirmations = _minConfirmations;
        excessConfirmations = _excessConfirmations;
        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
    }

    /* ========== ADMIN ========== */

    /// @dev Sets minimal required confirmations.
    /// @param _minConfirmations Minimal required confirmations.
    function setMinConfirmations(uint8 _minConfirmations) external onlyAdmin {
        if (_minConfirmations < oracleAddresses.length / 2 + 1) revert LowMinConfirmations();
        minConfirmations = _minConfirmations;
    }

    /// @dev Sets minimal required confirmations in case of too many confirmations.
    /// @param _excessConfirmations Minimal required confirmations in case of too many confirmations.
    function setExcessConfirmations(uint8 _excessConfirmations) external onlyAdmin {
        if (_excessConfirmations < minConfirmations) revert LowMinConfirmations();
        excessConfirmations = _excessConfirmations;
    }

    /// @dev Add oracles.
    /// @param _oracles Oracles' addresses.
    /// @param _required A transfer will not be confirmed without oracles having required set to true,
    function addOracles(
        address[] memory _oracles,
        bool[] memory _required
    ) external onlyAdmin {
        if (_oracles.length != _required.length) revert WrongArgument();
        if (minConfirmations < (oracleAddresses.length +  _oracles.length) / 2 + 1) revert LowMinConfirmations();

        for (uint256 i = 0; i < _oracles.length; i++) {
            OracleInfo storage oracleInfo = getOracleInfo[_oracles[i]];
            if (oracleInfo.exist) revert OracleAlreadyExist();

            oracleAddresses.push(_oracles[i]);

            if (_required[i]) {
                requiredOraclesCount += 1;
            }

            oracleInfo.exist = true;
            oracleInfo.isValid = true;
            oracleInfo.required = _required[i];

            emit AddOracle(_oracles[i], _required[i]);
        }
    }

    /// @dev Update an oracle.
    /// @param _oracle An oracle address.
    /// @param _isValid Is this oracle valid, i.e. should it be treated as an oracle.
    /// @param _required If set to true a transfer will not be confirmed without this oracle.
    function updateOracle(
        address _oracle,
        bool _isValid,
        bool _required
    ) external onlyAdmin {
        //If oracle is invalid, it must be not required
        if (!_isValid && _required) revert WrongArgument();

        OracleInfo storage oracleInfo = getOracleInfo[_oracle];
        if (!oracleInfo.exist) revert OracleNotFound();

        if (oracleInfo.required && !_required) {
            requiredOraclesCount -= 1;
        } else if (!oracleInfo.required && _required) {
            requiredOraclesCount += 1;
        }
        if (oracleInfo.isValid && !_isValid) {
            // remove oracle from oracleAddresses array without keeping an order
            for (uint256 i = 0; i < oracleAddresses.length; i++) {
                if (oracleAddresses[i] == _oracle) {
                    oracleAddresses[i] = oracleAddresses[oracleAddresses.length - 1];
                    oracleAddresses.pop();
                    break;
                }
            }
        } else if (!oracleInfo.isValid && _isValid) {
            if (minConfirmations < (oracleAddresses.length + 1) / 2 + 1) revert LowMinConfirmations();
            oracleAddresses.push(_oracle);
        }
        oracleInfo.isValid = _isValid;
        oracleInfo.required = _required;
        emit UpdateOracle(_oracle, _required, _isValid);
    }
}

File 3 of 12 : ISignatureVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;

interface ISignatureVerifier {

    /* ========== EVENTS ========== */

    /// @dev Emitted once the submission is confirmed by one oracle.
    event Confirmed(bytes32 submissionId, address operator);
    /// @dev Emitted once the submission is confirmed by min required amount of oracles.
    event DeployConfirmed(bytes32 deployId, address operator);

    /* ========== FUNCTIONS ========== */

    /// @dev Check confirmation (validate signatures) for the transfer request.
    /// @param _submissionId Submission identifier.
    /// @param _signatures Array of signatures by oracles.
    /// @param _excessConfirmations override min confirmations count
    function submit(
        bytes32 _submissionId,
        bytes memory _signatures,
        uint8 _excessConfirmations
    ) external;

}

File 4 of 12 : SignatureUtil.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.7;

library SignatureUtil {
    /* ========== ERRORS ========== */

    error WrongArgumentLength();
    error SignatureInvalidLength();
    error SignatureInvalidV();

    /// @dev Prepares raw msg that was signed by the oracle.
    /// @param _submissionId Submission identifier.
    function getUnsignedMsg(bytes32 _submissionId) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _submissionId));
    }

    /// @dev Splits signature bytes to r,s,v components.
    /// @param _signature Signature bytes in format r+s+v.
    function splitSignature(bytes memory _signature)
        internal
        pure
        returns (
            bytes32 r,
            bytes32 s,
            uint8 v
        )
    {
        if (_signature.length != 65) revert SignatureInvalidLength();
        return parseSignature(_signature, 0);
    }

    function parseSignature(bytes memory _signatures, uint256 offset)
        internal
        pure
        returns (
            bytes32 r,
            bytes32 s,
            uint8 v
        )
    {
        assembly {
            r := mload(add(_signatures, add(32, offset)))
            s := mload(add(_signatures, add(64, offset)))
            v := and(mload(add(_signatures, add(65, offset))), 0xff)
        }

        if (v < 27) v += 27;
        if (v != 27 && v != 28) revert SignatureInvalidV();
    }

    function toUint256(bytes memory _bytes, uint256 _offset)
        internal
        pure
        returns (uint256 result)
    {
        if (_bytes.length < _offset + 32) revert WrongArgumentLength();

        assembly {
            result := mload(add(add(_bytes, 0x20), _offset))
        }
    }
}

File 5 of 12 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (proxy/utils/Initializable.sol)

pragma solidity ^0.8.0;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
 * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() initializer {}
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }
}

File 6 of 12 : AccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (access/AccessControl.sol)

pragma solidity ^0.8.0;

import "./IAccessControlUpgradeable.sol";
import "../utils/ContextUpgradeable.sol";
import "../utils/StringsUpgradeable.sol";
import "../utils/introspection/ERC165Upgradeable.sol";
import "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable {
    function __AccessControl_init() internal initializer {
        __Context_init_unchained();
        __ERC165_init_unchained();
        __AccessControl_init_unchained();
    }

    function __AccessControl_init_unchained() internal initializer {
    }
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role, _msgSender());
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        StringsUpgradeable.toHexString(uint160(account), 20),
                        " is missing role ",
                        StringsUpgradeable.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     *
     * NOTE: This function is deprecated in favor of {_grantRole}.
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
    uint256[49] private __gap;
}

File 7 of 12 : IOraclesManager.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;

interface IOraclesManager {
    /* ========== STRUCTS ========== */

    struct OracleInfo {
        bool exist; // exist oracle
        bool isValid; // is valid oracle
        bool required; // without this oracle (DSRM), the transfer will not be confirmed
    }

    /* ========== EVENTS ========== */
    /// @dev Emitted when an oracle is added
    /// @param oracle Address of an added oracle
    /// @param required Is this oracle's signature required for every transfer
    event AddOracle(address oracle, bool required);
    /// @dev Emitted when an oracle is updated
    /// @param oracle Address of an updated oracle
    /// @param required Is this oracle's signature required for every transfer
    /// @param isValid Is this oracle valid, i.e. should it be treated as an oracle
    event UpdateOracle(address oracle, bool required, bool isValid);
    /// @dev Emitted once the submission is confirmed by min required amount of oracles
    event DeployApproved(bytes32 deployId);
    /// @dev Emitted once the submission is confirmed by min required amount of oracles
    event SubmissionApproved(bytes32 submissionId);
}

File 8 of 12 : IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControlUpgradeable {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

File 9 of 12 : ContextUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Context.sol)

pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";

/**
 * @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 ContextUpgradeable is Initializable {
    function __Context_init() internal initializer {
        __Context_init_unchained();
    }

    function __Context_init_unchained() internal initializer {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
    uint256[50] private __gap;
}

File 10 of 12 : StringsUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library StringsUpgradeable {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @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] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 11 of 12 : ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165Upgradeable.sol";
import "../../proxy/utils/Initializable.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
    function __ERC165_init() internal initializer {
        __ERC165_init_unchained();
    }

    function __ERC165_init_unchained() internal initializer {
    }
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165Upgradeable).interfaceId;
    }
    uint256[50] private __gap;
}

File 12 of 12 : IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165Upgradeable {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"name":"AdminBadRole","type":"error"},{"inputs":[],"name":"DeBridgeGateBadRole","type":"error"},{"inputs":[],"name":"DuplicateSignatures","type":"error"},{"inputs":[],"name":"LowMinConfirmations","type":"error"},{"inputs":[],"name":"NotConfirmedByRequiredOracles","type":"error"},{"inputs":[],"name":"NotConfirmedThreshold","type":"error"},{"inputs":[],"name":"OracleAlreadyExist","type":"error"},{"inputs":[],"name":"OracleBadRole","type":"error"},{"inputs":[],"name":"OracleNotFound","type":"error"},{"inputs":[],"name":"SignatureInvalidLength","type":"error"},{"inputs":[],"name":"SignatureInvalidV","type":"error"},{"inputs":[],"name":"SubmissionNotConfirmed","type":"error"},{"inputs":[],"name":"WrongArgument","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oracle","type":"address"},{"indexed":false,"internalType":"bool","name":"required","type":"bool"}],"name":"AddOracle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"submissionId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"Confirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"deployId","type":"bytes32"}],"name":"DeployApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"deployId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"DeployConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"submissionId","type":"bytes32"}],"name":"SubmissionApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oracle","type":"address"},{"indexed":false,"internalType":"bool","name":"required","type":"bool"},{"indexed":false,"internalType":"bool","name":"isValid","type":"bool"}],"name":"UpdateOracle","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_oracles","type":"address[]"},{"internalType":"bool[]","name":"_required","type":"bool[]"}],"name":"addOracles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"confirmationThreshold","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentBlock","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"debridgeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"excessConfirmations","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getOracleInfo","outputs":[{"internalType":"bool","name":"exist","type":"bool"},{"internalType":"bool","name":"isValid","type":"bool"},{"internalType":"bool","name":"required","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_minConfirmations","type":"uint8"},{"internalType":"uint8","name":"_confirmationThreshold","type":"uint8"},{"internalType":"uint8","name":"_excessConfirmations","type":"uint8"},{"internalType":"address","name":"_debridgeAddress","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_submissionId","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minConfirmations","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"oracleAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requiredOraclesCount","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_debridgeAddress","type":"address"}],"name":"setDebridgeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_excessConfirmations","type":"uint8"}],"name":"setExcessConfirmations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_minConfirmations","type":"uint8"}],"name":"setMinConfirmations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_confirmationThreshold","type":"uint8"}],"name":"setThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"submissionsInBlock","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_submissionId","type":"bytes32"},{"internalType":"bytes","name":"_signatures","type":"bytes"},{"internalType":"uint8","name":"_excessConfirmations","type":"uint8"}],"name":"submit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"bool","name":"_isValid","type":"bool"},{"internalType":"bool","name":"_required","type":"bool"}],"name":"updateOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}]

608060405234801561001057600080fd5b50611e46806100206000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c806391d14854116100de578063c4e7337711610097578063e12ed13c11610071578063e12ed13c146103de578063e5a98603146103f6578063e7c4393e14610409578063fceb17eb1461041657600080fd5b8063c4e7337714610386578063d547741f146103b8578063dc4bfb85146103cb57600080fd5b806391d14854146102de578063965d0a64146102f1578063a217fddf14610304578063b50492261461030c578063b9b556521461031f578063bfdb6b041461033157600080fd5b806332ea039a1161014b57806354fd4d501161012557806354fd4d501461028c578063698efb9514610293578063794a9c29146102a65780637c533fd3146102b957600080fd5b806332ea039a1461025357806336568abe146102665780634425bd9a1461027957600080fd5b806301ffc9a714610193578063140c0b1e146101bb5780631626ba7e146101d0578063248a9ca3146101e35780632f2ff15d146102145780632fa3ab6314610227575b600080fd5b6101a66101a1366004611ac3565b610423565b60405190151581526020015b60405180910390f35b6101ce6101c9366004611aed565b61045a565b005b6101a66101de366004611a38565b6104c8565b6102066101f13660046119f3565b60009081526065602052604090206001015490565b6040519081526020016101b2565b6101ce610222366004611a0c565b61056c565b609a5461023d90610100900464ffffffffff1681565b60405164ffffffffff90911681526020016101b2565b6101ce610261366004611aed565b610597565b6101ce610274366004611a0c565b610612565b6101ce61028736600461192c565b610695565b60c9610206565b6101ce6102a1366004611b08565b610917565b6101ce6102b43660046118e9565b610a18565b6097546102cc9062010000900460ff1681565b60405160ff90911681526020016101b2565b6101a66102ec366004611a0c565b610d9f565b6101ce6102ff366004611a75565b610dca565b610206600081565b6101ce61031a3660046118ce565b611210565b6097546102cc90610100900460ff1681565b61036761033f3660046118ce565b60996020526000908152604090205460ff808216916101008104821691620100009091041683565b60408051931515845291151560208401521515908201526060016101b2565b609a546103a090600160581b90046001600160a01b031681565b6040516001600160a01b0390911681526020016101b2565b6101ce6103c6366004611a0c565b611279565b6103a06103d93660046119f3565b61129f565b609a5461023d90600160301b900464ffffffffff1681565b6101ce610404366004611aed565b6112c9565b6097546102cc9060ff1681565b609a546102cc9060ff1681565b60006001600160e01b03198216637965db0b60e01b148061045457506301ffc9a760e01b6001600160e01b03198316145b92915050565b610465600033610d9f565b61048257604051636f4720fd60e11b815260040160405180910390fd5b60975460ff90811690821610156104ac5760405163412f84c160e11b815260040160405180910390fd5b6097805460ff9092166101000261ff0019909216919091179055565b6000806000806104d785611328565b925092509250600060016104ea88611367565b6040805160008152602081018083529290925260ff851690820152606081018690526080810185905260a0016020604051602081039080840390855afa158015610538573d6000803e3d6000fd5b505060408051601f1901516001600160a01b0316600090815260996020522054610100900460ff1698975050505050505050565b60008281526065602052604090206001015461058881336113ba565b610592838361141e565b505050565b6105a2600033610d9f565b6105bf57604051636f4720fd60e11b815260040160405180910390fd5b6098546105ce90600290611cbf565b6105d9906001611c59565b8160ff1610156105fc5760405163412f84c160e11b815260040160405180910390fd5b6097805460ff191660ff92909216919091179055565b6001600160a01b03811633146106875760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b61069182826114a4565b5050565b6106a0600033610d9f565b6106bd57604051636f4720fd60e11b815260040160405180910390fd5b80518251146106df57604051634668624160e01b815260040160405180910390fd5b81516098546002916106f091611c59565b6106fa9190611cbf565b610705906001611c59565b60975460ff16101561072a5760405163412f84c160e11b815260040160405180910390fd5b60005b82518110156105925760006099600085848151811061074e5761074e611de4565b6020908102919091018101516001600160a01b03168252810191909152604001600020805490915060ff161561079757604051633ad24c0760e11b815260040160405180910390fd5b60988483815181106107ab576107ab611de4565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b0390921691909117905582518390839081106107fa576107fa611de4565b60200260200101511561083f576001609760028282829054906101000a900460ff166108269190611c9a565b92506101000a81548160ff021916908360ff1602179055505b805461ffff1916610101178155825183908390811061086057610860611de4565b60209081029190910101518154901515620100000262ff00001990911617815583517fe755f450de2082b1e2a5be83219122e863839acc705c368b6e119432edfc360e908590849081106108b6576108b6611de4565b60200260200101518484815181106108d0576108d0611de4565b60200260200101516040516108fc9291906001600160a01b039290921682521515602082015260400190565b60405180910390a1508061090f81611d73565b91505061072d565b600054610100900460ff1680610930575060005460ff16155b6109935760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161067e565b600054610100900460ff161580156109b5576000805461ffff19166101011790555b6109bf858461150b565b609a80546001600160a01b038416600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffff0090911660ff8716171790558015610a11576000805461ff00191690555b5050505050565b610a23600033610d9f565b610a4057604051636f4720fd60e11b815260040160405180910390fd5b81158015610a4b5750805b15610a6957604051634668624160e01b815260040160405180910390fd5b6001600160a01b0383166000908152609960205260409020805460ff16610aa357604051630b0a0e0d60e21b815260040160405180910390fd5b805462010000900460ff168015610ab8575081155b15610af9576001609760028282829054906101000a900460ff16610adc9190611d09565b92506101000a81548160ff021916908360ff160217905550610b4b565b805462010000900460ff16158015610b0e5750815b15610b4b576001609760028282829054906101000a900460ff16610b329190611c9a565b92506101000a81548160ff021916908360ff1602179055505b8054610100900460ff168015610b5f575082155b15610c735760005b609854811015610c6d57846001600160a01b031660988281548110610b8e57610b8e611de4565b6000918252602090912001546001600160a01b03161415610c5b5760988054610bb990600190611cf2565b81548110610bc957610bc9611de4565b600091825260209091200154609880546001600160a01b039092169183908110610bf557610bf5611de4565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506098805480610c3457610c34611dce565b600082815260209020810160001990810180546001600160a01b0319169055019055610c6d565b80610c6581611d73565b915050610b67565b50610d23565b8054610100900460ff16158015610c875750825b15610d2357609854600290610c9d906001611c59565b610ca79190611cbf565b610cb2906001611c59565b60975460ff161015610cd75760405163412f84c160e11b815260040160405180910390fd5b609880546001810182556000919091527f2237a976fa961f5921fd19f2b03c925c725d77b20ce8f790c19709c03de4d8140180546001600160a01b0319166001600160a01b0386161790555b805462ffff00191661010084151590810262ff000019169190911762010000841515908102919091178355604080516001600160a01b038816815260208101929092528101919091527fd0a47d00eff59bee6da649bbe44f1e639db18f184bb4a80783cf8afd2a41e4609060600160405180910390a150505050565b60009182526065602090815260408084206001600160a01b0393909316845291905290205460ff1690565b609a54600160581b90046001600160a01b03163314610dfc576040516388a38fa160e01b815260040160405180910390fd5b60975460009060ff90811690831611610e1a5760975460ff16610e1c565b815b90506000806000610e2c86611564565b905060008167ffffffffffffffff811115610e4957610e49611dfa565b604051908082528060200260200182016040528015610e72578160200160208202803683370190505b50905060005b8281101561108f5760008080610e99610e92856041611cd3565b8c9061158e565b92509250925060006001610eac8e611367565b6040805160008152602081018083529290925260ff851690820152606081018690526080810185905260a0016020604051602081039080840390855afa158015610efa573d6000803e3d6000fd5b505060408051601f1901516001600160a01b038116600090815260996020529190912054909250610100900460ff161590506110785760005b85811015610f9957816001600160a01b0316878281518110610f5757610f57611de4565b60200260200101516001600160a01b03161415610f87576040516317ab4f2360e11b815260040160405180910390fd5b80610f9181611d73565b915050610f33565b5080868681518110610fad57610fad611de4565b6001600160a01b0390921660209283029190910190910152610fd0600189611c9a565b604080518f81526001600160a01b03841660208201529199507fd4964a7cd99f5c1fa8f2420fb5e1d3bd26eadf16e2658cf2e29a67dfda38601e910160405180910390a16001600160a01b03811660009081526099602052604090205462010000900460ff16156110495761104660018a611c59565b98505b8960ff168860ff161015801561106a575060975462010000900460ff168910155b15611078575050505061108f565b50505050808061108790611d73565b915050610e78565b5060975462010000900460ff1684146110bb576040516382635e4d60e01b815260040160405180910390fd5b60975460ff9081169084161061119657609a544364ffffffffff908116600160301b90920416141561112f576001609a60018282829054906101000a900464ffffffffff1661110a9190611c71565b92506101000a81548164ffffffffff021916908364ffffffffff160217905550611162565b609a805465ffffffffff001964ffffffffff4316600160301b02166affffffffffffffffffff0019909116176101001790555b6040518881527f2a6b4960c287d4d53a338f9c9a9f830f37e7b66e67a0a958f68be89a4eeb939d9060200160405180910390a15b609a5460ff811661010090910464ffffffffff1611156111df5760975460ff610100909104811690841610156111df576040516323d8dc8760e01b815260040160405180910390fd5b8460ff168360ff161015611206576040516374bb49d560e01b815260040160405180910390fd5b5050505050505050565b61121b600033610d9f565b61123857604051636f4720fd60e11b815260040160405180910390fd5b609a80546001600160a01b03909216600160581b027fff0000000000000000000000000000000000000000ffffffffffffffffffffff909216919091179055565b60008281526065602052604090206001015461129581336113ba565b61059283836114a4565b609881815481106112af57600080fd5b6000918252602090912001546001600160a01b0316905081565b6112d4600033610d9f565b6112f157604051636f4720fd60e11b815260040160405180910390fd5b60ff811661131257604051634668624160e01b815260040160405180910390fd5b609a805460ff191660ff92909216919091179055565b6000806000835160411461134f5760405163bb5ee95b60e01b815260040160405180910390fd5b61135a84600061158e565b9250925092509193909250565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b6113c48282610d9f565b610691576113dc816001600160a01b031660146115fb565b6113e78360206115fb565b6040516020016113f8929190611b5c565b60408051601f198184030181529082905262461bcd60e51b825261067e91600401611bd1565b6114288282610d9f565b6106915760008281526065602090815260408083206001600160a01b03851684529091529020805460ff191660011790556114603390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6114ae8282610d9f565b156106915760008281526065602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60ff8216158061152057508160ff168160ff16105b1561153e5760405163412f84c160e11b815260040160405180910390fd5b6097805460ff8381166101000261ffff199092169085161717905561069160003361179e565b6000604182516115749190611d8e565b15611580576000610454565b604182516104549190611cbf565b8181016020810151604082015160419092015190919060ff16601b8110156115be576115bb601b82611c9a565b90505b8060ff16601b141580156115d657508060ff16601c14155b156115f457604051630633a0a560e21b815260040160405180910390fd5b9250925092565b6060600061160a836002611cd3565b611615906002611c59565b67ffffffffffffffff81111561162d5761162d611dfa565b6040519080825280601f01601f191660200182016040528015611657576020820181803683370190505b509050600360fc1b8160008151811061167257611672611de4565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106116a1576116a1611de4565b60200101906001600160f81b031916908160001a90535060006116c5846002611cd3565b6116d0906001611c59565b90505b6001811115611748576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061170457611704611de4565b1a60f81b82828151811061171a5761171a611de4565b60200101906001600160f81b031916908160001a90535060049490941c9361174181611d5c565b90506116d3565b5083156117975760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604482015260640161067e565b9392505050565b610691828261141e565b80356001600160a01b03811681146117bf57600080fd5b919050565b600082601f8301126117d557600080fd5b813560206117ea6117e583611c35565b611c04565b80838252828201915082860187848660051b890101111561180a57600080fd5b60005b858110156118305761181e8261183d565b8452928401929084019060010161180d565b5090979650505050505050565b803580151581146117bf57600080fd5b600082601f83011261185e57600080fd5b813567ffffffffffffffff81111561187857611878611dfa565b61188b601f8201601f1916602001611c04565b8181528460208386010111156118a057600080fd5b816020850160208301376000918101602001919091529392505050565b803560ff811681146117bf57600080fd5b6000602082840312156118e057600080fd5b611797826117a8565b6000806000606084860312156118fe57600080fd5b611907846117a8565b92506119156020850161183d565b91506119236040850161183d565b90509250925092565b6000806040838503121561193f57600080fd5b823567ffffffffffffffff8082111561195757600080fd5b818501915085601f83011261196b57600080fd5b8135602061197b6117e583611c35565b8083825282820191508286018a848660051b890101111561199b57600080fd5b600096505b848710156119c5576119b1816117a8565b8352600196909601959183019183016119a0565b50965050860135925050808211156119dc57600080fd5b506119e9858286016117c4565b9150509250929050565b600060208284031215611a0557600080fd5b5035919050565b60008060408385031215611a1f57600080fd5b82359150611a2f602084016117a8565b90509250929050565b60008060408385031215611a4b57600080fd5b82359150602083013567ffffffffffffffff811115611a6957600080fd5b6119e98582860161184d565b600080600060608486031215611a8a57600080fd5b83359250602084013567ffffffffffffffff811115611aa857600080fd5b611ab48682870161184d565b925050611923604085016118bd565b600060208284031215611ad557600080fd5b81356001600160e01b03198116811461179757600080fd5b600060208284031215611aff57600080fd5b611797826118bd565b60008060008060808587031215611b1e57600080fd5b611b27856118bd565b9350611b35602086016118bd565b9250611b43604086016118bd565b9150611b51606086016117a8565b905092959194509250565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611b94816017850160208801611d2c565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351611bc5816028840160208801611d2c565b01602801949350505050565b6020815260008251806020840152611bf0816040850160208701611d2c565b601f01601f19169190910160400192915050565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c2d57611c2d611dfa565b604052919050565b600067ffffffffffffffff821115611c4f57611c4f611dfa565b5060051b60200190565b60008219821115611c6c57611c6c611da2565b500190565b600064ffffffffff808316818516808303821115611c9157611c91611da2565b01949350505050565b600060ff821660ff84168060ff03821115611cb757611cb7611da2565b019392505050565b600082611cce57611cce611db8565b500490565b6000816000190483118215151615611ced57611ced611da2565b500290565b600082821015611d0457611d04611da2565b500390565b600060ff821660ff841680821015611d2357611d23611da2565b90039392505050565b60005b83811015611d47578181015183820152602001611d2f565b83811115611d56576000848401525b50505050565b600081611d6b57611d6b611da2565b506000190190565b6000600019821415611d8757611d87611da2565b5060010190565b600082611d9d57611d9d611db8565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220f9760b135eaaddb7ba8149166dcb4c51f3416673392a0c426438ec72a4163faf64736f6c63430008070033

Block Transaction Gas Used Reward
Age Block Fee Address Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading