Holesky Testnet

Contract

0xEa8213EB7C11bd537e60B2AbbcF298623D807C34

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Nexus

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 10 : Nexus.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {INexusBridge} from "./interfaces/INexusBridge.sol";
import {INodeOperator} from "./interfaces/INodeOperator.sol";
import {Ownable} from "./utils/NexusOwnable.sol";
import {UUPSUpgreadable} from "./utils/UUPSUpgreadable.sol";
import {ISSVNetworkCore} from "./interfaces/ISSVNetwork.sol";
import {INexusInterface} from "./interfaces/INexusInterface.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {BytesArrayLibrary} from "./libraries/BytesArrayLibrary.sol";

/**
 * @title Nexus Core Contract
 * @author RohitAudit
 * @dev This contract is heart and soul of Nexus Network and is used for Operations like
 * 1. Onboarding of rollup to Nexus Network
 * 2. Change parameters for rollup
 * 3. Whitelisting rollup address
 * 4. Submitting keys to rollup bridge
 * 5. Submitting keyshares to SSV contract
 * 6. Recharge funds in SSV contract for validator operation
 * 7. Keep track of validator status and exits
 */
contract Nexus is INexusInterface, Ownable, UUPSUpgreadable {
    using EnumerableSet for EnumerableSet.AddressSet;
    using EnumerableSet for EnumerableSet.UintSet;
    using BytesArrayLibrary for bytes[];
    EnumerableSet.AddressSet private whitelistedRollups;
    address public offChainBot;
    mapping(address => Rollup) public rollups;
    mapping(bytes => ValidatorStatus) public validators;
    mapping(uint256 => uint16) polygonCDKPartners;
    address public NodeOperatorContract;

    // Goerli Address
    // address public constant SSV_NETWORK =
    //     0xC3CD9A0aE89Fff83b71b58b6512D43F8a41f363D;
    // address public constant SSV_TOKEN =
    //     0x3a9f01091C446bdE031E39ea8354647AFef091E7;

    // Holesky Address
    address public constant SSV_NETWORK =
        0x38A4794cCEd47d3baf7370CcC43B560D3a1beEFA;
    address public constant SSV_TOKEN =
        0xad45A78180961079BFaeEe349704F411dfF947C6;
    uint16 private constant BASIS_POINT = 10000;

    modifier onlyOffChainBot() {
        if (msg.sender != offChainBot) revert NotNexusBot();
        _;
    }

    modifier onlyWhitelistedRollup() {
        if (!whitelistedRollups.contains(msg.sender))
            revert AddressNotWhitelisted();
        _;
    }

    modifier nonZeroAddress(address _contract) {
        if (_contract == address(0)) revert IncorrectAddress();
        _;
    }

    function initialize() public initilizeOnce {
        _ownableInit(msg.sender);
    }

    // admin related functions

    function whitelistRollup(
        string calldata name,
        address rollupAddress
    ) external onlyOwner {
        if (whitelistedRollups.add(rollupAddress)) {
            emit RollupWhitelisted(name, rollupAddress);
        } else {
            revert AddressAlreadyWhitelisted();
        }
    }

    function setOffChainBot(
        address _botAddress
    ) external onlyOwner nonZeroAddress(_botAddress) {
        offChainBot = _botAddress;
    }

    function updateProxy(
        address newImplemetation
    ) public onlyOwner nonZeroAddress(newImplemetation) {
        updateCodeAddress(newImplemetation);
    }

    function setNodeOperatorContract(
        address _nodeOperator
    ) external onlyOwner nonZeroAddress(_nodeOperator) {
        NodeOperatorContract = _nodeOperator;
        emit NodeOperatorContractChanged(_nodeOperator);
    }

    function changeExecutionFeeAddress(
        address _execution_fee_address
    ) external onlyOwner nonZeroAddress(_execution_fee_address) {
        ISSVNetworkCore(SSV_NETWORK).setFeeRecipientAddress(
            _execution_fee_address
        );
    }

    // rollup related functions

    function isRollupWhitelisted(
        address rollupAddress
    ) external view returns (bool) {
        return whitelistedRollups.contains(rollupAddress);
    }

    function registerRollup(
        address bridgeContract,
        uint64 operatorCluster,
        uint256 nexusFee,
        uint16 stakingLimit
    ) external onlyWhitelistedRollup {
        if (rollups[msg.sender].bridgeContract != address(0))
            revert RollupAlreadyRegistered();
        if (INexusBridge(bridgeContract).NEXUS_NETWORK() != address(this))
            revert NexusAddressNotFound();
        if (stakingLimit > BASIS_POINT) revert IncorrectStakingLimit();
        INexusBridge(bridgeContract).setNexusFee(nexusFee);
        INodeOperator(NodeOperatorContract).getCluster(operatorCluster);
        rollups[msg.sender] = Rollup(
            bridgeContract,
            stakingLimit,
            operatorCluster
        );
        emit RollupRegistered(
            msg.sender,
            bridgeContract,
            stakingLimit,
            operatorCluster,
            nexusFee
        );
    }

    function changeStakingLimit(
        uint16 newStakingLimit
    ) external onlyWhitelistedRollup {
        if (newStakingLimit > BASIS_POINT) revert IncorrectStakingLimit();
        rollups[msg.sender].stakingLimit = newStakingLimit;
        emit StakingLimitChanged(msg.sender, newStakingLimit);
    }

    function changeNexusFee(uint256 _new_fee) external onlyWhitelistedRollup {
        INexusBridge(rollups[msg.sender].bridgeContract).setNexusFee(_new_fee);
        emit NexusFeeChanged(msg.sender, _new_fee);
    }

    function changeCluster(
        uint64 operatorCluster
    ) external onlyWhitelistedRollup {
        INodeOperator(NodeOperatorContract).getCluster(operatorCluster);
        rollups[msg.sender].operatorCluster = operatorCluster;
        emit RollupOperatorClusterChanged(msg.sender, operatorCluster);
    }

    // validator realted function

    function depositValidatorRollup(
        address _rollupAdmin,
        Validator[] calldata _validators
    ) external override onlyOffChainBot {
        for (uint i = 0; i < _validators.length; i++) {
            if (validators[_validators[i].pubKey] != ValidatorStatus.INACTIVE)
                revert IncorrectValidatorStatus();
            validators[_validators[i].pubKey] = ValidatorStatus.DEPOSITED;
            emit ValidatorSubmitted(_validators[i].pubKey, _rollupAdmin);
        }
        INexusBridge(rollups[_rollupAdmin].bridgeContract)
            .depositValidatorNexus(
                _validators,
                uint256(rollups[_rollupAdmin].stakingLimit)
            );
    }

    function depositValidatorShares(
        address _rollupAdmin,
        ValidatorShares calldata _validatorShare
    ) external override onlyOffChainBot {
        if (validators[_validatorShare.pubKey] != ValidatorStatus.DEPOSITED)
            revert IncorrectValidatorStatus();
        IERC20(SSV_TOKEN).approve(SSV_NETWORK, _validatorShare.amount);
        ISSVNetworkCore(SSV_NETWORK).registerValidator(
            _validatorShare.pubKey,
            _validatorShare.operatorIds,
            _validatorShare.sharesEncrypted,
            _validatorShare.amount,
            _validatorShare.cluster
        );
        validators[_validatorShare.pubKey] = ValidatorStatus.SHARE_DEPOSITED;
        emit ValidatorShareSubmitted(
            _validatorShare.pubKey,
            _rollupAdmin,
            _validatorShare.amount
        );
    }

    function validatorExit(
        address rollupAdmin,
        bytes calldata pubkey,
        uint64[] calldata operatorIds
    ) external onlyOffChainBot {
        if (validators[pubkey] != ValidatorStatus.SHARE_DEPOSITED) revert IncorrectValidatorStatus();
        ISSVNetworkCore(SSV_NETWORK).exitValidator(pubkey, operatorIds);
        validators[pubkey] = ValidatorStatus.VALIDATOR_EXIT_SUBMITTED;
        emit ValidatorExitSubmitted(rollupAdmin, pubkey);
    }

    function validatorExitBalanceTransferred(
        address rollupAdmin,
        bytes calldata pubkey,
        uint64[] memory operatorIds,
        ISSVNetworkCore.Cluster memory cluster
    ) external onlyOffChainBot {
        if (validators[pubkey] != ValidatorStatus.VALIDATOR_EXIT_SUBMITTED)
            revert IncorrectValidatorStatus();
        ISSVNetworkCore(SSV_NETWORK).removeValidator(
            pubkey,
            operatorIds,
            cluster
        );
        INexusBridge(rollups[rollupAdmin].bridgeContract)
            .updateExitedValidators();
        validators[pubkey] = ValidatorStatus.VALIDATOR_EXITED;
        emit ValidatorExited(rollupAdmin, pubkey);
    }

    function validatorSlashed(
        address rollupAdmin,
        uint256 amountSlashed
    ) external onlyOffChainBot {
        INexusBridge(rollups[rollupAdmin].bridgeContract).validatorsSlashed(
            amountSlashed
        );
        emit RollupValidatorSlashed(rollupAdmin, amountSlashed);
    }

    // cluster related functions

    function rechargeCluster(
        uint64 clusterId,
        uint256 amount,
        ISSVNetworkCore.Cluster memory cluster
    ) external onlyOffChainBot {
        ISSVNetworkCore(SSV_NETWORK).deposit(
            address(this),
            INodeOperator(NodeOperatorContract).getCluster(clusterId),
            amount,
            cluster
        );
        emit ClusterRecharged(clusterId, amount);
    }
}

File 2 of 10 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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 10 : EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastValue;
                // Update the index for the moved value
                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

File 4 of 10 : INexusBridge.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {INexusInterface} from "./INexusInterface.sol";

interface INexusBridge {
    function setNexusFee(uint256 _nexus_fee) external;
    function NEXUS_NETWORK() external view returns (address);
    function validatorCount() external view returns (uint256);
    function NexusFeePercentage() external view returns(uint256);
    function balance() external view returns(uint256);
    function validatorsSlashed(uint256 amount) external;
    function updateExitedValidators() external;
    function depositValidatorNexus(INexusInterface.Validator[] calldata _validators,uint256 stakingLimit) external;
}

File 5 of 10 : INexusInterface.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {ISSVNetworkCore} from "./ISSVNetwork.sol";

interface INexusInterface {
    // structs to be used for nexus interface
    // todo: add multiple operator cluster mapping so that rollup can select cluster and percentage per cluster
    struct Rollup {
        address bridgeContract;
        uint16 stakingLimit;
        uint64 operatorCluster;
    }
    struct Validator {
        bytes pubKey;
        bytes withdrawalAddress;
        bytes signature;
        bytes32 depositRoot;
    }
    struct ValidatorShares {
        bytes pubKey;
        uint64[] operatorIds;
        bytes sharesEncrypted;
        uint256 amount;
        ISSVNetworkCore.Cluster cluster;
    }

    enum ValidatorStatus{
        INACTIVE,
        DEPOSITED,
        SHARE_DEPOSITED,
        VALIDATOR_EXIT_SUBMITTED,
        VALIDATOR_EXITED
    }

    // errors
    error NotNexusBot();
    error AddressAlreadyWhitelisted();
    error AddressNotWhitelisted();
    error RollupAlreadyPresent();
    error RollupAlreadyRegistered();
    error KeyNotDeposited();
    error NexusAddressNotFound();
    error InvalidKeySupplied();
    error ClusterAlreadyExited();
    error IncorrectStakingLimit();
    error IncorrectValidatorStatus();

    // events
    event RollupWhitelisted(string name, address rollupAddress);
    event RollupRegistered(address rollupAdmin, address withdrawalAddress,uint16 stakingLimit,uint64 operatorCluster,uint256 nexusFee);
    event StakingLimitChanged(address rollupAdmin,uint16 StakingLimit);
    event RollupOperatorClusterChanged(address rollup_admin,uint64 operatorCluster);
    event NexusFeeChanged(address rollup_admin,uint256 newFee);
    event ValidatorSubmitted(bytes pubKey, address rolupAdmin);
    event ValidatorShareSubmitted(bytes pubKey, address rolupAdmin,uint256 amount);
    event ClusterAdded(uint64 clusterId, uint64[] operatorIds);
    event SSVRecharged(address sender, uint256 amount);
    event ClusterRecharged(uint64 clusterId,uint256 amount);
    event RollupValidatorSlashed(address admin,uint256 amount);
    event ValidatorExitSubmitted(address admin,bytes pubKey);
    event ValidatorExited(address admin,bytes pubKey);
    event NodeOperatorContractChanged(address _nodeOperatorContract);

    // functions
    function depositValidatorRollup(
        address _rollupAdmin,
        Validator[] calldata _validators
    ) external;

    function depositValidatorShares(
        address _rollupAdmin,
        ValidatorShares calldata _validatorShare
    ) external;
}

File 6 of 10 : INodeOperator.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
interface INodeOperator {

    error ClusterAlreadyExited();
    error OperatorNotRegistered();
    error OperatorAlreadyRegistered();
    error ClusterNotPresent();
    event ClusterAdded(uint64 clusterId, uint64[] operatorIds);
    event SSVOperatorRegistered(string name,uint256 indexed operatorId, string pubKey, string ip_address);
    event SSVOperatorUpdated(uint64 _operator_id,string _ip_address);

    function getCluster(uint64 clusterId) external view returns(uint64[] memory);
}

File 7 of 10 : ISSVNetwork.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

interface ISSVNetworkCore {
    /// @notice Represents a cluster of validators
    struct Cluster {
        /// @dev The number of validators in the cluster
        uint32 validatorCount;
        /// @dev The index of network fees related to this cluster
        uint64 networkFeeIndex;
        /// @dev The last index calculated for the cluster
        uint64 index;
        /// @dev Flag indicating whether the cluster is active
        bool active;
        /// @dev The balance of the cluster
        uint256 balance;
    }

    /********************************/
    /* Validator External Functions */
    /********************************/

    function registerValidator(
        bytes calldata publicKey,
        uint64[] memory operatorIds,
        bytes calldata sharesEncrypted,
        uint256 amount,
        Cluster memory cluster
    ) external;

    function exitValidator(bytes calldata publicKey, uint64[] calldata operatorIds) external;

    function removeValidator(
        bytes calldata publicKey,
        uint64[] memory operatorIds,
        Cluster memory cluster
    ) external;

    function deposit(
        address clusterOwner,
        uint64[] calldata operatorIds,
        uint256 amount,
        ISSVNetworkCore.Cluster memory cluster
    ) external;

    function setFeeRecipientAddress(address feeRecipientAddress) external;

}

File 8 of 10 : BytesArrayLibrary.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

/**
 * @title BytesArray Library
 * @author RohitAudit
 * @dev This library is used for managing bytes array by providing following functionality:
 * 1. Removing element from the array
 * 2. Adding element to the array
 */
library BytesArrayLibrary {
    function addElement(bytes[] storage arr, bytes memory data) internal {
        arr.push(data);
    }

    function findElement(
        bytes[] storage arr,
        bytes memory target
    ) internal view returns (bool found, uint256 index) {
        for (uint256 i = 0; i < arr.length; i++) {
            if (keccak256(arr[i]) == keccak256(target)) {
                return (true, i);
            }
        }
        return (false, 0);
    }

    function removeElement(bytes[] storage arr, bytes memory target) internal {
        for (uint256 i = 0; i < arr.length; i++) {
            if (keccak256(arr[i]) == keccak256(target)) {
                if (i < arr.length - 1) {
                    arr[i] = arr[arr.length - 1];
                }
                arr.pop();
                return;
            }
        }
    }
}

File 9 of 10 : NexusOwnable.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

/**
 * @title Ownable Contract
 * @author RohitAudit
 * @dev This contract is used to implement ownable features to the contracts
 */
contract Ownable {
    address private owner;
    bool private initialized = false;

    event OwnerChanged(address oldOwner, address newOwner);
    error NotOwner();
    error ContractAlreadyInitialized();
    error IncorrectAddress();
    modifier onlyOwner() {
        if (msg.sender != owner) revert NotOwner();
        _;
    }

    modifier initilizeOnce() {
        if (initialized) revert ContractAlreadyInitialized();
        _;
    }

    function getOwner() external view returns (address) {
        return owner;
    }

    function _ownableInit(address _owner) internal {
        owner = _owner;
        initialized = true;
    }

    /**
     * This function transfers the ownership of the contract
     * @param newOwner New Owner of the contract
     */
    function transferOwnership(address newOwner) external onlyOwner{
        if (newOwner == address(0)) revert IncorrectAddress();

        emit OwnerChanged(owner, newOwner);
        owner = newOwner;
    }
}

File 10 of 10 : UUPSUpgreadable.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

/**
 * @title Proxiable
 * @author RohitAudit
 * @dev This contract is implemented in the implementation contract to make it upgreadable. Removing this contract
 * will remove the upgreadability feature of the contract
 */
contract UUPSUpgreadable {
    // Code position in storage is keccak256("PROXIABLE") = "0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7"
    bytes32 constant IMPLEMENTATION_SLOT = 0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7;
    error NotCompatible();
    function updateCodeAddress(address newAddress) internal {
        if(bytes32(IMPLEMENTATION_SLOT) != UUPSUpgreadable(newAddress).proxiableUUID()) revert NotCompatible();
        assembly { // solium-disable-line
            sstore(IMPLEMENTATION_SLOT, newAddress)
        }
    }
    function proxiableUUID() public pure returns (bytes32) {
        return IMPLEMENTATION_SLOT;
    }
}

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

Contract ABI

[{"inputs":[],"name":"AddressAlreadyWhitelisted","type":"error"},{"inputs":[],"name":"AddressNotWhitelisted","type":"error"},{"inputs":[],"name":"ClusterAlreadyExited","type":"error"},{"inputs":[],"name":"ContractAlreadyInitialized","type":"error"},{"inputs":[],"name":"IncorrectAddress","type":"error"},{"inputs":[],"name":"IncorrectStakingLimit","type":"error"},{"inputs":[],"name":"IncorrectValidatorStatus","type":"error"},{"inputs":[],"name":"InvalidKeySupplied","type":"error"},{"inputs":[],"name":"KeyNotDeposited","type":"error"},{"inputs":[],"name":"NexusAddressNotFound","type":"error"},{"inputs":[],"name":"NotCompatible","type":"error"},{"inputs":[],"name":"NotNexusBot","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"RollupAlreadyPresent","type":"error"},{"inputs":[],"name":"RollupAlreadyRegistered","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"clusterId","type":"uint64"},{"indexed":false,"internalType":"uint64[]","name":"operatorIds","type":"uint64[]"}],"name":"ClusterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"clusterId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClusterRecharged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"rollup_admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"NexusFeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_nodeOperatorContract","type":"address"}],"name":"NodeOperatorContractChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"rollup_admin","type":"address"},{"indexed":false,"internalType":"uint64","name":"operatorCluster","type":"uint64"}],"name":"RollupOperatorClusterChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"rollupAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"withdrawalAddress","type":"address"},{"indexed":false,"internalType":"uint16","name":"stakingLimit","type":"uint16"},{"indexed":false,"internalType":"uint64","name":"operatorCluster","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"nexusFee","type":"uint256"}],"name":"RollupRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RollupValidatorSlashed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"address","name":"rollupAddress","type":"address"}],"name":"RollupWhitelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SSVRecharged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"rollupAdmin","type":"address"},{"indexed":false,"internalType":"uint16","name":"StakingLimit","type":"uint16"}],"name":"StakingLimitChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"pubKey","type":"bytes"}],"name":"ValidatorExitSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"pubKey","type":"bytes"}],"name":"ValidatorExited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"pubKey","type":"bytes"},{"indexed":false,"internalType":"address","name":"rolupAdmin","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ValidatorShareSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"pubKey","type":"bytes"},{"indexed":false,"internalType":"address","name":"rolupAdmin","type":"address"}],"name":"ValidatorSubmitted","type":"event"},{"inputs":[],"name":"NodeOperatorContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SSV_NETWORK","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SSV_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"operatorCluster","type":"uint64"}],"name":"changeCluster","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_execution_fee_address","type":"address"}],"name":"changeExecutionFeeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_new_fee","type":"uint256"}],"name":"changeNexusFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"newStakingLimit","type":"uint16"}],"name":"changeStakingLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rollupAdmin","type":"address"},{"components":[{"internalType":"bytes","name":"pubKey","type":"bytes"},{"internalType":"bytes","name":"withdrawalAddress","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"depositRoot","type":"bytes32"}],"internalType":"struct INexusInterface.Validator[]","name":"_validators","type":"tuple[]"}],"name":"depositValidatorRollup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rollupAdmin","type":"address"},{"components":[{"internalType":"bytes","name":"pubKey","type":"bytes"},{"internalType":"uint64[]","name":"operatorIds","type":"uint64[]"},{"internalType":"bytes","name":"sharesEncrypted","type":"bytes"},{"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"uint32","name":"validatorCount","type":"uint32"},{"internalType":"uint64","name":"networkFeeIndex","type":"uint64"},{"internalType":"uint64","name":"index","type":"uint64"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint256","name":"balance","type":"uint256"}],"internalType":"struct ISSVNetworkCore.Cluster","name":"cluster","type":"tuple"}],"internalType":"struct INexusInterface.ValidatorShares","name":"_validatorShare","type":"tuple"}],"name":"depositValidatorShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rollupAddress","type":"address"}],"name":"isRollupWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"offChainBot","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint64","name":"clusterId","type":"uint64"},{"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"uint32","name":"validatorCount","type":"uint32"},{"internalType":"uint64","name":"networkFeeIndex","type":"uint64"},{"internalType":"uint64","name":"index","type":"uint64"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint256","name":"balance","type":"uint256"}],"internalType":"struct ISSVNetworkCore.Cluster","name":"cluster","type":"tuple"}],"name":"rechargeCluster","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bridgeContract","type":"address"},{"internalType":"uint64","name":"operatorCluster","type":"uint64"},{"internalType":"uint256","name":"nexusFee","type":"uint256"},{"internalType":"uint16","name":"stakingLimit","type":"uint16"}],"name":"registerRollup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rollups","outputs":[{"internalType":"address","name":"bridgeContract","type":"address"},{"internalType":"uint16","name":"stakingLimit","type":"uint16"},{"internalType":"uint64","name":"operatorCluster","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeOperator","type":"address"}],"name":"setNodeOperatorContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_botAddress","type":"address"}],"name":"setOffChainBot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplemetation","type":"address"}],"name":"updateProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rollupAdmin","type":"address"},{"internalType":"bytes","name":"pubkey","type":"bytes"},{"internalType":"uint64[]","name":"operatorIds","type":"uint64[]"}],"name":"validatorExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rollupAdmin","type":"address"},{"internalType":"bytes","name":"pubkey","type":"bytes"},{"internalType":"uint64[]","name":"operatorIds","type":"uint64[]"},{"components":[{"internalType":"uint32","name":"validatorCount","type":"uint32"},{"internalType":"uint64","name":"networkFeeIndex","type":"uint64"},{"internalType":"uint64","name":"index","type":"uint64"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint256","name":"balance","type":"uint256"}],"internalType":"struct ISSVNetworkCore.Cluster","name":"cluster","type":"tuple"}],"name":"validatorExitBalanceTransferred","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rollupAdmin","type":"address"},{"internalType":"uint256","name":"amountSlashed","type":"uint256"}],"name":"validatorSlashed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"validators","outputs":[{"internalType":"enum INexusInterface.ValidatorStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"rollupAddress","type":"address"}],"name":"whitelistRollup","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526000805460ff60a01b1916905534801561001d57600080fd5b5061253e8061002d6000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80638129fc1c116100de5780639e95514911610097578063e03ad13c11610071578063e03ad13c1461039a578063e2f4a731146103ad578063eff00f9d146103d0578063f2fde38b1461044857600080fd5b80639e95514914610361578063c37a78dc14610374578063c40e9df91461038757600080fd5b80638129fc1c146102f457806384eff0fa146102fc578063893d20e81461030f5780639164975114610320578063946cd73f1461033b5780639b17541c1461034e57600080fd5b80633d4d837f1161014b578063614080a111610125578063614080a114610280578063687abf7d146102935780636c36511a146102a65780636f2a626f146102e157600080fd5b80633d4d837f1461022c5780634fde79ad1461023f57806352d1902d1461025257600080fd5b80630df1ecfd14610193578063139b0f75146101cb5780631621eecb146101e05780633011ad9b146101f357806334439c8014610206578063383bf14214610219575b600080fd5b6101ae73ad45a78180961079bfaeee349704f411dff947c681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101de6101d93660046119e1565b61045b565b005b6101de6101ee366004611a32565b6105b7565b6101de610201366004611aaa565b61066f565b6101de610214366004611b23565b6106f6565b6101de610227366004611c15565b6108d1565b6101de61023a366004611c6c565b610b24565b6101de61024d366004611cbd565b610df1565b6040517fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf781526020016101c2565b6003546101ae906001600160a01b031681565b6101de6102a1366004611cda565b610f00565b6102d46102b4366004611cf7565b805160208183018101805160058252928201919093012091525460ff1681565b6040516101c29190611da1565b6101de6102ef366004611dc9565b610fa1565b6101de61107a565b6007546101ae906001600160a01b031681565b6000546001600160a01b03166101ae565b6101ae7338a4794cced47d3baf7370ccc43b560d3a1beefa81565b6101de610349366004611df5565b6110c1565b6101de61035c366004611e52565b61118d565b6101de61036f366004611cda565b6113b2565b6101de610382366004611cda565b611412565b6101de610395366004611cda565b6114d6565b6101de6103a8366004611ea6565b61154c565b6103c06103bb366004611cda565b6116b1565b60405190151581526020016101c2565b6104176103de366004611cda565b6004602052600090815260409020546001600160a01b03811690600160a01b810461ffff1690600160b01b90046001600160401b031683565b604080516001600160a01b03909416845261ffff90921660208401526001600160401b0316908201526060016101c2565b6101de610456366004611cda565b6116c4565b6003546001600160a01b031633146104865760405163375152c160e01b815260040160405180910390fd5b60075460405163e596614f60e01b81526001600160401b03851660048201527338a4794cced47d3baf7370ccc43b560d3a1beefa9163bc26e7e59130916001600160a01b03169063e596614f90602401600060405180830381865afa1580156104f3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261051b9190810190611f28565b85856040518563ffffffff1660e01b815260040161053c949392919061204c565b600060405180830381600087803b15801561055657600080fd5b505af115801561056a573d6000803e3d6000fd5b5050604080516001600160401b0387168152602081018690527f50c39e9703d590409e39722da8c2ce8bfe34dded154bddaa043935c2409c80cc93500190505b60405180910390a1505050565b6105c260013361177f565b6105df5760405163ad7acb4760e01b815260040160405180910390fd5b61271061ffff821611156106065760405163013c3ba760e41b815260040160405180910390fd5b33600081815260046020908152604091829020805461ffff60a01b1916600160a01b61ffff8716908102919091179091558251938452908301527f027aba72ce53b1cf4098eff40bd649811ea216a5829fe29081fb013ae6a1b96f91015b60405180910390a150565b6000546001600160a01b0316331461069a576040516330cd747160e01b815260040160405180910390fd5b6106a56001826117a4565b156106dd577fcac241f16294cde789c1efe865bbb26d0a5d55fbf2b5b696fdb304c65f231d648383836040516105aa939291906120b9565b604051630f084ddf60e31b815260040160405180910390fd5b6003546001600160a01b031633146107215760405163375152c160e01b815260040160405180910390fd5b6003600585856040516107359291906120e5565b9081526040519081900360200190205460ff16600481111561075957610759611d8b565b14610777576040516365c4b31760e11b815260040160405180910390fd5b6040516312b3fc1960e01b81527338a4794cced47d3baf7370ccc43b560d3a1beefa906312b3fc19906107b49087908790879087906004016120f5565b600060405180830381600087803b1580156107ce57600080fd5b505af11580156107e2573d6000803e3d6000fd5b505050506001600160a01b038581166000908152600460208190526040808320548151631e5c085b60e31b8152915194169363f2e042d89382840193909282900301818387803b15801561083557600080fd5b505af1158015610849573d6000803e3d6000fd5b505050506004600585856040516108619291906120e5565b908152604051908190036020019020805460ff1916600183600481111561088a5761088a611d8b565b02179055507fcc8a7c9c5bd7463d45f32c9ffe39af44dc854cb4b8dc0329d1c3bdeb1031e0148585856040516108c29392919061212b565b60405180910390a15050505050565b6003546001600160a01b031633146108fc5760405163375152c160e01b815260040160405180910390fd5b6001600561090a8380612150565b6040516109189291906120e5565b9081526040519081900360200190205460ff16600481111561093c5761093c611d8b565b1461095a576040516365c4b31760e11b815260040160405180910390fd5b60405163095ea7b360e01b81527338a4794cced47d3baf7370ccc43b560d3a1beefa60048201526060820135602482015273ad45a78180961079bfaeee349704f411dff947c69063095ea7b3906044016020604051808303816000875af11580156109c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ed9190612196565b507338a4794cced47d3baf7370ccc43b560d3a1beefa6306e8fb9c610a128380612150565b610a1f60208601866121b3565b610a2c6040880188612150565b8860600135896080016040518963ffffffff1660e01b8152600401610a5898979695949392919061223a565b600060405180830381600087803b158015610a7257600080fd5b505af1158015610a86573d6000803e3d6000fd5b506002925060059150610a9b90508380612150565b604051610aa99291906120e5565b908152604051908190036020019020805460ff19166001836004811115610ad257610ad2611d8b565b02179055507f171bb1de68bd2c93b96f9f3f89ca7fd4a762f9459270bf93a55307be183f93f0610b028280612150565b848460600135604051610b1894939291906122f7565b60405180910390a15050565b610b2f60013361177f565b610b4c5760405163ad7acb4760e01b815260040160405180910390fd5b336000908152600460205260409020546001600160a01b031615610b83576040516312f8923160e31b815260040160405180910390fd5b306001600160a01b0316846001600160a01b031663c06546006040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bef9190612327565b6001600160a01b031614610c165760405163a714776d60e01b815260040160405180910390fd5b61271061ffff82161115610c3d5760405163013c3ba760e41b815260040160405180910390fd5b60405163142d3a2760e21b8152600481018390526001600160a01b038516906350b4e89c90602401600060405180830381600087803b158015610c7f57600080fd5b505af1158015610c93573d6000803e3d6000fd5b505060075460405163e596614f60e01b81526001600160401b03871660048201526001600160a01b03909116925063e596614f9150602401600060405180830381865afa158015610ce8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d109190810190611f28565b5060408051606080820183526001600160a01b0387811680845261ffff86811660208087018281526001600160401b038c8116898b01818152336000818152600487528d90209b518c5495519251909416600160b01b0267ffffffffffffffff60b01b1992909816600160a01b026001600160b01b0319909516939099169290921792909217169390931790965586519384529483019190915293810192909252810191909152608081018390527fb2098e6993da52c711ce658efb7338e41bcf578da2e4766a301bb62db47e33949060a00160405180910390a150505050565b610dfc60013361177f565b610e195760405163ad7acb4760e01b815260040160405180910390fd5b60075460405163e596614f60e01b81526001600160401b03831660048201526001600160a01b039091169063e596614f90602401600060405180830381865afa158015610e6a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e929190810190611f28565b5033600081815260046020908152604091829020805467ffffffffffffffff60b01b1916600160b01b6001600160401b038716908102919091179091558251938452908301527f6b15499268e2722b1ec653445be16693c8460e390b5f9c4dae011c081ee824459101610664565b6000546001600160a01b03163314610f2b576040516330cd747160e01b815260040160405180910390fd5b806001600160a01b038116610f53576040516376cb291d60e11b815260040160405180910390fd5b600780546001600160a01b0319166001600160a01b0384169081179091556040519081527f141084bbe0b806ca3d4c9dfa41d4987df8ed29c7f2ae20d4a017e87d955fb7ed90602001610b18565b6003546001600160a01b03163314610fcc5760405163375152c160e01b815260040160405180910390fd5b6001600160a01b0382811660009081526004602081905260409182902054915163043d014d60e41b81529081018490529116906343d014d090602401600060405180830381600087803b15801561102257600080fd5b505af1158015611036573d6000803e3d6000fd5b5050604080516001600160a01b0386168152602081018590527f7b3f28e29d512f36e608771705975ad5c436cf19d368573a1657c24e0db8b1209350019050610b18565b600054600160a01b900460ff16156110a557604051631ee1e30360e21b815260040160405180910390fd5b60008054600160a01b6001600160a81b03199091163317179055565b6110cc60013361177f565b6110e95760405163ad7acb4760e01b815260040160405180910390fd5b3360009081526004602081905260409182902054915163142d3a2760e21b81529081018390526001600160a01b03909116906350b4e89c90602401600060405180830381600087803b15801561113e57600080fd5b505af1158015611152573d6000803e3d6000fd5b505060408051338152602081018590527f61020a83dba6b08612f9c1dbe9e636c781693c44b062f0f4ab3307f11340b02a9350019050610664565b6003546001600160a01b031633146111b85760405163375152c160e01b815260040160405180910390fd5b60005b8181101561132c57600060058484848181106111d9576111d9612344565b90506020028101906111eb919061235a565b6111f59080612150565b6040516112039291906120e5565b9081526040519081900360200190205460ff16600481111561122757611227611d8b565b14611245576040516365c4b31760e11b815260040160405180910390fd5b6001600584848481811061125b5761125b612344565b905060200281019061126d919061235a565b6112779080612150565b6040516112859291906120e5565b908152604051908190036020019020805460ff191660018360048111156112ae576112ae611d8b565b02179055507fb7abbfc20ad848177398301a969cb076026b7c4a15b063eda34013ad984587c38383838181106112e6576112e6612344565b90506020028101906112f8919061235a565b6113029080612150565b86604051611312939291906120b9565b60405180910390a1806113248161237a565b9150506111bb565b506001600160a01b0383811660009081526004602081905260409182902054915163303f5e4160e11b81529282169263607ebc829261137b9287928792600160a01b900461ffff1691016123e6565b600060405180830381600087803b15801561139557600080fd5b505af11580156113a9573d6000803e3d6000fd5b50505050505050565b6000546001600160a01b031633146113dd576040516330cd747160e01b815260040160405180910390fd5b806001600160a01b038116611405576040516376cb291d60e11b815260040160405180910390fd5b61140e826117b9565b5050565b6000546001600160a01b0316331461143d576040516330cd747160e01b815260040160405180910390fd5b806001600160a01b038116611465576040516376cb291d60e11b815260040160405180910390fd5b6040516336f370b360e21b81526001600160a01b03831660048201527338a4794cced47d3baf7370ccc43b560d3a1beefa9063dbcdc2cc90602401600060405180830381600087803b1580156114ba57600080fd5b505af11580156114ce573d6000803e3d6000fd5b505050505050565b6000546001600160a01b03163314611501576040516330cd747160e01b815260040160405180910390fd5b806001600160a01b038116611529576040516376cb291d60e11b815260040160405180910390fd5b50600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146115775760405163375152c160e01b815260040160405180910390fd5b60026005858560405161158b9291906120e5565b9081526040519081900360200190205460ff1660048111156115af576115af611d8b565b146115cd576040516365c4b31760e11b815260040160405180910390fd5b604051633877322b60e01b81527338a4794cced47d3baf7370ccc43b560d3a1beefa90633877322b9061160a9087908790879087906004016124c8565b600060405180830381600087803b15801561162457600080fd5b505af1158015611638573d6000803e3d6000fd5b505050506003600585856040516116509291906120e5565b908152604051908190036020019020805460ff1916600183600481111561167957611679611d8b565b02179055507f214fff527fb78557a10a93b77e999e02035639169dd2ac2c14c3c9b19f4913d38585856040516108c29392919061212b565b60006116be60018361177f565b92915050565b6000546001600160a01b031633146116ef576040516330cd747160e01b815260040160405180910390fd5b6001600160a01b038116611716576040516376cb291d60e11b815260040160405180910390fd5b600054604080516001600160a01b03928316815291831660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b600061179d836001600160a01b03841661187e565b806001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181b91906124ef565b7fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf71461185a5760405163f030d0ad60e01b815260040160405180910390fd5b7fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf755565b60008181526001830160205260408120546118c5575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556116be565b5060006116be565b6001600160401b03811681146118e257600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611923576119236118e5565b604052919050565b803563ffffffff8116811461193f57600080fd5b919050565b80151581146118e257600080fd5b600060a0828403121561196457600080fd5b60405160a081018181106001600160401b0382111715611986576119866118e5565b6040529050806119958361192b565b815260208301356119a5816118cd565b602082015260408301356119b8816118cd565b604082015260608301356119cb81611944565b6060820152608092830135920191909152919050565b600080600060e084860312156119f657600080fd5b8335611a01816118cd565b925060208401359150611a178560408601611952565b90509250925092565b803561ffff8116811461193f57600080fd5b600060208284031215611a4457600080fd5b61179d82611a20565b60008083601f840112611a5f57600080fd5b5081356001600160401b03811115611a7657600080fd5b602083019150836020828501011115611a8e57600080fd5b9250929050565b6001600160a01b03811681146118e257600080fd5b600080600060408486031215611abf57600080fd5b83356001600160401b03811115611ad557600080fd5b611ae186828701611a4d565b9094509250506020840135611af581611a95565b809150509250925092565b60006001600160401b03821115611b1957611b196118e5565b5060051b60200190565b60008060008060006101008688031215611b3c57600080fd5b8535611b4781611a95565b94506020868101356001600160401b0380821115611b6457600080fd5b611b708a838b01611a4d565b90975095506040890135915080821115611b8957600080fd5b508701601f81018913611b9b57600080fd5b8035611bae611ba982611b00565b6118fb565b81815260059190911b8201830190838101908b831115611bcd57600080fd5b928401925b82841015611bf4578335611be5816118cd565b82529284019290840190611bd2565b8096505050505050611c098760608801611952565b90509295509295909350565b60008060408385031215611c2857600080fd5b8235611c3381611a95565b915060208301356001600160401b03811115611c4e57600080fd5b83016101208186031215611c6157600080fd5b809150509250929050565b60008060008060808587031215611c8257600080fd5b8435611c8d81611a95565b93506020850135611c9d816118cd565b925060408501359150611cb260608601611a20565b905092959194509250565b600060208284031215611ccf57600080fd5b813561179d816118cd565b600060208284031215611cec57600080fd5b813561179d81611a95565b60006020808385031215611d0a57600080fd5b82356001600160401b0380821115611d2157600080fd5b818501915085601f830112611d3557600080fd5b813581811115611d4757611d476118e5565b611d59601f8201601f191685016118fb565b91508082528684828501011115611d6f57600080fd5b8084840185840137600090820190930192909252509392505050565b634e487b7160e01b600052602160045260246000fd5b6020810160058310611dc357634e487b7160e01b600052602160045260246000fd5b91905290565b60008060408385031215611ddc57600080fd5b8235611de781611a95565b946020939093013593505050565b600060208284031215611e0757600080fd5b5035919050565b60008083601f840112611e2057600080fd5b5081356001600160401b03811115611e3757600080fd5b6020830191508360208260051b8501011115611a8e57600080fd5b600080600060408486031215611e6757600080fd5b8335611e7281611a95565b925060208401356001600160401b03811115611e8d57600080fd5b611e9986828701611e0e565b9497909650939450505050565b600080600080600060608688031215611ebe57600080fd5b8535611ec981611a95565b945060208601356001600160401b0380821115611ee557600080fd5b611ef189838a01611a4d565b90965094506040880135915080821115611f0a57600080fd5b50611f1788828901611e0e565b969995985093965092949392505050565b60006020808385031215611f3b57600080fd5b82516001600160401b03811115611f5157600080fd5b8301601f81018513611f6257600080fd5b8051611f70611ba982611b00565b81815260059190911b82018301908381019087831115611f8f57600080fd5b928401925b82841015611fb6578351611fa7816118cd565b82529284019290840190611f94565b979650505050505050565b600081518084526020808501945080840160005b83811015611ffa5781516001600160401b031687529582019590820190600101611fd5565b509495945050505050565b63ffffffff815116825260208101516001600160401b0380821660208501528060408401511660408501525050606081015115156060830152608081015160808301525050565b6001600160a01b03851681526101006020820181905260009061207183820187611fc1565b9150508360408301526120876060830184612005565b95945050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6040815260006120cd604083018587612090565b905060018060a01b0383166020830152949350505050565b8183823760009101908152919050565b60e08152600061210960e083018688612090565b828103602084015261211b8186611fc1565b9150506120876040830184612005565b6001600160a01b03841681526040602082018190526000906120879083018486612090565b6000808335601e1984360301811261216757600080fd5b8301803591506001600160401b0382111561218157600080fd5b602001915036819003821315611a8e57600080fd5b6000602082840312156121a857600080fd5b815161179d81611944565b6000808335601e198436030181126121ca57600080fd5b8301803591506001600160401b038211156121e457600080fd5b6020019150600581901b3603821315611a8e57600080fd5b8183526000602080850194508260005b85811015611ffa57813561221f816118cd565b6001600160401b03168752958201959082019060010161220c565b600061012080835261224f8184018b8d612090565b9050828103602084015261226481898b6121fc565b90508281036040840152612279818789612090565b91505083606083015263ffffffff6122908461192b565b16608083015260208301356122a4816118cd565b6001600160401b0390811660a08401526040840135906122c3826118cd565b1660c083015260608301356122d781611944565b151560e08301526080929092013561010090910152979650505050505050565b60608152600061230b606083018688612090565b6001600160a01b03949094166020830152506040015292915050565b60006020828403121561233957600080fd5b815161179d81611a95565b634e487b7160e01b600052603260045260246000fd5b60008235607e1983360301811261237057600080fd5b9190910192915050565b60006001820161239a57634e487b7160e01b600052601160045260246000fd5b5060010190565b6000808335601e198436030181126123b857600080fd5b83016020810192503590506001600160401b038111156123d757600080fd5b803603821315611a8e57600080fd5b60408082528181018490526000906060808401600587901b850182018885805b8a8110156124b057888403605f190185528235368d9003607e1901811261242b578283fd5b8c01608061243982806123a1565b8288526124498389018284612090565b92505050602061245b818401846123a1565b888403838a015261246d848284612090565b9350505061247d8a8401846123a1565b8884038c8a015261248f848284612090565b948b0135988b01989098525096870196919550509290920191600101612406565b50505080945050505050826020830152949350505050565b6040815260006124dc604083018688612090565b8281036020840152611fb68185876121fc565b60006020828403121561250157600080fd5b505191905056fea26469706673582212208f183f710082f405be0e45237f9db401e444338f1b9bdbd50bc1bce45401598564736f6c63430008130033

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061018e5760003560e01c80638129fc1c116100de5780639e95514911610097578063e03ad13c11610071578063e03ad13c1461039a578063e2f4a731146103ad578063eff00f9d146103d0578063f2fde38b1461044857600080fd5b80639e95514914610361578063c37a78dc14610374578063c40e9df91461038757600080fd5b80638129fc1c146102f457806384eff0fa146102fc578063893d20e81461030f5780639164975114610320578063946cd73f1461033b5780639b17541c1461034e57600080fd5b80633d4d837f1161014b578063614080a111610125578063614080a114610280578063687abf7d146102935780636c36511a146102a65780636f2a626f146102e157600080fd5b80633d4d837f1461022c5780634fde79ad1461023f57806352d1902d1461025257600080fd5b80630df1ecfd14610193578063139b0f75146101cb5780631621eecb146101e05780633011ad9b146101f357806334439c8014610206578063383bf14214610219575b600080fd5b6101ae73ad45a78180961079bfaeee349704f411dff947c681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101de6101d93660046119e1565b61045b565b005b6101de6101ee366004611a32565b6105b7565b6101de610201366004611aaa565b61066f565b6101de610214366004611b23565b6106f6565b6101de610227366004611c15565b6108d1565b6101de61023a366004611c6c565b610b24565b6101de61024d366004611cbd565b610df1565b6040517fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf781526020016101c2565b6003546101ae906001600160a01b031681565b6101de6102a1366004611cda565b610f00565b6102d46102b4366004611cf7565b805160208183018101805160058252928201919093012091525460ff1681565b6040516101c29190611da1565b6101de6102ef366004611dc9565b610fa1565b6101de61107a565b6007546101ae906001600160a01b031681565b6000546001600160a01b03166101ae565b6101ae7338a4794cced47d3baf7370ccc43b560d3a1beefa81565b6101de610349366004611df5565b6110c1565b6101de61035c366004611e52565b61118d565b6101de61036f366004611cda565b6113b2565b6101de610382366004611cda565b611412565b6101de610395366004611cda565b6114d6565b6101de6103a8366004611ea6565b61154c565b6103c06103bb366004611cda565b6116b1565b60405190151581526020016101c2565b6104176103de366004611cda565b6004602052600090815260409020546001600160a01b03811690600160a01b810461ffff1690600160b01b90046001600160401b031683565b604080516001600160a01b03909416845261ffff90921660208401526001600160401b0316908201526060016101c2565b6101de610456366004611cda565b6116c4565b6003546001600160a01b031633146104865760405163375152c160e01b815260040160405180910390fd5b60075460405163e596614f60e01b81526001600160401b03851660048201527338a4794cced47d3baf7370ccc43b560d3a1beefa9163bc26e7e59130916001600160a01b03169063e596614f90602401600060405180830381865afa1580156104f3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261051b9190810190611f28565b85856040518563ffffffff1660e01b815260040161053c949392919061204c565b600060405180830381600087803b15801561055657600080fd5b505af115801561056a573d6000803e3d6000fd5b5050604080516001600160401b0387168152602081018690527f50c39e9703d590409e39722da8c2ce8bfe34dded154bddaa043935c2409c80cc93500190505b60405180910390a1505050565b6105c260013361177f565b6105df5760405163ad7acb4760e01b815260040160405180910390fd5b61271061ffff821611156106065760405163013c3ba760e41b815260040160405180910390fd5b33600081815260046020908152604091829020805461ffff60a01b1916600160a01b61ffff8716908102919091179091558251938452908301527f027aba72ce53b1cf4098eff40bd649811ea216a5829fe29081fb013ae6a1b96f91015b60405180910390a150565b6000546001600160a01b0316331461069a576040516330cd747160e01b815260040160405180910390fd5b6106a56001826117a4565b156106dd577fcac241f16294cde789c1efe865bbb26d0a5d55fbf2b5b696fdb304c65f231d648383836040516105aa939291906120b9565b604051630f084ddf60e31b815260040160405180910390fd5b6003546001600160a01b031633146107215760405163375152c160e01b815260040160405180910390fd5b6003600585856040516107359291906120e5565b9081526040519081900360200190205460ff16600481111561075957610759611d8b565b14610777576040516365c4b31760e11b815260040160405180910390fd5b6040516312b3fc1960e01b81527338a4794cced47d3baf7370ccc43b560d3a1beefa906312b3fc19906107b49087908790879087906004016120f5565b600060405180830381600087803b1580156107ce57600080fd5b505af11580156107e2573d6000803e3d6000fd5b505050506001600160a01b038581166000908152600460208190526040808320548151631e5c085b60e31b8152915194169363f2e042d89382840193909282900301818387803b15801561083557600080fd5b505af1158015610849573d6000803e3d6000fd5b505050506004600585856040516108619291906120e5565b908152604051908190036020019020805460ff1916600183600481111561088a5761088a611d8b565b02179055507fcc8a7c9c5bd7463d45f32c9ffe39af44dc854cb4b8dc0329d1c3bdeb1031e0148585856040516108c29392919061212b565b60405180910390a15050505050565b6003546001600160a01b031633146108fc5760405163375152c160e01b815260040160405180910390fd5b6001600561090a8380612150565b6040516109189291906120e5565b9081526040519081900360200190205460ff16600481111561093c5761093c611d8b565b1461095a576040516365c4b31760e11b815260040160405180910390fd5b60405163095ea7b360e01b81527338a4794cced47d3baf7370ccc43b560d3a1beefa60048201526060820135602482015273ad45a78180961079bfaeee349704f411dff947c69063095ea7b3906044016020604051808303816000875af11580156109c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ed9190612196565b507338a4794cced47d3baf7370ccc43b560d3a1beefa6306e8fb9c610a128380612150565b610a1f60208601866121b3565b610a2c6040880188612150565b8860600135896080016040518963ffffffff1660e01b8152600401610a5898979695949392919061223a565b600060405180830381600087803b158015610a7257600080fd5b505af1158015610a86573d6000803e3d6000fd5b506002925060059150610a9b90508380612150565b604051610aa99291906120e5565b908152604051908190036020019020805460ff19166001836004811115610ad257610ad2611d8b565b02179055507f171bb1de68bd2c93b96f9f3f89ca7fd4a762f9459270bf93a55307be183f93f0610b028280612150565b848460600135604051610b1894939291906122f7565b60405180910390a15050565b610b2f60013361177f565b610b4c5760405163ad7acb4760e01b815260040160405180910390fd5b336000908152600460205260409020546001600160a01b031615610b83576040516312f8923160e31b815260040160405180910390fd5b306001600160a01b0316846001600160a01b031663c06546006040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bef9190612327565b6001600160a01b031614610c165760405163a714776d60e01b815260040160405180910390fd5b61271061ffff82161115610c3d5760405163013c3ba760e41b815260040160405180910390fd5b60405163142d3a2760e21b8152600481018390526001600160a01b038516906350b4e89c90602401600060405180830381600087803b158015610c7f57600080fd5b505af1158015610c93573d6000803e3d6000fd5b505060075460405163e596614f60e01b81526001600160401b03871660048201526001600160a01b03909116925063e596614f9150602401600060405180830381865afa158015610ce8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d109190810190611f28565b5060408051606080820183526001600160a01b0387811680845261ffff86811660208087018281526001600160401b038c8116898b01818152336000818152600487528d90209b518c5495519251909416600160b01b0267ffffffffffffffff60b01b1992909816600160a01b026001600160b01b0319909516939099169290921792909217169390931790965586519384529483019190915293810192909252810191909152608081018390527fb2098e6993da52c711ce658efb7338e41bcf578da2e4766a301bb62db47e33949060a00160405180910390a150505050565b610dfc60013361177f565b610e195760405163ad7acb4760e01b815260040160405180910390fd5b60075460405163e596614f60e01b81526001600160401b03831660048201526001600160a01b039091169063e596614f90602401600060405180830381865afa158015610e6a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e929190810190611f28565b5033600081815260046020908152604091829020805467ffffffffffffffff60b01b1916600160b01b6001600160401b038716908102919091179091558251938452908301527f6b15499268e2722b1ec653445be16693c8460e390b5f9c4dae011c081ee824459101610664565b6000546001600160a01b03163314610f2b576040516330cd747160e01b815260040160405180910390fd5b806001600160a01b038116610f53576040516376cb291d60e11b815260040160405180910390fd5b600780546001600160a01b0319166001600160a01b0384169081179091556040519081527f141084bbe0b806ca3d4c9dfa41d4987df8ed29c7f2ae20d4a017e87d955fb7ed90602001610b18565b6003546001600160a01b03163314610fcc5760405163375152c160e01b815260040160405180910390fd5b6001600160a01b0382811660009081526004602081905260409182902054915163043d014d60e41b81529081018490529116906343d014d090602401600060405180830381600087803b15801561102257600080fd5b505af1158015611036573d6000803e3d6000fd5b5050604080516001600160a01b0386168152602081018590527f7b3f28e29d512f36e608771705975ad5c436cf19d368573a1657c24e0db8b1209350019050610b18565b600054600160a01b900460ff16156110a557604051631ee1e30360e21b815260040160405180910390fd5b60008054600160a01b6001600160a81b03199091163317179055565b6110cc60013361177f565b6110e95760405163ad7acb4760e01b815260040160405180910390fd5b3360009081526004602081905260409182902054915163142d3a2760e21b81529081018390526001600160a01b03909116906350b4e89c90602401600060405180830381600087803b15801561113e57600080fd5b505af1158015611152573d6000803e3d6000fd5b505060408051338152602081018590527f61020a83dba6b08612f9c1dbe9e636c781693c44b062f0f4ab3307f11340b02a9350019050610664565b6003546001600160a01b031633146111b85760405163375152c160e01b815260040160405180910390fd5b60005b8181101561132c57600060058484848181106111d9576111d9612344565b90506020028101906111eb919061235a565b6111f59080612150565b6040516112039291906120e5565b9081526040519081900360200190205460ff16600481111561122757611227611d8b565b14611245576040516365c4b31760e11b815260040160405180910390fd5b6001600584848481811061125b5761125b612344565b905060200281019061126d919061235a565b6112779080612150565b6040516112859291906120e5565b908152604051908190036020019020805460ff191660018360048111156112ae576112ae611d8b565b02179055507fb7abbfc20ad848177398301a969cb076026b7c4a15b063eda34013ad984587c38383838181106112e6576112e6612344565b90506020028101906112f8919061235a565b6113029080612150565b86604051611312939291906120b9565b60405180910390a1806113248161237a565b9150506111bb565b506001600160a01b0383811660009081526004602081905260409182902054915163303f5e4160e11b81529282169263607ebc829261137b9287928792600160a01b900461ffff1691016123e6565b600060405180830381600087803b15801561139557600080fd5b505af11580156113a9573d6000803e3d6000fd5b50505050505050565b6000546001600160a01b031633146113dd576040516330cd747160e01b815260040160405180910390fd5b806001600160a01b038116611405576040516376cb291d60e11b815260040160405180910390fd5b61140e826117b9565b5050565b6000546001600160a01b0316331461143d576040516330cd747160e01b815260040160405180910390fd5b806001600160a01b038116611465576040516376cb291d60e11b815260040160405180910390fd5b6040516336f370b360e21b81526001600160a01b03831660048201527338a4794cced47d3baf7370ccc43b560d3a1beefa9063dbcdc2cc90602401600060405180830381600087803b1580156114ba57600080fd5b505af11580156114ce573d6000803e3d6000fd5b505050505050565b6000546001600160a01b03163314611501576040516330cd747160e01b815260040160405180910390fd5b806001600160a01b038116611529576040516376cb291d60e11b815260040160405180910390fd5b50600380546001600160a01b0319166001600160a01b0392909216919091179055565b6003546001600160a01b031633146115775760405163375152c160e01b815260040160405180910390fd5b60026005858560405161158b9291906120e5565b9081526040519081900360200190205460ff1660048111156115af576115af611d8b565b146115cd576040516365c4b31760e11b815260040160405180910390fd5b604051633877322b60e01b81527338a4794cced47d3baf7370ccc43b560d3a1beefa90633877322b9061160a9087908790879087906004016124c8565b600060405180830381600087803b15801561162457600080fd5b505af1158015611638573d6000803e3d6000fd5b505050506003600585856040516116509291906120e5565b908152604051908190036020019020805460ff1916600183600481111561167957611679611d8b565b02179055507f214fff527fb78557a10a93b77e999e02035639169dd2ac2c14c3c9b19f4913d38585856040516108c29392919061212b565b60006116be60018361177f565b92915050565b6000546001600160a01b031633146116ef576040516330cd747160e01b815260040160405180910390fd5b6001600160a01b038116611716576040516376cb291d60e11b815260040160405180910390fd5b600054604080516001600160a01b03928316815291831660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b600061179d836001600160a01b03841661187e565b806001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181b91906124ef565b7fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf71461185a5760405163f030d0ad60e01b815260040160405180910390fd5b7fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf755565b60008181526001830160205260408120546118c5575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556116be565b5060006116be565b6001600160401b03811681146118e257600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611923576119236118e5565b604052919050565b803563ffffffff8116811461193f57600080fd5b919050565b80151581146118e257600080fd5b600060a0828403121561196457600080fd5b60405160a081018181106001600160401b0382111715611986576119866118e5565b6040529050806119958361192b565b815260208301356119a5816118cd565b602082015260408301356119b8816118cd565b604082015260608301356119cb81611944565b6060820152608092830135920191909152919050565b600080600060e084860312156119f657600080fd5b8335611a01816118cd565b925060208401359150611a178560408601611952565b90509250925092565b803561ffff8116811461193f57600080fd5b600060208284031215611a4457600080fd5b61179d82611a20565b60008083601f840112611a5f57600080fd5b5081356001600160401b03811115611a7657600080fd5b602083019150836020828501011115611a8e57600080fd5b9250929050565b6001600160a01b03811681146118e257600080fd5b600080600060408486031215611abf57600080fd5b83356001600160401b03811115611ad557600080fd5b611ae186828701611a4d565b9094509250506020840135611af581611a95565b809150509250925092565b60006001600160401b03821115611b1957611b196118e5565b5060051b60200190565b60008060008060006101008688031215611b3c57600080fd5b8535611b4781611a95565b94506020868101356001600160401b0380821115611b6457600080fd5b611b708a838b01611a4d565b90975095506040890135915080821115611b8957600080fd5b508701601f81018913611b9b57600080fd5b8035611bae611ba982611b00565b6118fb565b81815260059190911b8201830190838101908b831115611bcd57600080fd5b928401925b82841015611bf4578335611be5816118cd565b82529284019290840190611bd2565b8096505050505050611c098760608801611952565b90509295509295909350565b60008060408385031215611c2857600080fd5b8235611c3381611a95565b915060208301356001600160401b03811115611c4e57600080fd5b83016101208186031215611c6157600080fd5b809150509250929050565b60008060008060808587031215611c8257600080fd5b8435611c8d81611a95565b93506020850135611c9d816118cd565b925060408501359150611cb260608601611a20565b905092959194509250565b600060208284031215611ccf57600080fd5b813561179d816118cd565b600060208284031215611cec57600080fd5b813561179d81611a95565b60006020808385031215611d0a57600080fd5b82356001600160401b0380821115611d2157600080fd5b818501915085601f830112611d3557600080fd5b813581811115611d4757611d476118e5565b611d59601f8201601f191685016118fb565b91508082528684828501011115611d6f57600080fd5b8084840185840137600090820190930192909252509392505050565b634e487b7160e01b600052602160045260246000fd5b6020810160058310611dc357634e487b7160e01b600052602160045260246000fd5b91905290565b60008060408385031215611ddc57600080fd5b8235611de781611a95565b946020939093013593505050565b600060208284031215611e0757600080fd5b5035919050565b60008083601f840112611e2057600080fd5b5081356001600160401b03811115611e3757600080fd5b6020830191508360208260051b8501011115611a8e57600080fd5b600080600060408486031215611e6757600080fd5b8335611e7281611a95565b925060208401356001600160401b03811115611e8d57600080fd5b611e9986828701611e0e565b9497909650939450505050565b600080600080600060608688031215611ebe57600080fd5b8535611ec981611a95565b945060208601356001600160401b0380821115611ee557600080fd5b611ef189838a01611a4d565b90965094506040880135915080821115611f0a57600080fd5b50611f1788828901611e0e565b969995985093965092949392505050565b60006020808385031215611f3b57600080fd5b82516001600160401b03811115611f5157600080fd5b8301601f81018513611f6257600080fd5b8051611f70611ba982611b00565b81815260059190911b82018301908381019087831115611f8f57600080fd5b928401925b82841015611fb6578351611fa7816118cd565b82529284019290840190611f94565b979650505050505050565b600081518084526020808501945080840160005b83811015611ffa5781516001600160401b031687529582019590820190600101611fd5565b509495945050505050565b63ffffffff815116825260208101516001600160401b0380821660208501528060408401511660408501525050606081015115156060830152608081015160808301525050565b6001600160a01b03851681526101006020820181905260009061207183820187611fc1565b9150508360408301526120876060830184612005565b95945050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6040815260006120cd604083018587612090565b905060018060a01b0383166020830152949350505050565b8183823760009101908152919050565b60e08152600061210960e083018688612090565b828103602084015261211b8186611fc1565b9150506120876040830184612005565b6001600160a01b03841681526040602082018190526000906120879083018486612090565b6000808335601e1984360301811261216757600080fd5b8301803591506001600160401b0382111561218157600080fd5b602001915036819003821315611a8e57600080fd5b6000602082840312156121a857600080fd5b815161179d81611944565b6000808335601e198436030181126121ca57600080fd5b8301803591506001600160401b038211156121e457600080fd5b6020019150600581901b3603821315611a8e57600080fd5b8183526000602080850194508260005b85811015611ffa57813561221f816118cd565b6001600160401b03168752958201959082019060010161220c565b600061012080835261224f8184018b8d612090565b9050828103602084015261226481898b6121fc565b90508281036040840152612279818789612090565b91505083606083015263ffffffff6122908461192b565b16608083015260208301356122a4816118cd565b6001600160401b0390811660a08401526040840135906122c3826118cd565b1660c083015260608301356122d781611944565b151560e08301526080929092013561010090910152979650505050505050565b60608152600061230b606083018688612090565b6001600160a01b03949094166020830152506040015292915050565b60006020828403121561233957600080fd5b815161179d81611a95565b634e487b7160e01b600052603260045260246000fd5b60008235607e1983360301811261237057600080fd5b9190910192915050565b60006001820161239a57634e487b7160e01b600052601160045260246000fd5b5060010190565b6000808335601e198436030181126123b857600080fd5b83016020810192503590506001600160401b038111156123d757600080fd5b803603821315611a8e57600080fd5b60408082528181018490526000906060808401600587901b850182018885805b8a8110156124b057888403605f190185528235368d9003607e1901811261242b578283fd5b8c01608061243982806123a1565b8288526124498389018284612090565b92505050602061245b818401846123a1565b888403838a015261246d848284612090565b9350505061247d8a8401846123a1565b8884038c8a015261248f848284612090565b948b0135988b01989098525096870196919550509290920191600101612406565b50505080945050505050826020830152949350505050565b6040815260006124dc604083018688612090565b8281036020840152611fb68185876121fc565b60006020828403121561250157600080fd5b505191905056fea26469706673582212208f183f710082f405be0e45237f9db401e444338f1b9bdbd50bc1bce45401598564736f6c63430008130033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits

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.