ETH Price: $2,048.99 (+2.25%)

Contract

0x15258eFE0E8fFa63C868b3ba314a4A2b5F6a7f4E
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Add DON219255052025-02-25 19:42:23397 days ago1740512543IN
0x15258eFE...b5F6a7f4E
0 ETH0.001018921.4643667
Add DON219255032025-02-25 19:41:59397 days ago1740512519IN
0x15258eFE...b5F6a7f4E
0 ETH0.002849591.3268719
Add DON219255022025-02-25 19:41:47397 days ago1740512507IN
0x15258eFE...b5F6a7f4E
0 ETH0.001884541.37386839
Add DON219255012025-02-25 19:41:35397 days ago1740512495IN
0x15258eFE...b5F6a7f4E
0 ETH0.001427281.32758202
Add Nodes219254292025-02-25 19:27:11397 days ago1740511631IN
0x15258eFE...b5F6a7f4E
0 ETH0.002648531.0165203
Add Nodes219250742025-02-25 18:16:11397 days ago1740507371IN
0x15258eFE...b5F6a7f4E
0 ETH0.017406761.4687456
Add Node Operato...219250322025-02-25 18:07:47397 days ago1740506867IN
0x15258eFE...b5F6a7f4E
0 ETH0.001284161.46828582
Add Capabilities219250252025-02-25 18:06:23397 days ago1740506783IN
0x15258eFE...b5F6a7f4E
0 ETH0.001017971.44515105

Advanced mode:
Parent Transaction Hash Method Block
From
To
View All Internal Transactions
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CapabilitiesRegistry

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol";
import {ICapabilityConfiguration} from "./interfaces/ICapabilityConfiguration.sol";

import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol";

import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol";
import {ERC165Checker} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol";
import {ICapabilityConfiguration} from "./interfaces/ICapabilityConfiguration.sol";
import {INodeInfoProvider} from "./interfaces/INodeInfoProvider.sol";

/// @notice CapabilitiesRegistry is used to manage Nodes (including their links to Node Operators), Capabilities,
/// and DONs (Decentralized Oracle Networks) which are sets of nodes that support those Capabilities.
/// @dev The contract currently stores the entire state of Node Operators, Nodes, Capabilities and DONs in the
/// contract and requires a full state migration if an upgrade is ever required. The team acknowledges this and is
/// fine reconfiguring the upgraded contract in the future so as to not add extra complexity to this current version.
contract CapabilitiesRegistry is INodeInfoProvider, OwnerIsCreator, ITypeAndVersion {
  // Add the library methods
  using EnumerableSet for EnumerableSet.Bytes32Set;
  using EnumerableSet for EnumerableSet.UintSet;

  struct NodeOperator {
    /// @notice The address of the admin that can manage a node operator
    address admin;
    /// @notice Human readable name of a Node Operator managing the node
    /// @dev The contract does not validate the length or characters of the node operator name because
    /// a trusted admin will supply these names. We reduce gas costs by omitting these checks on-chain.
    string name;
  }

  struct NodeParams {
    /// @notice The id of the node operator that manages this node
    uint32 nodeOperatorId;
    /// @notice The signer address for application-layer message verification.
    bytes32 signer;
    /// @notice This is an Ed25519 public key that is used to identify a node. This key is guaranteed to
    /// be unique in the CapabilitiesRegistry. It is used to identify a node in the the P2P network.
    bytes32 p2pId;
    /// @notice Public key used to encrypt secrets for this node
    bytes32 encryptionPublicKey;
    /// @notice The list of hashed capability IDs supported by the node
    bytes32[] hashedCapabilityIds;
  }

  struct Node {
    /// @notice The node's parameters
    /// @notice The id of the node operator that manages this node
    uint32 nodeOperatorId;
    /// @notice The number of times the node's configuration has been updated
    uint32 configCount;
    /// @notice The ID of the Workflow DON that the node belongs to. A node can
    /// only belong to one DON that accepts Workflows.
    uint32 workflowDONId;
    /// @notice The signer address for application-layer message verification.
    /// @dev This key is guaranteed to be unique in the CapabilitiesRegistry as a signer
    /// address can only belong to one node.
    /// @dev This should be the ABI encoded version of the node's address. I.e 0x0000address. The Capability Registry
    /// does not store it as an address so that non EVM chains with addresses greater than 20 bytes can be supported
    /// in the future.
    bytes32 signer;
    /// @notice This is an Ed25519 public key that is used to identify a node. This key is guaranteed
    /// to be unique in the CapabilitiesRegistry. It is used to identify a node in the the P2P network.
    bytes32 p2pId;
    /// @notice Public key used to encrypt secrets for this node
    bytes32 encryptionPublicKey;
    /// @notice The node's supported capabilities
    /// @dev This is stored as a map so that we can easily update to a set of new capabilities by
    /// incrementing the configCount and creating a new set of supported capability IDs
    mapping(uint32 configCount => EnumerableSet.Bytes32Set capabilityId) supportedHashedCapabilityIds;
    /// @notice The list of capabilities DON Ids supported by the node. A node can belong to multiple
    /// capabilities DONs. This list does not include a Workflow DON id if the node belongs to one.
    EnumerableSet.UintSet capabilitiesDONIds;
  }

  /// @notice CapabilityResponseType indicates whether remote response requires aggregation or is
  /// an already aggregated report. There are multiple possible ways to aggregate.
  /// @dev REPORT response type receives signatures together with the response that is used to verify the data.
  /// OBSERVATION_IDENTICAL just receives data without signatures and waits for some number of observations before
  /// proceeding to the next step
  enum CapabilityResponseType {
    // No additional aggregation is needed on the remote response.
    REPORT,
    // A number of identical observations need to be aggregated.
    OBSERVATION_IDENTICAL
  }

  /// @notice CapabilityType indicates the type of capability which determines
  /// where the capability can be used in a Workflow Spec.
  enum CapabilityType {
    TRIGGER,
    ACTION,
    CONSENSUS,
    TARGET
  }

  struct Capability {
    /// @notice The partially qualified ID for the capability.
    /// @dev Given the following capability ID: {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version}
    /// Then we denote the `labelledName` as the `{name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}`
    /// portion of the ID.
    ///
    /// Ex. id = "data-streams-reports:chain:ethereum@1.0.0"
    ///     labelledName = "data-streams-reports:chain:ethereum"
    string labelledName;
    /// @notice Semver, e.g., "1.2.3"
    /// @dev must be valid Semver + max 32 characters.
    string version;
    /// @notice CapabilityType indicates the type of capability which determines
    /// where the capability can be used in a Workflow Spec.
    CapabilityType capabilityType;
    /// @notice CapabilityResponseType indicates whether remote response requires aggregation or is an
    /// already aggregated report. There are multiple possible ways to aggregate.
    CapabilityResponseType responseType;
    /// @notice An address to the capability configuration contract. Having this defined on a capability enforces
    /// consistent configuration across DON instances serving the same capability. Configuration contract MUST implement
    /// CapabilityConfigurationContractInterface.
    ///
    /// @dev The main use cases are:
    /// 1) Sharing capability configuration across DON instances
    /// 2) Inspect and modify on-chain configuration without off-chain capability code.
    ///
    /// It is not recommended to store configuration which requires knowledge of the DON membership.
    address configurationContract;
  }

  struct CapabilityInfo {
    /// @notice A hashed ID created by the `getHashedCapabilityId` function.
    bytes32 hashedId;
    /// @notice The partially qualified ID for the capability.
    /// @dev Given the following capability ID: {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version}
    /// Then we denote the `labelledName` as the `{name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}`
    /// portion of the ID.
    ///
    /// Ex. id = "data-streams-reports:chain:ethereum@1.0.0"
    ///     labelledName = "data-streams-reports:chain:ethereum"
    string labelledName;
    /// @notice Semver, e.g., "1.2.3"
    /// @dev must be valid Semver + max 32 characters.
    string version;
    /// @notice CapabilityType indicates the type of capability which determines
    /// where the capability can be used in a Workflow Spec.
    CapabilityType capabilityType;
    /// @notice CapabilityResponseType indicates whether remote response requires aggregation
    /// or is an already aggregated report. There are multiple possible ways to aggregate.
    CapabilityResponseType responseType;
    /// @notice An address to the capability configuration contract. Having this defined on a capability enforces
    /// consistent configuration across DON instances serving the same capability. Configuration contract MUST implement
    /// CapabilityConfigurationContractInterface.
    ///
    /// @dev The main use cases are:
    /// 1) Sharing capability configuration across DON instances
    /// 2) Inspect and modify on-chain configuration without off-chain capability code.
    ///
    /// It is not recommended to store configuration which requires knowledge of the DON membership.
    address configurationContract;
    /// @notice True if the capability is deprecated
    bool isDeprecated;
  }

  /// @notice CapabilityConfiguration is a struct that holds the capability configuration
  /// for a specific DON
  struct CapabilityConfiguration {
    /// @notice The capability Id
    bytes32 capabilityId;
    /// @notice The capability config specific to a DON.  This will be decoded offchain
    bytes config;
  }

  struct DONCapabilityConfig {
    /// @notice The set of p2pIds of nodes that belong to this DON. A node (the same p2pId) can belong to multiple DONs.
    EnumerableSet.Bytes32Set nodes;
    /// @notice The set of capabilityIds
    bytes32[] capabilityIds;
    /// @notice Mapping from hashed capability IDs to configs
    mapping(bytes32 capabilityId => bytes config) capabilityConfigs;
  }

  /// @notice DON (Decentralized Oracle Network) is a grouping of nodes that support
  // the same capabilities.
  struct DON {
    /// @notice Computed. Auto-increment.
    uint32 id;
    /// @notice The number of times the DON was configured
    uint32 configCount;
    /// @notice The f value for the DON.  This is the number of faulty nodes
    /// that the DON can tolerate. This can be different from the f value of
    /// the OCR instances that capabilities spawn.
    uint8 f;
    /// @notice True if the DON is public. A public DON means that it accepts
    /// external capability requests
    bool isPublic;
    /// @notice True if the DON accepts Workflows. A DON that accepts Workflows
    /// is called Workflow DON and it can process Workflow Specs. A Workflow
    /// DON also support one or more capabilities as well.
    bool acceptsWorkflows;
    /// @notice Mapping of config counts to configurations
    mapping(uint32 configCount => DONCapabilityConfig donConfig) config;
  }

  struct DONInfo {
    /// @notice Computed. Auto-increment.
    uint32 id;
    /// @notice The number of times the DON was configured
    uint32 configCount;
    /// @notice The f value for the DON.  This is the number of faulty nodes
    /// that the DON can tolerate. This can be different from the f value of
    /// the OCR instances that capabilities spawn.
    uint8 f;
    /// @notice True if the DON is public.  A public DON means that it accepts
    /// external capability requests
    bool isPublic;
    /// @notice True if the DON accepts Workflows.
    bool acceptsWorkflows;
    /// @notice List of member node P2P Ids
    bytes32[] nodeP2PIds;
    /// @notice List of capability configurations
    CapabilityConfiguration[] capabilityConfigurations;
  }

  /// @notice DONParams is a struct that holds the parameters for a DON.
  /// @dev This is needed to avoid "stack too deep" errors in _setDONConfig.
  struct DONParams {
    uint32 id;
    uint32 configCount;
    bool isPublic;
    bool acceptsWorkflows;
    uint8 f;
  }

  /// @notice This error is thrown when a caller is not allowed
  /// to execute the transaction
  /// @param sender The address that tried to execute the transaction
  error AccessForbidden(address sender);

  /// @notice This error is thrown when there is a mismatch between
  /// array arguments
  /// @param lengthOne The length of the first array argument
  /// @param lengthTwo The length of the second array argument
  error LengthMismatch(uint256 lengthOne, uint256 lengthTwo);

  /// @notice This error is thrown when trying to set a node operator's
  /// admin address to the zero address
  error InvalidNodeOperatorAdmin();

  /// @notice This error is thrown when trying to add a node with P2P ID that
  /// is empty bytes
  /// @param p2pId The provided P2P ID
  error InvalidNodeP2PId(bytes32 p2pId);

  /// @notice This error is thrown when trying to add a node without
  /// including the encryption public key bytes.
  /// @param encryptionPublicKey The encryption public key bytes
  error InvalidNodeEncryptionPublicKey(bytes32 encryptionPublicKey);

  /// @notice This error is thrown when trying to add a node without
  /// capabilities or with capabilities that do not exist.
  /// @param hashedCapabilityIds The IDs of the capabilities that are being added.
  error InvalidNodeCapabilities(bytes32[] hashedCapabilityIds);

  /// @notice This error is emitted when a DON does not exist
  /// @param donId The ID of the nonexistent DON
  error DONDoesNotExist(uint32 donId);

  /// @notice This error is thrown when trying to set the node's
  /// signer address to zero or if the signer address has already
  /// been used by another node
  error InvalidNodeSigner();

  /// @notice This error is thrown when trying to add a capability that already
  /// exists.
  /// @param hashedCapabilityId The hashed capability ID of the capability
  /// that already exists
  error CapabilityAlreadyExists(bytes32 hashedCapabilityId);

  /// @notice This error is thrown when trying to add a node that already
  /// exists.
  /// @param nodeP2PId The P2P ID of the node that already exists
  error NodeAlreadyExists(bytes32 nodeP2PId);

  /// @notice This error is thrown when trying to add a node to a DON where
  /// the node does not support the capability
  /// @param nodeP2PId The P2P ID of the node
  /// @param capabilityId The ID of the capability
  error NodeDoesNotSupportCapability(bytes32 nodeP2PId, bytes32 capabilityId);

  /// @notice This error is thrown when trying to add a capability configuration
  /// for a capability that was already configured on a DON
  /// @param donId The ID of the DON that the capability was configured for
  /// @param capabilityId The ID of the capability that was configured
  error DuplicateDONCapability(uint32 donId, bytes32 capabilityId);

  /// @notice This error is thrown when trying to add a duplicate node to a DON
  /// @param donId The ID of the DON that the node was added for
  /// @param nodeP2PId The P2P ID of the node
  error DuplicateDONNode(uint32 donId, bytes32 nodeP2PId);

  /// @notice This error is thrown when trying to configure a DON with invalid
  /// fault tolerance value.
  /// @param f The proposed fault tolerance value
  /// @param nodeCount The proposed number of nodes in the DON
  error InvalidFaultTolerance(uint8 f, uint256 nodeCount);

  /// @notice This error is thrown when a capability with the provided hashed ID is
  /// not found.
  /// @param hashedCapabilityId The hashed ID used for the lookup.
  error CapabilityDoesNotExist(bytes32 hashedCapabilityId);

  /// @notice This error is thrown when trying to deprecate a capability that
  /// is deprecated.
  /// @param hashedCapabilityId The hashed ID of the capability that is deprecated.
  error CapabilityIsDeprecated(bytes32 hashedCapabilityId);

  /// @notice This error is thrown when a node operator does not exist
  /// @param nodeOperatorId The ID of the node operator that does not exist
  error NodeOperatorDoesNotExist(uint32 nodeOperatorId);

  /// @notice This error is thrown when trying to remove a node that is still
  /// part of a capabilities DON
  /// @param donId The Id of the DON the node belongs to
  /// @param nodeP2PId The P2P Id of the node being removed
  error NodePartOfCapabilitiesDON(uint32 donId, bytes32 nodeP2PId);

  /// @notice This error is thrown when attempting to add a node to a second
  /// Workflow DON or when trying to remove a node that belongs to a Workflow
  /// DON
  /// @param donId The Id of the DON the node belongs to
  /// @param nodeP2PId The P2P Id of the node
  error NodePartOfWorkflowDON(uint32 donId, bytes32 nodeP2PId);

  /// @notice This error is thrown when removing a capability from the node
  /// when that capability is still required by one of the DONs the node
  /// belongs to.
  /// @param hashedCapabilityId The hashed ID of the capability
  /// @param donId The ID of the DON that requires the capability
  error CapabilityRequiredByDON(bytes32 hashedCapabilityId, uint32 donId);

  /// @notice This error is thrown when trying to add a capability with a
  /// configuration contract that does not implement the required interface.
  /// @param proposedConfigurationContract The address of the proposed
  /// configuration contract.
  error InvalidCapabilityConfigurationContractInterface(address proposedConfigurationContract);

  /// @notice This event is emitted when a new node is added
  /// @param p2pId The P2P ID of the node
  /// @param nodeOperatorId The ID of the node operator that manages this node
  /// @param signer The encoded node's signer address
  event NodeAdded(bytes32 p2pId, uint32 indexed nodeOperatorId, bytes32 signer);

  /// @notice This event is emitted when a node is removed
  /// @param p2pId The P2P ID of the node that was removed
  event NodeRemoved(bytes32 p2pId);

  /// @notice This event is emitted when a node is updated
  /// @param p2pId The P2P ID of the node
  /// @param nodeOperatorId The ID of the node operator that manages this node
  /// @param signer The node's signer address
  event NodeUpdated(bytes32 p2pId, uint32 indexed nodeOperatorId, bytes32 signer);

  /// @notice This event is emitted when a DON's config is set
  /// @param donId The ID of the DON the config was set for
  /// @param configCount The number of times the DON has been
  /// configured
  event ConfigSet(uint32 indexed donId, uint32 configCount);

  /// @notice This event is emitted when a new node operator is added
  /// @param nodeOperatorId The ID of the newly added node operator
  /// @param admin The address of the admin that can manage the node
  /// operator
  /// @param name The human readable name of the node operator
  event NodeOperatorAdded(uint32 indexed nodeOperatorId, address indexed admin, string name);

  /// @notice This event is emitted when a node operator is removed
  /// @param nodeOperatorId The ID of the node operator that was removed
  event NodeOperatorRemoved(uint32 indexed nodeOperatorId);

  /// @notice This event is emitted when a node operator is updated
  /// @param nodeOperatorId The ID of the node operator that was updated
  /// @param admin The address of the node operator's admin
  /// @param name The node operator's human readable name
  event NodeOperatorUpdated(uint32 indexed nodeOperatorId, address indexed admin, string name);

  /// @notice This event is emitted when a new capability is added
  /// @param hashedCapabilityId The hashed ID of the newly added capability
  event CapabilityConfigured(bytes32 indexed hashedCapabilityId);

  /// @notice This event is emitted when a capability is deprecated
  /// @param hashedCapabilityId The hashed ID of the deprecated capability
  event CapabilityDeprecated(bytes32 indexed hashedCapabilityId);

  string public constant override typeAndVersion = "CapabilitiesRegistry 1.1.0";

  /// @notice Mapping of capabilities
  mapping(bytes32 hashedCapabilityId => Capability capability) private s_capabilities;

  /// @notice Set of hashed capability IDs.
  /// A hashed ID is created by the function `getHashedCapabilityId`.
  EnumerableSet.Bytes32Set private s_hashedCapabilityIds;

  /// @notice Set of deprecated hashed capability IDs,
  /// A hashed ID is created by the function `getHashedCapabilityId`.
  EnumerableSet.Bytes32Set private s_deprecatedHashedCapabilityIds;

  /// @notice Encoded node signer addresses
  EnumerableSet.Bytes32Set private s_nodeSigners;

  /// @notice Set of node P2P IDs
  EnumerableSet.Bytes32Set private s_nodeP2PIds;

  /// @notice Mapping of node operators
  mapping(uint32 nodeOperatorId => NodeOperator nodeOperator) private s_nodeOperators;

  /// @notice Mapping of nodes
  mapping(bytes32 p2pId => Node node) private s_nodes;

  /// @notice Mapping of DON IDs to DONs
  mapping(uint32 donId => DON don) private s_dons;

  /// @notice The next ID to assign a new node operator to
  /// @dev Starting with 1 to avoid confusion with the zero value
  /// @dev No getter for this as this is an implementation detail
  uint32 private s_nextNodeOperatorId = 1;

  /// @notice The next ID to assign a new DON to
  /// @dev Starting with 1 to avoid confusion with the zero value
  uint32 private s_nextDONId = 1;

  /// @notice Adds a list of node operators
  /// @param nodeOperators List of node operators to add
  function addNodeOperators(NodeOperator[] calldata nodeOperators) external onlyOwner {
    for (uint256 i; i < nodeOperators.length; ++i) {
      NodeOperator memory nodeOperator = nodeOperators[i];
      if (nodeOperator.admin == address(0)) revert InvalidNodeOperatorAdmin();
      uint32 nodeOperatorId = s_nextNodeOperatorId;
      s_nodeOperators[nodeOperatorId] = NodeOperator({admin: nodeOperator.admin, name: nodeOperator.name});
      ++s_nextNodeOperatorId;
      emit NodeOperatorAdded(nodeOperatorId, nodeOperator.admin, nodeOperator.name);
    }
  }

  /// @notice Removes a node operator
  /// @param nodeOperatorIds The IDs of the node operators to remove
  function removeNodeOperators(uint32[] calldata nodeOperatorIds) external onlyOwner {
    for (uint32 i; i < nodeOperatorIds.length; ++i) {
      uint32 nodeOperatorId = nodeOperatorIds[i];
      delete s_nodeOperators[nodeOperatorId];
      emit NodeOperatorRemoved(nodeOperatorId);
    }
  }

  /// @notice Updates a node operator
  /// @param nodeOperatorIds The ID of the node operator being updated
  /// @param nodeOperators The updated node operator params
  function updateNodeOperators(uint32[] calldata nodeOperatorIds, NodeOperator[] calldata nodeOperators) external {
    if (nodeOperatorIds.length != nodeOperators.length)
      revert LengthMismatch(nodeOperatorIds.length, nodeOperators.length);

    address owner = owner();
    for (uint256 i; i < nodeOperatorIds.length; ++i) {
      uint32 nodeOperatorId = nodeOperatorIds[i];

      NodeOperator storage currentNodeOperator = s_nodeOperators[nodeOperatorId];
      if (currentNodeOperator.admin == address(0)) revert NodeOperatorDoesNotExist(nodeOperatorId);

      NodeOperator memory nodeOperator = nodeOperators[i];
      if (nodeOperator.admin == address(0)) revert InvalidNodeOperatorAdmin();
      if (msg.sender != currentNodeOperator.admin && msg.sender != owner) revert AccessForbidden(msg.sender);

      if (
        currentNodeOperator.admin != nodeOperator.admin ||
        keccak256(abi.encode(currentNodeOperator.name)) != keccak256(abi.encode(nodeOperator.name))
      ) {
        currentNodeOperator.admin = nodeOperator.admin;
        currentNodeOperator.name = nodeOperator.name;
        emit NodeOperatorUpdated(nodeOperatorId, nodeOperator.admin, nodeOperator.name);
      }
    }
  }

  /// @notice Gets a node operator's data
  /// @param nodeOperatorId The ID of the node operator to query for
  /// @return NodeOperator The node operator data
  function getNodeOperator(uint32 nodeOperatorId) external view returns (NodeOperator memory) {
    return s_nodeOperators[nodeOperatorId];
  }

  /// @notice Gets all node operators
  /// @return NodeOperator[] All node operators
  function getNodeOperators() external view returns (NodeOperator[] memory) {
    uint32 nodeOperatorId = s_nextNodeOperatorId;
    /// Minus one to account for s_nextNodeOperatorId starting at index 1
    NodeOperator[] memory nodeOperators = new NodeOperator[](s_nextNodeOperatorId - 1);
    uint256 idx;
    for (uint32 i = 1; i < nodeOperatorId; ++i) {
      if (s_nodeOperators[i].admin != address(0)) {
        nodeOperators[idx] = s_nodeOperators[i];
        ++idx;
      }
    }
    if (idx != s_nextNodeOperatorId - 1) {
      assembly {
        mstore(nodeOperators, idx)
      }
    }
    return nodeOperators;
  }

  /// @notice Gets the next node DON ID
  /// @return uint32 The next node DON ID
  function getNextDONId() external view returns (uint32) {
    return s_nextDONId;
  }

  /// @notice Adds nodes. Nodes can be added with deprecated capabilities to
  /// avoid breaking changes when deprecating capabilities.
  /// @param nodes The nodes to add
  function addNodes(NodeParams[] calldata nodes) external {
    bool isOwner = msg.sender == owner();
    for (uint256 i; i < nodes.length; ++i) {
      NodeParams memory node = nodes[i];

      NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId];
      if (nodeOperator.admin == address(0)) revert NodeOperatorDoesNotExist(node.nodeOperatorId);
      if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(msg.sender);

      Node storage storedNode = s_nodes[node.p2pId];
      if (storedNode.signer != bytes32("")) revert NodeAlreadyExists(node.p2pId);
      if (node.p2pId == bytes32("")) revert InvalidNodeP2PId(node.p2pId);

      if (node.signer == bytes32("") || s_nodeSigners.contains(node.signer)) revert InvalidNodeSigner();

      if (node.encryptionPublicKey == bytes32("")) revert InvalidNodeEncryptionPublicKey(node.encryptionPublicKey);

      bytes32[] memory capabilityIds = node.hashedCapabilityIds;
      if (capabilityIds.length == 0) revert InvalidNodeCapabilities(capabilityIds);

      ++storedNode.configCount;

      uint32 capabilityConfigCount = storedNode.configCount;
      for (uint256 j; j < capabilityIds.length; ++j) {
        if (!s_hashedCapabilityIds.contains(capabilityIds[j])) revert InvalidNodeCapabilities(capabilityIds);
        storedNode.supportedHashedCapabilityIds[capabilityConfigCount].add(capabilityIds[j]);
      }

      storedNode.encryptionPublicKey = node.encryptionPublicKey;
      storedNode.nodeOperatorId = node.nodeOperatorId;
      storedNode.p2pId = node.p2pId;
      storedNode.signer = node.signer;
      s_nodeSigners.add(node.signer);
      s_nodeP2PIds.add(node.p2pId);
      emit NodeAdded(node.p2pId, node.nodeOperatorId, node.signer);
    }
  }

  /// @notice Removes nodes.  The node operator admin or contract owner
  /// can remove nodes
  /// @param removedNodeP2PIds The P2P Ids of the nodes to remove
  function removeNodes(bytes32[] calldata removedNodeP2PIds) external {
    bool isOwner = msg.sender == owner();
    for (uint256 i; i < removedNodeP2PIds.length; ++i) {
      bytes32 p2pId = removedNodeP2PIds[i];

      Node storage node = s_nodes[p2pId];

      if (node.signer == bytes32("")) revert NodeDoesNotExist(p2pId);
      if (node.capabilitiesDONIds.length() > 0)
        revert NodePartOfCapabilitiesDON(uint32(node.capabilitiesDONIds.at(i)), p2pId);
      if (node.workflowDONId != 0) revert NodePartOfWorkflowDON(node.workflowDONId, p2pId);

      if (!isOwner && msg.sender != s_nodeOperators[node.nodeOperatorId].admin) revert AccessForbidden(msg.sender);
      s_nodeSigners.remove(node.signer);
      s_nodeP2PIds.remove(node.p2pId);
      delete s_nodes[p2pId];
      emit NodeRemoved(p2pId);
    }
  }

  /// @notice Updates nodes.  The node admin can update the node's signer address
  /// and reconfigure its supported capabilities
  /// @param nodes The nodes to update
  function updateNodes(NodeParams[] calldata nodes) external {
    bool isOwner = msg.sender == owner();
    for (uint256 i; i < nodes.length; ++i) {
      NodeParams memory node = nodes[i];
      Node storage storedNode = s_nodes[node.p2pId];
      NodeOperator memory nodeOperator = s_nodeOperators[storedNode.nodeOperatorId];

      if (storedNode.signer == bytes32("")) revert NodeDoesNotExist(node.p2pId);
      if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(msg.sender);

      if (node.signer == bytes32("")) revert InvalidNodeSigner();

      bytes32 previousSigner = storedNode.signer;
      if (previousSigner != node.signer) {
        if (s_nodeSigners.contains(node.signer)) revert InvalidNodeSigner();
        storedNode.signer = node.signer;
        s_nodeSigners.remove(previousSigner);
        s_nodeSigners.add(node.signer);
      }

      if (node.encryptionPublicKey == bytes32("")) revert InvalidNodeEncryptionPublicKey(node.encryptionPublicKey);

      bytes32[] memory supportedHashedCapabilityIds = node.hashedCapabilityIds;
      if (supportedHashedCapabilityIds.length == 0) revert InvalidNodeCapabilities(supportedHashedCapabilityIds);

      uint32 capabilityConfigCount = ++storedNode.configCount;
      for (uint256 j; j < supportedHashedCapabilityIds.length; ++j) {
        if (!s_hashedCapabilityIds.contains(supportedHashedCapabilityIds[j]))
          revert InvalidNodeCapabilities(supportedHashedCapabilityIds);
        storedNode.supportedHashedCapabilityIds[capabilityConfigCount].add(supportedHashedCapabilityIds[j]);
      }

      // Validate that capabilities required by a Workflow DON are still supported
      uint32 nodeWorkflowDONId = storedNode.workflowDONId;
      if (nodeWorkflowDONId != 0) {
        bytes32[] memory workflowDonCapabilityIds = s_dons[nodeWorkflowDONId]
          .config[s_dons[nodeWorkflowDONId].configCount]
          .capabilityIds;

        for (uint256 j; j < workflowDonCapabilityIds.length; ++j) {
          if (!storedNode.supportedHashedCapabilityIds[capabilityConfigCount].contains(workflowDonCapabilityIds[j]))
            revert CapabilityRequiredByDON(workflowDonCapabilityIds[j], nodeWorkflowDONId);
        }
      }

      // Validate that capabilities required by capabilities DONs are still supported
      uint256[] memory capabilitiesDONIds = storedNode.capabilitiesDONIds.values();
      for (uint32 j; j < capabilitiesDONIds.length; ++j) {
        uint32 donId = uint32(capabilitiesDONIds[j]);
        bytes32[] memory donCapabilityIds = s_dons[donId].config[s_dons[donId].configCount].capabilityIds;

        for (uint256 k; k < donCapabilityIds.length; ++k) {
          if (!storedNode.supportedHashedCapabilityIds[capabilityConfigCount].contains(donCapabilityIds[k]))
            revert CapabilityRequiredByDON(donCapabilityIds[k], donId);
        }
      }

      storedNode.nodeOperatorId = node.nodeOperatorId;
      storedNode.p2pId = node.p2pId;
      storedNode.encryptionPublicKey = node.encryptionPublicKey;

      emit NodeUpdated(node.p2pId, node.nodeOperatorId, node.signer);
    }
  }

  /// @notice Gets a node's data
  /// @param p2pId The P2P ID of the node to query for
  /// @return nodeInfo NodeInfo The node data
  function getNode(bytes32 p2pId) public view returns (NodeInfo memory nodeInfo) {
    return (
      NodeInfo({
        nodeOperatorId: s_nodes[p2pId].nodeOperatorId,
        p2pId: s_nodes[p2pId].p2pId,
        signer: s_nodes[p2pId].signer,
        encryptionPublicKey: s_nodes[p2pId].encryptionPublicKey,
        hashedCapabilityIds: s_nodes[p2pId].supportedHashedCapabilityIds[s_nodes[p2pId].configCount].values(),
        configCount: s_nodes[p2pId].configCount,
        workflowDONId: s_nodes[p2pId].workflowDONId,
        capabilitiesDONIds: s_nodes[p2pId].capabilitiesDONIds.values()
      })
    );
  }

  /// @notice Gets all nodes
  /// @return NodeInfo[] All nodes in the capability registry
  function getNodes() external view returns (NodeInfo[] memory) {
    bytes32[] memory p2pIds = s_nodeP2PIds.values();
    NodeInfo[] memory nodesInfo = new NodeInfo[](p2pIds.length);

    for (uint256 i; i < p2pIds.length; ++i) {
      nodesInfo[i] = getNode(p2pIds[i]);
    }
    return nodesInfo;
  }

  /// @notice Gets nodes by their P2P IDs
  /// @param p2pIds The P2P IDs of the nodes to query for
  /// @return NodeInfo[] The nodes data
  function getNodesByP2PIds(bytes32[] calldata p2pIds) external view returns (NodeInfo[] memory) {
    NodeInfo[] memory nodesInfo = new NodeInfo[](p2pIds.length);

    for (uint256 i; i < p2pIds.length; ++i) {
      nodesInfo[i] = getNode(p2pIds[i]);
      if (nodesInfo[i].p2pId == bytes32("")) revert NodeDoesNotExist(p2pIds[i]);
    }
    return nodesInfo;
  }

  /// @notice Adds a new capability to the capability registry
  /// @param capabilities The capabilities being added
  /// @dev There is no function to update capabilities as this would require
  /// nodes to trust that the capabilities they support are not updated by the
  /// admin
  function addCapabilities(Capability[] calldata capabilities) external onlyOwner {
    for (uint256 i; i < capabilities.length; ++i) {
      Capability memory capability = capabilities[i];
      bytes32 hashedCapabilityId = getHashedCapabilityId(capability.labelledName, capability.version);
      if (!s_hashedCapabilityIds.add(hashedCapabilityId)) revert CapabilityAlreadyExists(hashedCapabilityId);
      _setCapability(hashedCapabilityId, capability);
    }
  }

  /// @notice Deprecates a capability
  /// @param hashedCapabilityIds[] The IDs of the capabilities to deprecate
  function deprecateCapabilities(bytes32[] calldata hashedCapabilityIds) external onlyOwner {
    for (uint256 i; i < hashedCapabilityIds.length; ++i) {
      bytes32 hashedCapabilityId = hashedCapabilityIds[i];
      if (!s_hashedCapabilityIds.contains(hashedCapabilityId)) revert CapabilityDoesNotExist(hashedCapabilityId);
      if (!s_deprecatedHashedCapabilityIds.add(hashedCapabilityId)) revert CapabilityIsDeprecated(hashedCapabilityId);

      emit CapabilityDeprecated(hashedCapabilityId);
    }
  }

  /// @notice Returns a Capability by its hashed ID.
  /// @dev Use `getHashedCapabilityId` to get the hashed ID.
  function getCapability(bytes32 hashedId) public view returns (CapabilityInfo memory) {
    return (
      CapabilityInfo({
        hashedId: hashedId,
        labelledName: s_capabilities[hashedId].labelledName,
        version: s_capabilities[hashedId].version,
        capabilityType: s_capabilities[hashedId].capabilityType,
        responseType: s_capabilities[hashedId].responseType,
        configurationContract: s_capabilities[hashedId].configurationContract,
        isDeprecated: s_deprecatedHashedCapabilityIds.contains(hashedId)
      })
    );
  }

  /// @notice Returns all capabilities. This operation will copy capabilities
  /// to memory, which can be quite expensive. This is designed to mostly be
  /// used by view accessors that are queried without any gas fees.
  /// @return CapabilityInfo[] List of capabilities
  function getCapabilities() external view returns (CapabilityInfo[] memory) {
    bytes32[] memory hashedCapabilityIds = s_hashedCapabilityIds.values();
    CapabilityInfo[] memory capabilitiesInfo = new CapabilityInfo[](hashedCapabilityIds.length);

    for (uint256 i; i < hashedCapabilityIds.length; ++i) {
      capabilitiesInfo[i] = getCapability(hashedCapabilityIds[i]);
    }
    return capabilitiesInfo;
  }

  /// @notice This functions returns a capability id that has been hashed to fit into a bytes32 for cheaper access
  /// @param labelledName The name of the capability
  /// @param version The capability's version number
  /// @return bytes32 A unique identifier for the capability
  /// @dev The hash of the encoded labelledName and version
  function getHashedCapabilityId(string memory labelledName, string memory version) public pure returns (bytes32) {
    return keccak256(abi.encode(labelledName, version));
  }

  /// @notice Returns whether a capability is deprecated
  /// @param hashedCapabilityId The hashed ID of the capability to check
  /// @return bool True if the capability is deprecated, false otherwise
  function isCapabilityDeprecated(bytes32 hashedCapabilityId) external view returns (bool) {
    return s_deprecatedHashedCapabilityIds.contains(hashedCapabilityId);
  }

  /// @notice Adds a DON made up by a group of nodes that support a list
  /// of capability configurations
  /// @param nodes The nodes making up the DON
  /// @param capabilityConfigurations The list of configurations for the
  /// capabilities supported by the DON
  /// @param isPublic True if the DON is can accept external capability requests
  /// @param acceptsWorkflows True if the DON can accept workflows
  /// @param f The maximum number of faulty nodes the DON can tolerate
  function addDON(
    bytes32[] calldata nodes,
    CapabilityConfiguration[] calldata capabilityConfigurations,
    bool isPublic,
    bool acceptsWorkflows,
    uint8 f
  ) external onlyOwner {
    uint32 id = s_nextDONId++;
    s_dons[id].id = id;

    _setDONConfig(
      nodes,
      capabilityConfigurations,
      DONParams({id: id, configCount: 1, isPublic: isPublic, acceptsWorkflows: acceptsWorkflows, f: f})
    );
  }

  /// @notice Updates a DON's configuration.  This allows
  /// the admin to reconfigure the list of capabilities supported
  /// by the DON, the list of nodes that make up the DON as well
  /// as whether or not the DON can accept external workflows
  /// @param donId The ID of the DON to update
  /// @param nodes The nodes making up the DON
  /// @param capabilityConfigurations The list of configurations for the
  /// capabilities supported by the DON
  /// @param isPublic True if the DON is can accept external capability requests
  /// @param f The maximum number of nodes that can fail
  function updateDON(
    uint32 donId,
    bytes32[] calldata nodes,
    CapabilityConfiguration[] calldata capabilityConfigurations,
    bool isPublic,
    uint8 f
  ) external onlyOwner {
    DON storage don = s_dons[donId];
    uint32 configCount = don.configCount;
    if (configCount == 0) revert DONDoesNotExist(donId);
    _setDONConfig(
      nodes,
      capabilityConfigurations,
      DONParams({
        id: donId,
        configCount: ++configCount,
        isPublic: isPublic,
        acceptsWorkflows: don.acceptsWorkflows,
        f: f
      })
    );
  }

  /// @notice Removes DONs from the Capability Registry
  /// @param donIds The IDs of the DON to be removed
  function removeDONs(uint32[] calldata donIds) external onlyOwner {
    for (uint256 i; i < donIds.length; ++i) {
      uint32 donId = donIds[i];
      DON storage don = s_dons[donId];

      uint32 configCount = don.configCount;
      EnumerableSet.Bytes32Set storage nodeP2PIds = don.config[configCount].nodes;

      bool isWorkflowDON = don.acceptsWorkflows;
      for (uint256 j; j < nodeP2PIds.length(); ++j) {
        if (isWorkflowDON) {
          delete s_nodes[nodeP2PIds.at(j)].workflowDONId;
        } else {
          s_nodes[nodeP2PIds.at(j)].capabilitiesDONIds.remove(donId);
        }
      }

      // DON config count starts at index 1
      if (don.configCount == 0) revert DONDoesNotExist(donId);
      delete s_dons[donId];
      emit ConfigSet(donId, 0);
    }
  }

  /// @notice Gets DON's data
  /// @param donId The DON ID
  /// @return DONInfo The DON's parameters
  function getDON(uint32 donId) external view returns (DONInfo memory) {
    return _getDON(donId);
  }

  /// @notice Returns the list of configured DONs
  /// @return DONInfo[] The list of configured DONs
  function getDONs() external view returns (DONInfo[] memory) {
    /// Minus one to account for s_nextDONId starting at index 1
    uint32 donId = s_nextDONId;
    DONInfo[] memory dons = new DONInfo[](donId - 1);
    uint256 idx;
    ///
    for (uint32 i = 1; i < donId; ++i) {
      if (s_dons[i].id != 0) {
        dons[idx] = _getDON(i);
        ++idx;
      }
    }
    if (idx != donId - 1) {
      assembly {
        mstore(dons, idx)
      }
    }
    return dons;
  }

  /// @notice Returns the DON specific configuration for a capability
  /// @param donId The DON's ID
  /// @param capabilityId The Capability ID
  /// @return bytes The DON specific configuration for the capability stored on the capability registry
  /// @return bytes The DON specific configuration stored on the capability's configuration contract
  function getCapabilityConfigs(uint32 donId, bytes32 capabilityId) external view returns (bytes memory, bytes memory) {
    uint32 configCount = s_dons[donId].configCount;

    bytes memory donCapabilityConfig = s_dons[donId].config[configCount].capabilityConfigs[capabilityId];
    bytes memory globalCapabilityConfig;

    if (s_capabilities[capabilityId].configurationContract != address(0)) {
      globalCapabilityConfig = ICapabilityConfiguration(s_capabilities[capabilityId].configurationContract)
        .getCapabilityConfiguration(donId);
    }

    return (donCapabilityConfig, globalCapabilityConfig);
  }

  /// @notice Sets the configuration for a DON
  /// @param nodes The nodes making up the DON
  /// @param capabilityConfigurations The list of configurations for the capabilities supported by the DON
  /// @param donParams The DON's parameters
  function _setDONConfig(
    bytes32[] calldata nodes,
    CapabilityConfiguration[] calldata capabilityConfigurations,
    DONParams memory donParams
  ) internal {
    DONCapabilityConfig storage donCapabilityConfig = s_dons[donParams.id].config[donParams.configCount];

    // Validate the f value. We are intentionally relaxing the 3f+1 requirement
    // as not all DONs will run OCR instances.
    if (donParams.f == 0 || donParams.f + 1 > nodes.length) revert InvalidFaultTolerance(donParams.f, nodes.length);

    // Skip removing supported DON Ids from previously configured nodes in DON if
    // we are adding the DON for the first time
    if (donParams.configCount > 1) {
      DONCapabilityConfig storage prevDONCapabilityConfig = s_dons[donParams.id].config[donParams.configCount - 1];

      // We acknowledge that this may result in an out of gas error if the number of configured
      // nodes is large.  This is mitigated by ensuring that there will not be a large number
      // of nodes configured to a DON.
      // We also do not remove the nodes from the previous DON capability config.  This is not
      // needed as the previous config will be overwritten by storing the latest config
      // at configCount
      for (uint256 i; i < prevDONCapabilityConfig.nodes.length(); ++i) {
        s_nodes[prevDONCapabilityConfig.nodes.at(i)].capabilitiesDONIds.remove(donParams.id);
        delete s_nodes[prevDONCapabilityConfig.nodes.at(i)].workflowDONId;
      }
    }

    for (uint256 i; i < nodes.length; ++i) {
      if (!donCapabilityConfig.nodes.add(nodes[i])) revert DuplicateDONNode(donParams.id, nodes[i]);

      if (donParams.acceptsWorkflows) {
        if (s_nodes[nodes[i]].workflowDONId != donParams.id && s_nodes[nodes[i]].workflowDONId != 0)
          revert NodePartOfWorkflowDON(donParams.id, nodes[i]);
        s_nodes[nodes[i]].workflowDONId = donParams.id;
      } else {
        /// Fine to add a duplicate DON ID to the set of supported DON IDs again as the set
        /// will only store unique DON IDs
        s_nodes[nodes[i]].capabilitiesDONIds.add(donParams.id);
      }
    }

    for (uint256 i; i < capabilityConfigurations.length; ++i) {
      CapabilityConfiguration calldata configuration = capabilityConfigurations[i];

      if (!s_hashedCapabilityIds.contains(configuration.capabilityId))
        revert CapabilityDoesNotExist(configuration.capabilityId);
      if (s_deprecatedHashedCapabilityIds.contains(configuration.capabilityId))
        revert CapabilityIsDeprecated(configuration.capabilityId);

      if (donCapabilityConfig.capabilityConfigs[configuration.capabilityId].length > 0)
        revert DuplicateDONCapability(donParams.id, configuration.capabilityId);

      for (uint256 j; j < nodes.length; ++j) {
        if (
          !s_nodes[nodes[j]].supportedHashedCapabilityIds[s_nodes[nodes[j]].configCount].contains(
            configuration.capabilityId
          )
        ) revert NodeDoesNotSupportCapability(nodes[j], configuration.capabilityId);
      }

      donCapabilityConfig.capabilityIds.push(configuration.capabilityId);
      donCapabilityConfig.capabilityConfigs[configuration.capabilityId] = configuration.config;

      s_dons[donParams.id].isPublic = donParams.isPublic;
      s_dons[donParams.id].acceptsWorkflows = donParams.acceptsWorkflows;
      s_dons[donParams.id].f = donParams.f;
      s_dons[donParams.id].configCount = donParams.configCount;

      _setDONCapabilityConfig(
        donParams.id,
        donParams.configCount,
        configuration.capabilityId,
        nodes,
        configuration.config
      );
    }
    emit ConfigSet(donParams.id, donParams.configCount);
  }

  /// @notice Sets the capability's config on the config contract
  /// @param donId The ID of the DON the capability is being configured for
  /// @param configCount The number of times the DON has been configured
  /// @param capabilityId The capability's ID
  /// @param nodes The nodes in the DON
  /// @param config The DON's capability config
  /// @dev Helper function used to resolve stack too deep errors in _setDONConfig
  function _setDONCapabilityConfig(
    uint32 donId,
    uint32 configCount,
    bytes32 capabilityId,
    bytes32[] calldata nodes,
    bytes memory config
  ) internal {
    if (s_capabilities[capabilityId].configurationContract != address(0)) {
      ICapabilityConfiguration(s_capabilities[capabilityId].configurationContract).beforeCapabilityConfigSet(
        nodes,
        config,
        configCount,
        donId
      );
    }
  }

  /// @notice Sets a capability's data
  /// @param hashedCapabilityId The ID of the capability being set
  /// @param capability The capability's data
  function _setCapability(bytes32 hashedCapabilityId, Capability memory capability) internal {
    if (capability.configurationContract != address(0)) {
      /// Check that the configuration contract being assigned
      /// correctly supports the ICapabilityConfiguration interface
      /// by implementing both getCapabilityConfiguration and
      /// beforeCapabilityConfigSet
      if (
        !ERC165Checker.supportsInterface(capability.configurationContract, type(ICapabilityConfiguration).interfaceId)
      ) revert InvalidCapabilityConfigurationContractInterface(capability.configurationContract);
    }
    s_capabilities[hashedCapabilityId] = capability;
    emit CapabilityConfigured(hashedCapabilityId);
  }

  /// @notice Gets DON's data
  /// @param donId The DON ID
  /// @return DONInfo The DON's parameters
  function _getDON(uint32 donId) internal view returns (DONInfo memory) {
    uint32 configCount = s_dons[donId].configCount;

    DONCapabilityConfig storage donCapabilityConfig = s_dons[donId].config[configCount];

    bytes32[] memory capabilityIds = donCapabilityConfig.capabilityIds;
    CapabilityConfiguration[] memory capabilityConfigurations = new CapabilityConfiguration[](capabilityIds.length);

    for (uint256 i; i < capabilityConfigurations.length; ++i) {
      capabilityConfigurations[i] = CapabilityConfiguration({
        capabilityId: capabilityIds[i],
        config: donCapabilityConfig.capabilityConfigs[capabilityIds[i]]
      });
    }

    return
      DONInfo({
        id: s_dons[donId].id,
        configCount: configCount,
        f: s_dons[donId].f,
        isPublic: s_dons[donId].isPublic,
        acceptsWorkflows: s_dons[donId].acceptsWorkflows,
        nodeP2PIds: donCapabilityConfig.nodes.values(),
        capabilityConfigurations: capabilityConfigurations
      });
  }
}

File 2 of 11 : ITypeAndVersion.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface ITypeAndVersion {
  function typeAndVersion() external pure returns (string memory);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @notice Interface for capability configuration contract. It MUST be
/// implemented for a contract to be used as a capability configuration.
/// The contract MAY store configuration that is shared across multiple
/// DON instances and capability versions.
/// @dev This interface does not guarantee the configuration contract's
/// correctness. It is the responsibility of the contract owner to ensure
/// that the configuration contract emits the CapabilityConfigurationSet
/// event when the configuration is set.
interface ICapabilityConfiguration {
  /// @notice Emitted when a capability configuration is set.
  event CapabilityConfigurationSet();

  /// @notice Returns the capability configuration for a particular DON instance.
  /// @dev donId is required to get DON-specific configuration. It avoids a
  /// situation where configuration size grows too large.
  /// @param donId The DON instance ID. These are stored in the CapabilitiesRegistry.
  /// @return configuration DON's configuration for the capability.
  function getCapabilityConfiguration(uint32 donId) external view returns (bytes memory configuration);

  /// @notice Called by the registry prior to the config being set for a particular DON.
  /// @param nodes The nodes that the configuration is being set for.
  /// @param donCapabilityConfig The configuration being set on the capability registry.
  /// @param donCapabilityConfigCount The number of times the DON has been configured, tracked on the capability registry.
  /// @param donId The DON ID on the capability registry.
  function beforeCapabilityConfigSet(
    bytes32[] calldata nodes,
    bytes calldata donCapabilityConfig,
    uint64 donCapabilityConfigCount,
    uint32 donId
  ) external;
}

File 4 of 11 : OwnerIsCreator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

/// @title The OwnerIsCreator contract
/// @notice A contract with helpers for basic contract ownership.
contract OwnerIsCreator is ConfirmedOwner {
  constructor() ConfirmedOwner(msg.sender) {}
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.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.
 *
 * ```
 * 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;
  }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.2) (utils/introspection/ERC165Checker.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Library used to query support of an interface declared via {IERC165}.
 *
 * Note that these functions return the actual result of the query: they do not
 * `revert` if an interface is not supported. It is up to the caller to decide
 * what to do in these cases.
 */
library ERC165Checker {
    // As per the EIP-165 spec, no interface should ever match 0xffffffff
    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;

    /**
     * @dev Returns true if `account` supports the {IERC165} interface.
     */
    function supportsERC165(address account) internal view returns (bool) {
        // Any contract that implements ERC165 must explicitly indicate support of
        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
        return
            supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&
            !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);
    }

    /**
     * @dev Returns true if `account` supports the interface defined by
     * `interfaceId`. Support for {IERC165} itself is queried automatically.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
        // query support of both ERC165 as per the spec and support of _interfaceId
        return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);
    }

    /**
     * @dev Returns a boolean array where each value corresponds to the
     * interfaces passed in and whether they're supported or not. This allows
     * you to batch check interfaces for a contract where your expectation
     * is that some interfaces may not be supported.
     *
     * See {IERC165-supportsInterface}.
     *
     * _Available since v3.4._
     */
    function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)
        internal
        view
        returns (bool[] memory)
    {
        // an array of booleans corresponding to interfaceIds and whether they're supported or not
        bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);

        // query support of ERC165 itself
        if (supportsERC165(account)) {
            // query support of each interface in interfaceIds
            for (uint256 i = 0; i < interfaceIds.length; i++) {
                interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);
            }
        }

        return interfaceIdsSupported;
    }

    /**
     * @dev Returns true if `account` supports all the interfaces defined in
     * `interfaceIds`. Support for {IERC165} itself is queried automatically.
     *
     * Batch-querying can lead to gas savings by skipping repeated checks for
     * {IERC165} support.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
        // query support of ERC165 itself
        if (!supportsERC165(account)) {
            return false;
        }

        // query support of each interface in interfaceIds
        for (uint256 i = 0; i < interfaceIds.length; i++) {
            if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {
                return false;
            }
        }

        // all interfaces supported
        return true;
    }

    /**
     * @notice Query if a contract implements an interface, does not check ERC165 support
     * @param account The address of the contract to query for support of an interface
     * @param interfaceId The interface identifier, as specified in ERC-165
     * @return true if the contract at account indicates support of the interface with
     * identifier interfaceId, false otherwise
     * @dev Assumes that account contains a contract that supports ERC165, otherwise
     * the behavior of this method is undefined. This precondition can be checked
     * with {supportsERC165}.
     *
     * Some precompiled contracts will falsely indicate support for a given interface, so caution
     * should be exercised when using this function.
     *
     * Interface identification is specified in ERC-165.
     */
    function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {
        // prepare call
        bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);

        // perform static call
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly {
            success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0x00)
        }

        return success && returnSize >= 0x20 && returnValue > 0;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @title INodeInfoProvider
/// @notice Interface for retrieving node information.
interface INodeInfoProvider {
  /// @notice This error is thrown when a node with the provided P2P ID is
  /// not found.
  /// @param nodeP2PId The node P2P ID used for the lookup.
  error NodeDoesNotExist(bytes32 nodeP2PId);

  struct NodeInfo {
    /// @notice The id of the node operator that manages this node
    uint32 nodeOperatorId;
    /// @notice The number of times the node's configuration has been updated
    uint32 configCount;
    /// @notice The ID of the Workflow DON that the node belongs to. A node can
    /// only belong to one DON that accepts Workflows.
    uint32 workflowDONId;
    /// @notice The signer address for application-layer message verification.
    bytes32 signer;
    /// @notice This is an Ed25519 public key that is used to identify a node.
    /// This key is guaranteed to be unique in the CapabilitiesRegistry. It is
    /// used to identify a node in the the P2P network.
    bytes32 p2pId;
    /// @notice Public key used to encrypt secrets for this node
    bytes32 encryptionPublicKey;
    /// @notice The list of hashed capability IDs supported by the node
    bytes32[] hashedCapabilityIds;
    /// @notice The list of capabilities DON Ids supported by the node. A node
    /// can belong to multiple capabilities DONs. This list does not include a
    /// Workflow DON id if the node belongs to one.
    uint256[] capabilitiesDONIds;
  }

  /// @notice Retrieves node information by its P2P ID.
  /// @param p2pId The P2P ID of the node to query for.
  /// @return nodeInfo The node data.
  function getNode(bytes32 p2pId) external view returns (NodeInfo memory nodeInfo);

  /// @notice Retrieves all node information.
  /// @return NodeInfo[] Array of all nodes in the registry.
  function getNodes() external view returns (NodeInfo[] memory);

  /// @notice Retrieves nodes by their P2P IDs.
  /// @param p2pIds Array of P2P IDs to query for.
  /// @return NodeInfo[] Array of node data corresponding to the provided P2P IDs.
  function getNodesByP2PIds(bytes32[] calldata p2pIds) external view returns (NodeInfo[] memory);
}

File 8 of 11 : ConfirmedOwner.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

/// @title The ConfirmedOwner contract
/// @notice A contract with helpers for basic contract ownership.
contract ConfirmedOwner is ConfirmedOwnerWithProposal {
  constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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 IERC165 {
    /**
     * @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);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

/// @title The ConfirmedOwner contract
/// @notice A contract with helpers for basic contract ownership.
contract ConfirmedOwnerWithProposal is IOwnable {
  address private s_owner;
  address private s_pendingOwner;

  event OwnershipTransferRequested(address indexed from, address indexed to);
  event OwnershipTransferred(address indexed from, address indexed to);

  constructor(address newOwner, address pendingOwner) {
    // solhint-disable-next-line gas-custom-errors
    require(newOwner != address(0), "Cannot set owner to zero");

    s_owner = newOwner;
    if (pendingOwner != address(0)) {
      _transferOwnership(pendingOwner);
    }
  }

  /// @notice Allows an owner to begin transferring ownership to a new address.
  function transferOwnership(address to) public override onlyOwner {
    _transferOwnership(to);
  }

  /// @notice Allows an ownership transfer to be completed by the recipient.
  function acceptOwnership() external override {
    // solhint-disable-next-line gas-custom-errors
    require(msg.sender == s_pendingOwner, "Must be proposed owner");

    address oldOwner = s_owner;
    s_owner = msg.sender;
    s_pendingOwner = address(0);

    emit OwnershipTransferred(oldOwner, msg.sender);
  }

  /// @notice Get the current owner
  function owner() public view override returns (address) {
    return s_owner;
  }

  /// @notice validate, transfer ownership, and emit relevant events
  function _transferOwnership(address to) private {
    // solhint-disable-next-line gas-custom-errors
    require(to != msg.sender, "Cannot transfer to self");

    s_pendingOwner = to;

    emit OwnershipTransferRequested(s_owner, to);
  }

  /// @notice validate access
  function _validateOwnership() internal view {
    // solhint-disable-next-line gas-custom-errors
    require(msg.sender == s_owner, "Only callable by owner");
  }

  /// @notice Reverts if called by anyone other than the contract owner.
  modifier onlyOwner() {
    _validateOwnership();
    _;
  }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IOwnable {
  function owner() external returns (address);

  function transferOwnership(address recipient) external;

  function acceptOwnership() external;
}

Settings
{
  "remappings": [
    "forge-std/=src/v0.8/vendor/forge-std/src/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@arbitrum/=node_modules/@arbitrum/",
    "hardhat/=node_modules/hardhat/",
    "@eth-optimism/=node_modules/@eth-optimism/",
    "@scroll-tech/=node_modules/@scroll-tech/",
    "@zksync/=node_modules/@zksync/",
    "@offchainlabs/=node_modules/@offchainlabs/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"AccessForbidden","type":"error"},{"inputs":[{"internalType":"bytes32","name":"hashedCapabilityId","type":"bytes32"}],"name":"CapabilityAlreadyExists","type":"error"},{"inputs":[{"internalType":"bytes32","name":"hashedCapabilityId","type":"bytes32"}],"name":"CapabilityDoesNotExist","type":"error"},{"inputs":[{"internalType":"bytes32","name":"hashedCapabilityId","type":"bytes32"}],"name":"CapabilityIsDeprecated","type":"error"},{"inputs":[{"internalType":"bytes32","name":"hashedCapabilityId","type":"bytes32"},{"internalType":"uint32","name":"donId","type":"uint32"}],"name":"CapabilityRequiredByDON","type":"error"},{"inputs":[{"internalType":"uint32","name":"donId","type":"uint32"}],"name":"DONDoesNotExist","type":"error"},{"inputs":[{"internalType":"uint32","name":"donId","type":"uint32"},{"internalType":"bytes32","name":"capabilityId","type":"bytes32"}],"name":"DuplicateDONCapability","type":"error"},{"inputs":[{"internalType":"uint32","name":"donId","type":"uint32"},{"internalType":"bytes32","name":"nodeP2PId","type":"bytes32"}],"name":"DuplicateDONNode","type":"error"},{"inputs":[{"internalType":"address","name":"proposedConfigurationContract","type":"address"}],"name":"InvalidCapabilityConfigurationContractInterface","type":"error"},{"inputs":[{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"uint256","name":"nodeCount","type":"uint256"}],"name":"InvalidFaultTolerance","type":"error"},{"inputs":[{"internalType":"bytes32[]","name":"hashedCapabilityIds","type":"bytes32[]"}],"name":"InvalidNodeCapabilities","type":"error"},{"inputs":[{"internalType":"bytes32","name":"encryptionPublicKey","type":"bytes32"}],"name":"InvalidNodeEncryptionPublicKey","type":"error"},{"inputs":[],"name":"InvalidNodeOperatorAdmin","type":"error"},{"inputs":[{"internalType":"bytes32","name":"p2pId","type":"bytes32"}],"name":"InvalidNodeP2PId","type":"error"},{"inputs":[],"name":"InvalidNodeSigner","type":"error"},{"inputs":[{"internalType":"uint256","name":"lengthOne","type":"uint256"},{"internalType":"uint256","name":"lengthTwo","type":"uint256"}],"name":"LengthMismatch","type":"error"},{"inputs":[{"internalType":"bytes32","name":"nodeP2PId","type":"bytes32"}],"name":"NodeAlreadyExists","type":"error"},{"inputs":[{"internalType":"bytes32","name":"nodeP2PId","type":"bytes32"}],"name":"NodeDoesNotExist","type":"error"},{"inputs":[{"internalType":"bytes32","name":"nodeP2PId","type":"bytes32"},{"internalType":"bytes32","name":"capabilityId","type":"bytes32"}],"name":"NodeDoesNotSupportCapability","type":"error"},{"inputs":[{"internalType":"uint32","name":"nodeOperatorId","type":"uint32"}],"name":"NodeOperatorDoesNotExist","type":"error"},{"inputs":[{"internalType":"uint32","name":"donId","type":"uint32"},{"internalType":"bytes32","name":"nodeP2PId","type":"bytes32"}],"name":"NodePartOfCapabilitiesDON","type":"error"},{"inputs":[{"internalType":"uint32","name":"donId","type":"uint32"},{"internalType":"bytes32","name":"nodeP2PId","type":"bytes32"}],"name":"NodePartOfWorkflowDON","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"hashedCapabilityId","type":"bytes32"}],"name":"CapabilityConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"hashedCapabilityId","type":"bytes32"}],"name":"CapabilityDeprecated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"donId","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"configCount","type":"uint32"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"p2pId","type":"bytes32"},{"indexed":true,"internalType":"uint32","name":"nodeOperatorId","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"signer","type":"bytes32"}],"name":"NodeAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"nodeOperatorId","type":"uint32"},{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NodeOperatorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"nodeOperatorId","type":"uint32"}],"name":"NodeOperatorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"nodeOperatorId","type":"uint32"},{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NodeOperatorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"p2pId","type":"bytes32"}],"name":"NodeRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"p2pId","type":"bytes32"},{"indexed":true,"internalType":"uint32","name":"nodeOperatorId","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"signer","type":"bytes32"}],"name":"NodeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"labelledName","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"enum CapabilitiesRegistry.CapabilityType","name":"capabilityType","type":"uint8"},{"internalType":"enum CapabilitiesRegistry.CapabilityResponseType","name":"responseType","type":"uint8"},{"internalType":"address","name":"configurationContract","type":"address"}],"internalType":"struct CapabilitiesRegistry.Capability[]","name":"capabilities","type":"tuple[]"}],"name":"addCapabilities","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"nodes","type":"bytes32[]"},{"components":[{"internalType":"bytes32","name":"capabilityId","type":"bytes32"},{"internalType":"bytes","name":"config","type":"bytes"}],"internalType":"struct CapabilitiesRegistry.CapabilityConfiguration[]","name":"capabilityConfigurations","type":"tuple[]"},{"internalType":"bool","name":"isPublic","type":"bool"},{"internalType":"bool","name":"acceptsWorkflows","type":"bool"},{"internalType":"uint8","name":"f","type":"uint8"}],"name":"addDON","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct CapabilitiesRegistry.NodeOperator[]","name":"nodeOperators","type":"tuple[]"}],"name":"addNodeOperators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"nodeOperatorId","type":"uint32"},{"internalType":"bytes32","name":"signer","type":"bytes32"},{"internalType":"bytes32","name":"p2pId","type":"bytes32"},{"internalType":"bytes32","name":"encryptionPublicKey","type":"bytes32"},{"internalType":"bytes32[]","name":"hashedCapabilityIds","type":"bytes32[]"}],"internalType":"struct CapabilitiesRegistry.NodeParams[]","name":"nodes","type":"tuple[]"}],"name":"addNodes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"hashedCapabilityIds","type":"bytes32[]"}],"name":"deprecateCapabilities","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCapabilities","outputs":[{"components":[{"internalType":"bytes32","name":"hashedId","type":"bytes32"},{"internalType":"string","name":"labelledName","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"enum CapabilitiesRegistry.CapabilityType","name":"capabilityType","type":"uint8"},{"internalType":"enum CapabilitiesRegistry.CapabilityResponseType","name":"responseType","type":"uint8"},{"internalType":"address","name":"configurationContract","type":"address"},{"internalType":"bool","name":"isDeprecated","type":"bool"}],"internalType":"struct CapabilitiesRegistry.CapabilityInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hashedId","type":"bytes32"}],"name":"getCapability","outputs":[{"components":[{"internalType":"bytes32","name":"hashedId","type":"bytes32"},{"internalType":"string","name":"labelledName","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"enum CapabilitiesRegistry.CapabilityType","name":"capabilityType","type":"uint8"},{"internalType":"enum CapabilitiesRegistry.CapabilityResponseType","name":"responseType","type":"uint8"},{"internalType":"address","name":"configurationContract","type":"address"},{"internalType":"bool","name":"isDeprecated","type":"bool"}],"internalType":"struct CapabilitiesRegistry.CapabilityInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"donId","type":"uint32"},{"internalType":"bytes32","name":"capabilityId","type":"bytes32"}],"name":"getCapabilityConfigs","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"donId","type":"uint32"}],"name":"getDON","outputs":[{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"isPublic","type":"bool"},{"internalType":"bool","name":"acceptsWorkflows","type":"bool"},{"internalType":"bytes32[]","name":"nodeP2PIds","type":"bytes32[]"},{"components":[{"internalType":"bytes32","name":"capabilityId","type":"bytes32"},{"internalType":"bytes","name":"config","type":"bytes"}],"internalType":"struct CapabilitiesRegistry.CapabilityConfiguration[]","name":"capabilityConfigurations","type":"tuple[]"}],"internalType":"struct CapabilitiesRegistry.DONInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDONs","outputs":[{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"isPublic","type":"bool"},{"internalType":"bool","name":"acceptsWorkflows","type":"bool"},{"internalType":"bytes32[]","name":"nodeP2PIds","type":"bytes32[]"},{"components":[{"internalType":"bytes32","name":"capabilityId","type":"bytes32"},{"internalType":"bytes","name":"config","type":"bytes"}],"internalType":"struct CapabilitiesRegistry.CapabilityConfiguration[]","name":"capabilityConfigurations","type":"tuple[]"}],"internalType":"struct CapabilitiesRegistry.DONInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"labelledName","type":"string"},{"internalType":"string","name":"version","type":"string"}],"name":"getHashedCapabilityId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getNextDONId","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"p2pId","type":"bytes32"}],"name":"getNode","outputs":[{"components":[{"internalType":"uint32","name":"nodeOperatorId","type":"uint32"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"workflowDONId","type":"uint32"},{"internalType":"bytes32","name":"signer","type":"bytes32"},{"internalType":"bytes32","name":"p2pId","type":"bytes32"},{"internalType":"bytes32","name":"encryptionPublicKey","type":"bytes32"},{"internalType":"bytes32[]","name":"hashedCapabilityIds","type":"bytes32[]"},{"internalType":"uint256[]","name":"capabilitiesDONIds","type":"uint256[]"}],"internalType":"struct INodeInfoProvider.NodeInfo","name":"nodeInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"nodeOperatorId","type":"uint32"}],"name":"getNodeOperator","outputs":[{"components":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct CapabilitiesRegistry.NodeOperator","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNodeOperators","outputs":[{"components":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct CapabilitiesRegistry.NodeOperator[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNodes","outputs":[{"components":[{"internalType":"uint32","name":"nodeOperatorId","type":"uint32"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"workflowDONId","type":"uint32"},{"internalType":"bytes32","name":"signer","type":"bytes32"},{"internalType":"bytes32","name":"p2pId","type":"bytes32"},{"internalType":"bytes32","name":"encryptionPublicKey","type":"bytes32"},{"internalType":"bytes32[]","name":"hashedCapabilityIds","type":"bytes32[]"},{"internalType":"uint256[]","name":"capabilitiesDONIds","type":"uint256[]"}],"internalType":"struct INodeInfoProvider.NodeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"p2pIds","type":"bytes32[]"}],"name":"getNodesByP2PIds","outputs":[{"components":[{"internalType":"uint32","name":"nodeOperatorId","type":"uint32"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"workflowDONId","type":"uint32"},{"internalType":"bytes32","name":"signer","type":"bytes32"},{"internalType":"bytes32","name":"p2pId","type":"bytes32"},{"internalType":"bytes32","name":"encryptionPublicKey","type":"bytes32"},{"internalType":"bytes32[]","name":"hashedCapabilityIds","type":"bytes32[]"},{"internalType":"uint256[]","name":"capabilitiesDONIds","type":"uint256[]"}],"internalType":"struct INodeInfoProvider.NodeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hashedCapabilityId","type":"bytes32"}],"name":"isCapabilityDeprecated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"donIds","type":"uint32[]"}],"name":"removeDONs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"nodeOperatorIds","type":"uint32[]"}],"name":"removeNodeOperators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"removedNodeP2PIds","type":"bytes32[]"}],"name":"removeNodes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"donId","type":"uint32"},{"internalType":"bytes32[]","name":"nodes","type":"bytes32[]"},{"components":[{"internalType":"bytes32","name":"capabilityId","type":"bytes32"},{"internalType":"bytes","name":"config","type":"bytes"}],"internalType":"struct CapabilitiesRegistry.CapabilityConfiguration[]","name":"capabilityConfigurations","type":"tuple[]"},{"internalType":"bool","name":"isPublic","type":"bool"},{"internalType":"uint8","name":"f","type":"uint8"}],"name":"updateDON","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"nodeOperatorIds","type":"uint32[]"},{"components":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct CapabilitiesRegistry.NodeOperator[]","name":"nodeOperators","type":"tuple[]"}],"name":"updateNodeOperators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"nodeOperatorId","type":"uint32"},{"internalType":"bytes32","name":"signer","type":"bytes32"},{"internalType":"bytes32","name":"p2pId","type":"bytes32"},{"internalType":"bytes32","name":"encryptionPublicKey","type":"bytes32"},{"internalType":"bytes32[]","name":"hashedCapabilityIds","type":"bytes32[]"}],"internalType":"struct CapabilitiesRegistry.NodeParams[]","name":"nodes","type":"tuple[]"}],"name":"updateNodes","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052600e80546001600160401b03191664010000000117905534801562000027575f80fd5b5033805f816200007e5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b5f80546001600160a01b0319166001600160a01b0384811691909117909155811615620000b057620000b081620000b9565b50505062000163565b336001600160a01b03821603620001135760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000075565b600180546001600160a01b0319166001600160a01b038381169182179092555f8054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6151fc80620001715f395ff3fe608060405234801561000f575f80fd5b50600436106101bb575f3560e01c806350c946fe116100f35780638da5cb5b11610093578063ddbe4f821161006e578063ddbe4f8214610442578063e29581aa14610457578063f2fde38b1461045f578063fcdc8efe14610472575f80fd5b80638da5cb5b146103e85780639cb7c5f41461040f578063d8bc7b681461042f575f80fd5b8063715f5295116100ce578063715f5295146103a757806379ba5097146103ba57806384f5ed8a146103c257806386fa4246146103d5575f80fd5b806350c946fe1461035f5780635d83d9671461037f57806366acaa3314610392575f80fd5b8063235374051161015e5780632c01a1e8116101395780632c01a1e814610305578063358039f414610318578063398f37731461032b5780633f2a13c91461033e575f80fd5b806323537405146102bf578063275459f2146102df5780632a852933146102f2575f80fd5b8063181f5a7711610199578063181f5a771461022c5780631d05394c14610275578063214502431461028a57806322bdbcbc1461029f575f80fd5b806305a51966146101bf5780630fe5800a146101e85780631257001114610209575b5f80fd5b6101d26101cd366004613fb4565b610498565b6040516101df91906140ad565b60405180910390f35b6101fb6101f6366004614269565b61061d565b6040519081526020016101df565b61021c6102173660046142c9565b61064f565b60405190151581526020016101df565b6102686040518060400160405280601a81526020017f4361706162696c6974696573526567697374727920312e312e3000000000000081525081565b6040516101df919061434b565b610288610283366004613fb4565b61065b565b005b61029261085a565b6040516101df9190614455565b6102b26102ad3660046144e0565b6109b3565b6040516101df9190614535565b6102d26102cd3660046144e0565b610a9c565b6040516101df9190614547565b6102886102ed366004613fb4565b610adf565b610288610300366004614578565b610bb2565b610288610313366004613fb4565b610c91565b610288610326366004613fb4565b610f2e565b610288610339366004613fb4565b61168a565b61035161034c366004614613565b611844565b6040516101df92919061463b565b61037261036d3660046142c9565b611a27565b6040516101df919061465f565b61028861038d366004613fb4565b611b10565b61039a611c02565b6040516101df9190614671565b6102886103b5366004613fb4565b611dde565b610288611e8c565b6102886103d0366004613fb4565b611f88565b6102886103e33660046146e4565b612499565b5f5460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101df565b61042261041d3660046142c9565b6127d4565b6040516101df9190614823565b61028861043d366004614835565b612a02565b61044a612aca565b6040516101df91906148b4565b6101d2612bb8565b61028861046d36600461494a565b612cc5565b600e54640100000000900463ffffffff1660405163ffffffff90911681526020016101df565b60605f8267ffffffffffffffff8111156104b4576104b461412d565b60405190808252806020026020018201604052801561054257816020015b60408051610100810182525f808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816104d25790505b5090505f5b838110156106135761057085858381811061056457610564614963565b90506020020135611a27565b82828151811061058257610582614963565b60200260200101819052505f8019168282815181106105a3576105a3614963565b6020026020010151608001510361060b578484828181106105c6576105c6614963565b905060200201356040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b60405180910390fd5b600101610547565b5090505b92915050565b5f828260405160200161063192919061463b565b60405160208183030381529060405280519060200120905092915050565b5f610617600583612cd9565b610663612cf3565b5f5b81811015610855575f83838381811061068057610680614963565b905060200201602081019061069591906144e0565b63ffffffff8181165f908152600d60209081526040808320805464010000000081049095168085526001820190935290832094955093909290916a010000000000000000000090910460ff16905b6106ec83612d75565b81101561078857811561074057600c5f6107068584612d7e565b815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff169055610780565b61077e8663ffffffff16600c5f6107608588612d7e90919063ffffffff16565b81526020019081526020015f20600501612d8990919063ffffffff16565b505b6001016106e3565b508354640100000000900463ffffffff165f036107d9576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff86166004820152602401610602565b63ffffffff85165f818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffff0000000000000000000000169055519182527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a25050505050806001019050610665565b505050565b600e54606090640100000000900463ffffffff165f61087a6001836149bd565b63ffffffff1667ffffffffffffffff8111156108985761089861412d565b60405190808252806020026020018201604052801561091e57816020015b6040805160e0810182525f80825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816108b65790505b5090505f60015b8363ffffffff168163ffffffff1610156109905763ffffffff8082165f908152600d602052604090205416156109885761095e81612d94565b83838151811061097057610970614963565b602002602001018190525081610985906149da565b91505b600101610925565b5061099c6001846149bd565b63ffffffff1681146109ac578082525b5092915050565b604080518082019091525f81526060602082015263ffffffff82165f908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610a1590614a11565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4190614a11565b8015610a8c5780601f10610a6357610100808354040283529160200191610a8c565b820191905f5260205f20905b815481529060010190602001808311610a6f57829003601f168201915b5050505050815250509050919050565b6040805160e0810182525f808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261061782612d94565b610ae7612cf3565b5f5b63ffffffff8116821115610855575f83838363ffffffff16818110610b1057610b10614963565b9050602002016020810190610b2591906144e0565b63ffffffff81165f908152600b6020526040812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155919250610b6f6001830182613f0d565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a905f90a250610bab81614a62565b9050610ae9565b610bba612cf3565b63ffffffff8088165f908152600d60205260408120805490926401000000009091041690819003610c1f576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a166004820152602401610602565b610c86888888886040518060a001604052808f63ffffffff16815260200187610c4790614a62565b63ffffffff811682528b15156020830152895460ff6a01000000000000000000009091048116151560408401528b166060909201919091529650613054565b505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f28575f848483818110610cc957610cc9614963565b602090810292909201355f818152600c90935260409092206001810154929350919050610d25576040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260048101839052602401610602565b5f610d3282600501612d75565b1115610d8757610d456005820184612d7e565b6040517f60a6d89800000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101839052604401610602565b805468010000000000000000900463ffffffff1615610def5780546040517f60b9df730000000000000000000000000000000000000000000000000000000081526801000000000000000090910463ffffffff16600482015260248101839052604401610602565b83158015610e285750805463ffffffff165f908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610e61576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b6001810154610e7290600790612d89565b506002810154610e8490600990612d89565b505f828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001681556001810182905560028101829055600381018290559060058201818181610edf8282613f44565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610f1691815260200190565b60405180910390a15050600101610cae565b50505050565b5f805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f28575f848483818110610f6657610f66614963565b9050602002810190610f789190614a84565b610f8190614ac0565b6040808201515f908152600c6020908152828220805463ffffffff168352600b82528383208451808601909552805473ffffffffffffffffffffffffffffffffffffffff1685526001810180549697509195939493909284019190610fe590614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461101190614a11565b801561105c5780601f106110335761010080835404028352916020019161105c565b820191905f5260205f20905b81548152906001019060200180831161103f57829003601f168201915b5050509190925250505060018301549091506110ac5782604001516040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b841580156110d15750805173ffffffffffffffffffffffffffffffffffffffff163314155b1561110a576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b6020830151611145576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001820154602084015181146111c657602084015161116690600790612cd9565b1561119d576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084015160018401556111b2600782612d89565b5060208401516111c49060079061384a565b505b60608401516112095783606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b608084015180515f0361124a57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b83545f90859060049061126a90640100000000900463ffffffff16614a62565b91906101000a81548163ffffffff021916908363ffffffff160217905590505f5b825181101561134c576112c18382815181106112a9576112a9614963565b60200260200101516003612cd990919063ffffffff16565b6112f957826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b61134383828151811061130e5761130e614963565b6020026020010151876004015f8563ffffffff1663ffffffff1681526020019081526020015f2061384a90919063ffffffff16565b5060010161128b565b50845468010000000000000000900463ffffffff1680156114a75763ffffffff8082165f908152600d6020908152604080832080546401000000009004909416835260019093018152828220600201805484518184028101840190955280855292939290918301828280156113de57602002820191905f5260205f20905b8154815260200190600101908083116113ca575b505050505090505f5b81518110156114a45761143a82828151811061140557611405614963565b6020026020010151896004015f8763ffffffff1663ffffffff1681526020019081526020015f20612cd990919063ffffffff16565b61149c5781818151811061145057611450614963565b6020026020010151836040517f03dcd86200000000000000000000000000000000000000000000000000000000815260040161060292919091825263ffffffff16602082015260400190565b6001016113e7565b50505b5f6114b487600501613855565b90505f5b81518163ffffffff1610156115f2575f828263ffffffff16815181106114e0576114e0614963565b60209081029190910181015163ffffffff8082165f908152600d8452604080822080546401000000009004909316825260019092018452818120600201805483518187028101870190945280845293955090939192909183018282801561156457602002820191905f5260205f20905b815481526020019060010190808311611550575b505050505090505f5b81518110156115de576115c082828151811061158b5761158b614963565b60200260200101518c6004015f8a63ffffffff1663ffffffff1681526020019081526020015f20612cd990919063ffffffff16565b6115d65781818151811061145057611450614963565b60010161156d565b505050806115eb90614a62565b90506114b8565b50875187547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90911690811788556040808a015160028a0181905560608b015160038b01556020808c01518351928352908201527f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a25050505050505050806001019050610f4b565b611692612cf3565b5f5b81811015610855575f8383838181106116af576116af614963565b90506020028101906116c19190614bdb565b6116ca90614c0d565b805190915073ffffffffffffffffffffffffffffffffffffffff1661171b576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095165f818152600b909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815592519192909160018201906117a69082614cc7565b5050600e80549091505f906117c09063ffffffff16614a62565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e8460200151604051611832919061434b565b60405180910390a35050600101611694565b63ffffffff8083165f908152600d6020908152604080832080546401000000009004909416808452600190940182528083208584526003019091528120805460609384939092909161189590614a11565b80601f01602080910402602001604051908101604052809291908181526020018280546118c190614a11565b801561190c5780601f106118e35761010080835404028352916020019161190c565b820191905f5260205f20905b8154815290600101906020018083116118ef57829003601f168201915b5050505f888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff16159150611a199050575f86815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d906024015f60405180830381865afa1580156119d1573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a169190810190614ddf565b90505b9093509150505b9250929050565b60408051610100810182525f8082526020820181905291810182905260608082018390526080820183905260a082019290925260c0810182905260e081019190915260408051610100810182525f848152600c6020908152838220805463ffffffff8082168652640100000000820481168487018190526801000000000000000090920416858701526001820154606086015260028201546080860152600382015460a0860152835260040190529190912060c0820190611ae790613855565b8152602001611b08600c5f8681526020019081526020015f20600501613855565b905292915050565b611b18612cf3565b5f5b81811015610855575f838383818110611b3557611b35614963565b905060200201359050611b52816003612cd990919063ffffffff16565b611b8b576040517fe181733f00000000000000000000000000000000000000000000000000000000815260048101829052602401610602565b611b9660058261384a565b611bcf576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815260048101829052602401610602565b60405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf21905f90a250600101611b1a565b600e5460609063ffffffff165f611c1a6001836149bd565b63ffffffff1667ffffffffffffffff811115611c3857611c3861412d565b604051908082528060200260200182016040528015611c7d57816020015b604080518082019091525f815260606020820152815260200190600190039081611c565790505b5090505f60015b8363ffffffff168163ffffffff161015611dc85763ffffffff81165f908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611dc05763ffffffff81165f908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191611d1690614a11565b80601f0160208091040260200160405190810160405280929190818152602001828054611d4290614a11565b8015611d8d5780601f10611d6457610100808354040283529160200191611d8d565b820191905f5260205f20905b815481529060010190602001808311611d7057829003601f168201915b505050505081525050838381518110611da857611da8614963565b602002602001018190525081611dbd906149da565b91505b600101611c84565b50600e5461099c9060019063ffffffff166149bd565b611de6612cf3565b5f5b81811015610855575f838383818110611e0357611e03614963565b9050602002810190611e159190614a84565b611e1e90614e56565b90505f611e32825f0151836020015161061d565b9050611e3f60038261384a565b611e78576040517febf5255100000000000000000000000000000000000000000000000000000000815260048101829052602401610602565b611e828183613861565b5050600101611de8565b60015473ffffffffffffffffffffffffffffffffffffffff163314611f0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610602565b5f8054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b5f805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f28575f848483818110611fc057611fc0614963565b9050602002810190611fd29190614a84565b611fdb90614ac0565b805163ffffffff165f908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff16825260018101805495965093949193909284019161203090614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461205c90614a11565b80156120a75780601f1061207e576101008083540402835291602001916120a7565b820191905f5260205f20905b81548152906001019060200180831161208a57829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff1661210d5781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610602565b831580156121325750805173ffffffffffffffffffffffffffffffffffffffff163314155b1561216b576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b6040808301515f908152600c602052206001810154156121bf5782604001516040517f5461848300000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b60408301516122025782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b6020830151158061221f5750602083015161221f90600790612cd9565b15612256576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301516122995782606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b608083015180515f036122da57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b815482906004906122f890640100000000900463ffffffff16614a62565b82546101009290920a63ffffffff81810219909316918316021790915582546401000000009004165f5b82518110156123cb576123408382815181106112a9576112a9614963565b61237857826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b6123c283828151811061238d5761238d614963565b6020026020010151856004015f8563ffffffff1663ffffffff1681526020019081526020015f2061384a90919063ffffffff16565b50600101612322565b5060608501516003840155845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9182161784556040860151600285015560208601516001850181905561242b916007919061384a16565b50604085015161243d9060099061384a565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a25050505050806001019050611fa5565b8281146124dc576040517fab8b67c60000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610602565b5f805473ffffffffffffffffffffffffffffffffffffffff16905b848110156127cc575f86868381811061251257612512614963565b905060200201602081019061252791906144e0565b63ffffffff81165f908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff16612595576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610602565b5f8686858181106125a8576125a8614963565b90506020028101906125ba9190614bdb565b6125c390614c0d565b805190915073ffffffffffffffffffffffffffffffffffffffff16612614576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815473ffffffffffffffffffffffffffffffffffffffff16331480159061265157503373ffffffffffffffffffffffffffffffffffffffff861614155b1561268a576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b8051825473ffffffffffffffffffffffffffffffffffffffff908116911614158061270657506020808201516040516126c3920161434b565b60405160208183030381529060405280519060200120826001016040516020016126ed9190614ef7565b6040516020818303038152906040528051906020012014155b156127be57805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602081015160018301906127609082614cc7565b50805f015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a2883602001516040516127b5919061434b565b60405180910390a35b5050508060010190506124f7565b505050505050565b6128126040805160e0810182525f808252606060208301819052928201839052909182019081526020015f81525f6020820181905260409091015290565b6040805160e0810182528381525f848152600260209081529290208054919283019161283d90614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461286990614a11565b80156128b45780601f1061288b576101008083540402835291602001916128b4565b820191905f5260205f20905b81548152906001019060200180831161289757829003601f168201915b5050505050815260200160025f8581526020019081526020015f2060010180546128dd90614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461290990614a11565b80156129545780601f1061292b57610100808354040283529160200191612954565b820191905f5260205f20905b81548152906001019060200180831161293757829003601f168201915b50505091835250505f848152600260208181526040909220015491019060ff1660038111156129855761298561474b565b81525f8481526002602081815260409092200154910190610100900460ff1660018111156129b5576129b561474b565b81525f848152600260208181526040928390209091015462010000900473ffffffffffffffffffffffffffffffffffffffff1690830152016129f8600585612cd9565b1515905292915050565b612a0a612cf3565b600e80545f9164010000000090910463ffffffff16906004612a2b83614a62565b82546101009290920a63ffffffff81810219909316918316021790915581165f818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a08101835292835260019083015286151590820152841515606082015260ff84166080820152909150612ac0908990899089908990613054565b5050505050505050565b60605f612ad76003613855565b90505f815167ffffffffffffffff811115612af457612af461412d565b604051908082528060200260200182016040528015612b6357816020015b612b506040805160e0810182525f808252606060208301819052928201839052909182019081526020015f81525f6020820181905260409091015290565b815260200190600190039081612b125790505b5090505f5b82518110156109ac57612b93838281518110612b8657612b86614963565b60200260200101516127d4565b828281518110612ba557612ba5614963565b6020908102919091010152600101612b68565b60605f612bc56009613855565b90505f815167ffffffffffffffff811115612be257612be261412d565b604051908082528060200260200182016040528015612c7057816020015b60408051610100810182525f808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181612c005790505b5090505f5b82518110156109ac57612ca0838281518110612c9357612c93614963565b6020026020010151611a27565b828281518110612cb257612cb2614963565b6020908102919091010152600101612c75565b612ccd612cf3565b612cd681613a47565b50565b5f81815260018301602052604081205415155b9392505050565b5f5473ffffffffffffffffffffffffffffffffffffffff163314612d73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610602565b565b5f610617825490565b5f612cec8383613b3b565b5f612cec8383613b61565b6040805160e0810182525f808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d8252848320805464010000000090049091168084526001909101825284832060028101805487518186028101860190985280885295969295919493909190830182828015612e4257602002820191905f5260205f20905b815481526020019060010190808311612e2e575b505050505090505f815167ffffffffffffffff811115612e6457612e6461412d565b604051908082528060200260200182016040528015612ea957816020015b604080518082019091525f815260606020820152815260200190600190039081612e825790505b5090505f5b8151811015612fbc576040518060400160405280848381518110612ed457612ed4614963565b60200260200101518152602001856003015f868581518110612ef857612ef8614963565b602002602001015181526020019081526020015f208054612f1890614a11565b80601f0160208091040260200160405190810160405280929190818152602001828054612f4490614a11565b8015612f8f5780601f10612f6657610100808354040283529160200191612f8f565b820191905f5260205f20905b815481529060010190602001808311612f7257829003601f168201915b5050505050815250828281518110612fa957612fa9614963565b6020908102919091010152600101612eae565b506040805160e08101825263ffffffff8089165f818152600d6020818152868320548086168752948b168187015260ff680100000000000000008604811697870197909752690100000000000000000085048716151560608701529290915290526a010000000000000000000090049091161515608082015260a0810161304285613855565b81526020019190915295945050505050565b805163ffffffff9081165f908152600d602090815260408083208286015190941683526001909301905220608082015160ff1615806130a55750608082015185906130a0906001614f9f565b60ff16115b156130ee5760808201516040517f25b4d61800000000000000000000000000000000000000000000000000000000815260ff909116600482015260248101869052604401610602565b6001826020015163ffffffff1611156131ce57815163ffffffff165f908152600d60209081526040822090840151600191820191839161312e91906149bd565b63ffffffff1663ffffffff1681526020019081526020015f2090505f5b61315482612d75565b8110156131cb57613180845f015163ffffffff16600c5f61076085875f01612d7e90919063ffffffff16565b50600c5f61318e8484612d7e565b815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16905560010161314b565b50505b5f5b858110156133fe576131fd8787838181106131ed576131ed614963565b859260209091020135905061384a565b61325e57825187878381811061321557613215614963565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610602565b8260600151156133ae57825163ffffffff16600c5f89898581811061328557613285614963565b602090810292909201358352508101919091526040015f205468010000000000000000900463ffffffff16148015906132fc5750600c5f8888848181106132ce576132ce614963565b602090810292909201358352508101919091526040015f205468010000000000000000900463ffffffff1615155b1561335e57825187878381811061331557613315614963565b6040517f60b9df7300000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610602565b8251600c5f89898581811061337557613375614963565b9050602002013581526020019081526020015f205f0160086101000a81548163ffffffff021916908363ffffffff1602179055506133f6565b82516133f49063ffffffff16600c5f8a8a868181106133cf576133cf614963565b9050602002013581526020019081526020015f2060050161384a90919063ffffffff16565b505b6001016131d0565b505f5b838110156137fe573685858381811061341c5761341c614963565b905060200281019061342e9190614bdb565b905061343c60038235612cd9565b613475576040517fe181733f00000000000000000000000000000000000000000000000000000000815281356004820152602401610602565b61348160058235612cd9565b156134bb576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815281356004820152602401610602565b80355f908152600384016020526040812080546134d790614a11565b905011156135235783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015281356024820152604401610602565b5f5b87811015613625576135c28235600c5f8c8c8681811061354757613547614963565b9050602002013581526020019081526020015f206004015f600c5f8e8e8881811061357457613574614963565b9050602002013581526020019081526020015f205f0160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020019081526020015f20612cd990919063ffffffff16565b61361d578888828181106135d8576135d8614963565b6040517fa7e792500000000000000000000000000000000000000000000000000000000081526020909102929092013560048301525082356024820152604401610602565b600101613525565b506002830180546001810182555f918252602091829020833591015561364d90820182614fb8565b82355f90815260038601602052604090209161366a919083615019565b50604080850151855163ffffffff9081165f908152600d602090815284822080549415156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff90951694909417909355606088015188518316825284822080549115156a0100000000000000000000027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff9092169190911790556080880151885183168252848220805460ff9290921668010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909216919091179055828801805189518416835294909120805494909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff909416939093179055855191516137f592918435908c908c906137bc90880188614fb8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250613c4492505050565b50600101613401565b50815160208084015160405163ffffffff91821681529216917ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a2505050505050565b5f612cec8383613d1e565b60605f612cec83613d6a565b608081015173ffffffffffffffffffffffffffffffffffffffff1615613903576138af81608001517f78bea72100000000000000000000000000000000000000000000000000000000613dc3565b6139035760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610602565b5f828152600260205260409020815182919081906139219082614cc7565b50602082015160018201906139369082614cc7565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360038111156139785761397861474b565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101008360018111156139bf576139bf61474b565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae905f90a25050565b3373ffffffffffffffffffffffffffffffffffffffff821603613ac6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610602565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8381169182179092555f8054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b5f825f018281548110613b5057613b50614963565b905f5260205f200154905092915050565b5f8181526001830160205260408120548015613c3b575f613b8360018361512f565b85549091505f90613b969060019061512f565b9050818114613bf5575f865f018281548110613bb457613bb4614963565b905f5260205f200154905080875f018481548110613bd457613bd4614963565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080613c0657613c06615142565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610617565b5f915050610617565b5f848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff16156127cc575f84815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c90613ce9908690869086908b908d9060040161516f565b5f604051808303815f87803b158015613d00575f80fd5b505af1158015613d12573d5f803e3d5ffd5b50505050505050505050565b5f818152600183016020526040812054613d6357508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610617565b505f610617565b6060815f01805480602002602001604051908101604052809291908181526020018280548015613db757602002820191905f5260205f20905b815481526020019060010190808311613da3575b50505050509050919050565b5f613dcd83613dde565b8015612cec5750612cec8383613e41565b5f613e09827f01ffc9a700000000000000000000000000000000000000000000000000000000613e41565b80156106175750613e3a827fffffffff00000000000000000000000000000000000000000000000000000000613e41565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017815282515f9392849283928392918391908a617530fa92503d91505f519050828015613ef7575060208210155b8015613f0257505f81115b979650505050505050565b508054613f1990614a11565b5f825580601f10613f28575050565b601f0160209004905f5260205f2090810190612cd69190613f5b565b5080545f8255905f5260205f2090810190612cd691905b5b80821115613f6f575f8155600101613f5c565b5090565b5f8083601f840112613f83575f80fd5b50813567ffffffffffffffff811115613f9a575f80fd5b6020830191508360208260051b8501011115611a20575f80fd5b5f8060208385031215613fc5575f80fd5b823567ffffffffffffffff811115613fdb575f80fd5b613fe785828601613f73565b90969095509350505050565b5f815180845260208085019450602084015f5b8381101561402257815187529582019590820190600101614006565b509495945050505050565b5f61010063ffffffff80845116855280602085015116602086015280604085015116604086015250606083015160608501526080830151608085015260a083015160a085015260c08301518160c086015261408a82860182613ff3565b91505060e083015184820360e08601526140a48282613ff3565b95945050505050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261410e85835161402d565b945092850192908501906001016140d4565b5092979650505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160a0810167ffffffffffffffff8111828210171561417d5761417d61412d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156141ca576141ca61412d565b604052919050565b5f67ffffffffffffffff8211156141eb576141eb61412d565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112614226575f80fd5b8135614239614234826141d2565b614183565b81815284602083860101111561424d575f80fd5b816020850160208301375f918101602001919091529392505050565b5f806040838503121561427a575f80fd5b823567ffffffffffffffff80821115614291575f80fd5b61429d86838701614217565b935060208501359150808211156142b2575f80fd5b506142bf85828601614217565b9150509250929050565b5f602082840312156142d9575f80fd5b5035919050565b5f5b838110156142fa5781810151838201526020016142e2565b50505f910152565b5f81518084526143198160208601602086016142e0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f612cec6020830184614302565b5f82825180855260208086019550808260051b8401018186015f5b848110156143d8578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051845284015160408585018190526143c481860183614302565b9a86019a9450505090830190600101614378565b5090979650505050505050565b5f63ffffffff8083511684528060208401511660208501525060ff604083015116604084015260608201511515606084015260808201511515608084015260a082015160e060a085015261443c60e0850182613ff3565b905060c083015184820360c08601526140a4828261435d565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526144b68583516143e5565b9450928501929085019060010161447c565b803563ffffffff811681146144db575f80fd5b919050565b5f602082840312156144f0575f80fd5b612cec826144c8565b73ffffffffffffffffffffffffffffffffffffffff81511682525f60208201516040602085015261452d6040850182614302565b949350505050565b602081525f612cec60208301846144f9565b602081525f612cec60208301846143e5565b803580151581146144db575f80fd5b803560ff811681146144db575f80fd5b5f805f805f805f60a0888a03121561458e575f80fd5b614597886144c8565b9650602088013567ffffffffffffffff808211156145b3575f80fd5b6145bf8b838c01613f73565b909850965060408a01359150808211156145d7575f80fd5b506145e48a828b01613f73565b90955093506145f7905060608901614559565b915061460560808901614568565b905092959891949750929550565b5f8060408385031215614624575f80fd5b61462d836144c8565b946020939093013593505050565b604081525f61464d6040830185614302565b82810360208401526140a48185614302565b602081525f612cec602083018461402d565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526146d28583516144f9565b94509285019290850190600101614698565b5f805f80604085870312156146f7575f80fd5b843567ffffffffffffffff8082111561470e575f80fd5b61471a88838901613f73565b90965094506020870135915080821115614732575f80fd5b5061473f87828801613f73565b95989497509550505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b805182525f602082015160e0602085015261479660e0850182614302565b9050604083015184820360408601526147af8282614302565b9150506060830151600481106147c7576147c761474b565b60608501526080830151600281106147e1576147e161474b565b8060808601525060a083015161480f60a086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015161061360c086018215159052565b602081525f612cec6020830184614778565b5f805f805f805f60a0888a03121561484b575f80fd5b873567ffffffffffffffff80821115614862575f80fd5b61486e8b838c01613f73565b909950975060208a0135915080821115614886575f80fd5b506148938a828b01613f73565b90965094506148a6905060408901614559565b92506145f760608901614559565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614915858351614778565b945092850192908501906001016148db565b803573ffffffffffffffffffffffffffffffffffffffff811681146144db575f80fd5b5f6020828403121561495a575f80fd5b612cec82614927565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b63ffffffff8281168282160390808211156109ac576109ac614990565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614a0a57614a0a614990565b5060010190565b600181811c90821680614a2557607f821691505b602082108103614a5c577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f63ffffffff808316818103614a7a57614a7a614990565b6001019392505050565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112614ab6575f80fd5b9190910192915050565b5f60a08236031215614ad0575f80fd5b614ad861415a565b614ae1836144c8565b8152602080840135818301526040840135604083015260608401356060830152608084013567ffffffffffffffff80821115614b1b575f80fd5b9085019036601f830112614b2d575f80fd5b813581811115614b3f57614b3f61412d565b8060051b9150614b50848301614183565b8181529183018401918481019036841115614b69575f80fd5b938501935b83851015614b8757843582529385019390850190614b6e565b608087015250939695505050505050565b602080825282518282018190525f9190848201906040850190845b81811015614bcf57835183529284019291840191600101614bb3565b50909695505050505050565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112614ab6575f80fd5b5f60408236031215614c1d575f80fd5b6040516040810167ffffffffffffffff8282108183111715614c4157614c4161412d565b81604052614c4e85614927565b83526020850135915080821115614c63575f80fd5b50614c7036828601614217565b60208301525092915050565b601f82111561085557805f5260205f20601f840160051c81016020851015614ca15750805b601f840160051c820191505b81811015614cc0575f8155600101614cad565b5050505050565b815167ffffffffffffffff811115614ce157614ce161412d565b614cf581614cef8454614a11565b84614c7c565b602080601f831160018114614d47575f8415614d115750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556127cc565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614d9357888601518255948401946001909101908401614d74565b5085821015614dcf57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b5f60208284031215614def575f80fd5b815167ffffffffffffffff811115614e05575f80fd5b8201601f81018413614e15575f80fd5b8051614e23614234826141d2565b818152856020838501011115614e37575f80fd5b6140a48260208301602086016142e0565b8035600281106144db575f80fd5b5f60a08236031215614e66575f80fd5b614e6e61415a565b823567ffffffffffffffff80821115614e85575f80fd5b614e9136838701614217565b83526020850135915080821115614ea6575f80fd5b50614eb336828601614217565b602083015250604083013560048110614eca575f80fd5b6040820152614edb60608401614e48565b6060820152614eec60808401614927565b608082015292915050565b5f60208083525f8454614f0981614a11565b806020870152604060018084165f8114614f2a5760018114614f6457614f91565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a01019550614f91565b895f5260205f205f5b85811015614f885781548b8201860152908301908801614f6d565b8a016040019650505b509398975050505050505050565b60ff818116838216019081111561061757610617614990565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614feb575f80fd5b83018035915067ffffffffffffffff821115615005575f80fd5b602001915036819003821315611a20575f80fd5b67ffffffffffffffff8311156150315761503161412d565b6150458361503f8354614a11565b83614c7c565b5f601f841160018114615095575f851561505f5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614cc0565b5f838152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08716915b828110156150e257868501358255602094850194600190920191016150c2565b508682101561511d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b8181038181111561061757610617614990565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b608081528460808201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8611156151a6575f80fd5b8560051b808860a0850137820182810360a090810160208501526151cc90820187614302565b91505063ffffffff8085166040840152808416606084015250969550505050505056fea164736f6c6343000818000a

Deployed Bytecode

0x608060405234801561000f575f80fd5b50600436106101bb575f3560e01c806350c946fe116100f35780638da5cb5b11610093578063ddbe4f821161006e578063ddbe4f8214610442578063e29581aa14610457578063f2fde38b1461045f578063fcdc8efe14610472575f80fd5b80638da5cb5b146103e85780639cb7c5f41461040f578063d8bc7b681461042f575f80fd5b8063715f5295116100ce578063715f5295146103a757806379ba5097146103ba57806384f5ed8a146103c257806386fa4246146103d5575f80fd5b806350c946fe1461035f5780635d83d9671461037f57806366acaa3314610392575f80fd5b8063235374051161015e5780632c01a1e8116101395780632c01a1e814610305578063358039f414610318578063398f37731461032b5780633f2a13c91461033e575f80fd5b806323537405146102bf578063275459f2146102df5780632a852933146102f2575f80fd5b8063181f5a7711610199578063181f5a771461022c5780631d05394c14610275578063214502431461028a57806322bdbcbc1461029f575f80fd5b806305a51966146101bf5780630fe5800a146101e85780631257001114610209575b5f80fd5b6101d26101cd366004613fb4565b610498565b6040516101df91906140ad565b60405180910390f35b6101fb6101f6366004614269565b61061d565b6040519081526020016101df565b61021c6102173660046142c9565b61064f565b60405190151581526020016101df565b6102686040518060400160405280601a81526020017f4361706162696c6974696573526567697374727920312e312e3000000000000081525081565b6040516101df919061434b565b610288610283366004613fb4565b61065b565b005b61029261085a565b6040516101df9190614455565b6102b26102ad3660046144e0565b6109b3565b6040516101df9190614535565b6102d26102cd3660046144e0565b610a9c565b6040516101df9190614547565b6102886102ed366004613fb4565b610adf565b610288610300366004614578565b610bb2565b610288610313366004613fb4565b610c91565b610288610326366004613fb4565b610f2e565b610288610339366004613fb4565b61168a565b61035161034c366004614613565b611844565b6040516101df92919061463b565b61037261036d3660046142c9565b611a27565b6040516101df919061465f565b61028861038d366004613fb4565b611b10565b61039a611c02565b6040516101df9190614671565b6102886103b5366004613fb4565b611dde565b610288611e8c565b6102886103d0366004613fb4565b611f88565b6102886103e33660046146e4565b612499565b5f5460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101df565b61042261041d3660046142c9565b6127d4565b6040516101df9190614823565b61028861043d366004614835565b612a02565b61044a612aca565b6040516101df91906148b4565b6101d2612bb8565b61028861046d36600461494a565b612cc5565b600e54640100000000900463ffffffff1660405163ffffffff90911681526020016101df565b60605f8267ffffffffffffffff8111156104b4576104b461412d565b60405190808252806020026020018201604052801561054257816020015b60408051610100810182525f808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816104d25790505b5090505f5b838110156106135761057085858381811061056457610564614963565b90506020020135611a27565b82828151811061058257610582614963565b60200260200101819052505f8019168282815181106105a3576105a3614963565b6020026020010151608001510361060b578484828181106105c6576105c6614963565b905060200201356040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b60405180910390fd5b600101610547565b5090505b92915050565b5f828260405160200161063192919061463b565b60405160208183030381529060405280519060200120905092915050565b5f610617600583612cd9565b610663612cf3565b5f5b81811015610855575f83838381811061068057610680614963565b905060200201602081019061069591906144e0565b63ffffffff8181165f908152600d60209081526040808320805464010000000081049095168085526001820190935290832094955093909290916a010000000000000000000090910460ff16905b6106ec83612d75565b81101561078857811561074057600c5f6107068584612d7e565b815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff169055610780565b61077e8663ffffffff16600c5f6107608588612d7e90919063ffffffff16565b81526020019081526020015f20600501612d8990919063ffffffff16565b505b6001016106e3565b508354640100000000900463ffffffff165f036107d9576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff86166004820152602401610602565b63ffffffff85165f818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffff0000000000000000000000169055519182527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a25050505050806001019050610665565b505050565b600e54606090640100000000900463ffffffff165f61087a6001836149bd565b63ffffffff1667ffffffffffffffff8111156108985761089861412d565b60405190808252806020026020018201604052801561091e57816020015b6040805160e0810182525f80825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816108b65790505b5090505f60015b8363ffffffff168163ffffffff1610156109905763ffffffff8082165f908152600d602052604090205416156109885761095e81612d94565b83838151811061097057610970614963565b602002602001018190525081610985906149da565b91505b600101610925565b5061099c6001846149bd565b63ffffffff1681146109ac578082525b5092915050565b604080518082019091525f81526060602082015263ffffffff82165f908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610a1590614a11565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4190614a11565b8015610a8c5780601f10610a6357610100808354040283529160200191610a8c565b820191905f5260205f20905b815481529060010190602001808311610a6f57829003601f168201915b5050505050815250509050919050565b6040805160e0810182525f808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261061782612d94565b610ae7612cf3565b5f5b63ffffffff8116821115610855575f83838363ffffffff16818110610b1057610b10614963565b9050602002016020810190610b2591906144e0565b63ffffffff81165f908152600b6020526040812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155919250610b6f6001830182613f0d565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a905f90a250610bab81614a62565b9050610ae9565b610bba612cf3565b63ffffffff8088165f908152600d60205260408120805490926401000000009091041690819003610c1f576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a166004820152602401610602565b610c86888888886040518060a001604052808f63ffffffff16815260200187610c4790614a62565b63ffffffff811682528b15156020830152895460ff6a01000000000000000000009091048116151560408401528b166060909201919091529650613054565b505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f28575f848483818110610cc957610cc9614963565b602090810292909201355f818152600c90935260409092206001810154929350919050610d25576040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260048101839052602401610602565b5f610d3282600501612d75565b1115610d8757610d456005820184612d7e565b6040517f60a6d89800000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101839052604401610602565b805468010000000000000000900463ffffffff1615610def5780546040517f60b9df730000000000000000000000000000000000000000000000000000000081526801000000000000000090910463ffffffff16600482015260248101839052604401610602565b83158015610e285750805463ffffffff165f908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610e61576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b6001810154610e7290600790612d89565b506002810154610e8490600990612d89565b505f828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001681556001810182905560028101829055600381018290559060058201818181610edf8282613f44565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610f1691815260200190565b60405180910390a15050600101610cae565b50505050565b5f805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f28575f848483818110610f6657610f66614963565b9050602002810190610f789190614a84565b610f8190614ac0565b6040808201515f908152600c6020908152828220805463ffffffff168352600b82528383208451808601909552805473ffffffffffffffffffffffffffffffffffffffff1685526001810180549697509195939493909284019190610fe590614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461101190614a11565b801561105c5780601f106110335761010080835404028352916020019161105c565b820191905f5260205f20905b81548152906001019060200180831161103f57829003601f168201915b5050509190925250505060018301549091506110ac5782604001516040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b841580156110d15750805173ffffffffffffffffffffffffffffffffffffffff163314155b1561110a576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b6020830151611145576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001820154602084015181146111c657602084015161116690600790612cd9565b1561119d576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084015160018401556111b2600782612d89565b5060208401516111c49060079061384a565b505b60608401516112095783606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b608084015180515f0361124a57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b83545f90859060049061126a90640100000000900463ffffffff16614a62565b91906101000a81548163ffffffff021916908363ffffffff160217905590505f5b825181101561134c576112c18382815181106112a9576112a9614963565b60200260200101516003612cd990919063ffffffff16565b6112f957826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b61134383828151811061130e5761130e614963565b6020026020010151876004015f8563ffffffff1663ffffffff1681526020019081526020015f2061384a90919063ffffffff16565b5060010161128b565b50845468010000000000000000900463ffffffff1680156114a75763ffffffff8082165f908152600d6020908152604080832080546401000000009004909416835260019093018152828220600201805484518184028101840190955280855292939290918301828280156113de57602002820191905f5260205f20905b8154815260200190600101908083116113ca575b505050505090505f5b81518110156114a45761143a82828151811061140557611405614963565b6020026020010151896004015f8763ffffffff1663ffffffff1681526020019081526020015f20612cd990919063ffffffff16565b61149c5781818151811061145057611450614963565b6020026020010151836040517f03dcd86200000000000000000000000000000000000000000000000000000000815260040161060292919091825263ffffffff16602082015260400190565b6001016113e7565b50505b5f6114b487600501613855565b90505f5b81518163ffffffff1610156115f2575f828263ffffffff16815181106114e0576114e0614963565b60209081029190910181015163ffffffff8082165f908152600d8452604080822080546401000000009004909316825260019092018452818120600201805483518187028101870190945280845293955090939192909183018282801561156457602002820191905f5260205f20905b815481526020019060010190808311611550575b505050505090505f5b81518110156115de576115c082828151811061158b5761158b614963565b60200260200101518c6004015f8a63ffffffff1663ffffffff1681526020019081526020015f20612cd990919063ffffffff16565b6115d65781818151811061145057611450614963565b60010161156d565b505050806115eb90614a62565b90506114b8565b50875187547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90911690811788556040808a015160028a0181905560608b015160038b01556020808c01518351928352908201527f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a25050505050505050806001019050610f4b565b611692612cf3565b5f5b81811015610855575f8383838181106116af576116af614963565b90506020028101906116c19190614bdb565b6116ca90614c0d565b805190915073ffffffffffffffffffffffffffffffffffffffff1661171b576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095165f818152600b909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815592519192909160018201906117a69082614cc7565b5050600e80549091505f906117c09063ffffffff16614a62565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e8460200151604051611832919061434b565b60405180910390a35050600101611694565b63ffffffff8083165f908152600d6020908152604080832080546401000000009004909416808452600190940182528083208584526003019091528120805460609384939092909161189590614a11565b80601f01602080910402602001604051908101604052809291908181526020018280546118c190614a11565b801561190c5780601f106118e35761010080835404028352916020019161190c565b820191905f5260205f20905b8154815290600101906020018083116118ef57829003601f168201915b5050505f888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff16159150611a199050575f86815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d906024015f60405180830381865afa1580156119d1573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a169190810190614ddf565b90505b9093509150505b9250929050565b60408051610100810182525f8082526020820181905291810182905260608082018390526080820183905260a082019290925260c0810182905260e081019190915260408051610100810182525f848152600c6020908152838220805463ffffffff8082168652640100000000820481168487018190526801000000000000000090920416858701526001820154606086015260028201546080860152600382015460a0860152835260040190529190912060c0820190611ae790613855565b8152602001611b08600c5f8681526020019081526020015f20600501613855565b905292915050565b611b18612cf3565b5f5b81811015610855575f838383818110611b3557611b35614963565b905060200201359050611b52816003612cd990919063ffffffff16565b611b8b576040517fe181733f00000000000000000000000000000000000000000000000000000000815260048101829052602401610602565b611b9660058261384a565b611bcf576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815260048101829052602401610602565b60405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf21905f90a250600101611b1a565b600e5460609063ffffffff165f611c1a6001836149bd565b63ffffffff1667ffffffffffffffff811115611c3857611c3861412d565b604051908082528060200260200182016040528015611c7d57816020015b604080518082019091525f815260606020820152815260200190600190039081611c565790505b5090505f60015b8363ffffffff168163ffffffff161015611dc85763ffffffff81165f908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611dc05763ffffffff81165f908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191611d1690614a11565b80601f0160208091040260200160405190810160405280929190818152602001828054611d4290614a11565b8015611d8d5780601f10611d6457610100808354040283529160200191611d8d565b820191905f5260205f20905b815481529060010190602001808311611d7057829003601f168201915b505050505081525050838381518110611da857611da8614963565b602002602001018190525081611dbd906149da565b91505b600101611c84565b50600e5461099c9060019063ffffffff166149bd565b611de6612cf3565b5f5b81811015610855575f838383818110611e0357611e03614963565b9050602002810190611e159190614a84565b611e1e90614e56565b90505f611e32825f0151836020015161061d565b9050611e3f60038261384a565b611e78576040517febf5255100000000000000000000000000000000000000000000000000000000815260048101829052602401610602565b611e828183613861565b5050600101611de8565b60015473ffffffffffffffffffffffffffffffffffffffff163314611f0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610602565b5f8054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b5f805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f28575f848483818110611fc057611fc0614963565b9050602002810190611fd29190614a84565b611fdb90614ac0565b805163ffffffff165f908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff16825260018101805495965093949193909284019161203090614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461205c90614a11565b80156120a75780601f1061207e576101008083540402835291602001916120a7565b820191905f5260205f20905b81548152906001019060200180831161208a57829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff1661210d5781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610602565b831580156121325750805173ffffffffffffffffffffffffffffffffffffffff163314155b1561216b576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b6040808301515f908152600c602052206001810154156121bf5782604001516040517f5461848300000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b60408301516122025782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b6020830151158061221f5750602083015161221f90600790612cd9565b15612256576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301516122995782606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b608083015180515f036122da57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b815482906004906122f890640100000000900463ffffffff16614a62565b82546101009290920a63ffffffff81810219909316918316021790915582546401000000009004165f5b82518110156123cb576123408382815181106112a9576112a9614963565b61237857826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b6123c283828151811061238d5761238d614963565b6020026020010151856004015f8563ffffffff1663ffffffff1681526020019081526020015f2061384a90919063ffffffff16565b50600101612322565b5060608501516003840155845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9182161784556040860151600285015560208601516001850181905561242b916007919061384a16565b50604085015161243d9060099061384a565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a25050505050806001019050611fa5565b8281146124dc576040517fab8b67c60000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610602565b5f805473ffffffffffffffffffffffffffffffffffffffff16905b848110156127cc575f86868381811061251257612512614963565b905060200201602081019061252791906144e0565b63ffffffff81165f908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff16612595576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610602565b5f8686858181106125a8576125a8614963565b90506020028101906125ba9190614bdb565b6125c390614c0d565b805190915073ffffffffffffffffffffffffffffffffffffffff16612614576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815473ffffffffffffffffffffffffffffffffffffffff16331480159061265157503373ffffffffffffffffffffffffffffffffffffffff861614155b1561268a576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b8051825473ffffffffffffffffffffffffffffffffffffffff908116911614158061270657506020808201516040516126c3920161434b565b60405160208183030381529060405280519060200120826001016040516020016126ed9190614ef7565b6040516020818303038152906040528051906020012014155b156127be57805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602081015160018301906127609082614cc7565b50805f015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a2883602001516040516127b5919061434b565b60405180910390a35b5050508060010190506124f7565b505050505050565b6128126040805160e0810182525f808252606060208301819052928201839052909182019081526020015f81525f6020820181905260409091015290565b6040805160e0810182528381525f848152600260209081529290208054919283019161283d90614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461286990614a11565b80156128b45780601f1061288b576101008083540402835291602001916128b4565b820191905f5260205f20905b81548152906001019060200180831161289757829003601f168201915b5050505050815260200160025f8581526020019081526020015f2060010180546128dd90614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461290990614a11565b80156129545780601f1061292b57610100808354040283529160200191612954565b820191905f5260205f20905b81548152906001019060200180831161293757829003601f168201915b50505091835250505f848152600260208181526040909220015491019060ff1660038111156129855761298561474b565b81525f8481526002602081815260409092200154910190610100900460ff1660018111156129b5576129b561474b565b81525f848152600260208181526040928390209091015462010000900473ffffffffffffffffffffffffffffffffffffffff1690830152016129f8600585612cd9565b1515905292915050565b612a0a612cf3565b600e80545f9164010000000090910463ffffffff16906004612a2b83614a62565b82546101009290920a63ffffffff81810219909316918316021790915581165f818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a08101835292835260019083015286151590820152841515606082015260ff84166080820152909150612ac0908990899089908990613054565b5050505050505050565b60605f612ad76003613855565b90505f815167ffffffffffffffff811115612af457612af461412d565b604051908082528060200260200182016040528015612b6357816020015b612b506040805160e0810182525f808252606060208301819052928201839052909182019081526020015f81525f6020820181905260409091015290565b815260200190600190039081612b125790505b5090505f5b82518110156109ac57612b93838281518110612b8657612b86614963565b60200260200101516127d4565b828281518110612ba557612ba5614963565b6020908102919091010152600101612b68565b60605f612bc56009613855565b90505f815167ffffffffffffffff811115612be257612be261412d565b604051908082528060200260200182016040528015612c7057816020015b60408051610100810182525f808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181612c005790505b5090505f5b82518110156109ac57612ca0838281518110612c9357612c93614963565b6020026020010151611a27565b828281518110612cb257612cb2614963565b6020908102919091010152600101612c75565b612ccd612cf3565b612cd681613a47565b50565b5f81815260018301602052604081205415155b9392505050565b5f5473ffffffffffffffffffffffffffffffffffffffff163314612d73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610602565b565b5f610617825490565b5f612cec8383613b3b565b5f612cec8383613b61565b6040805160e0810182525f808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d8252848320805464010000000090049091168084526001909101825284832060028101805487518186028101860190985280885295969295919493909190830182828015612e4257602002820191905f5260205f20905b815481526020019060010190808311612e2e575b505050505090505f815167ffffffffffffffff811115612e6457612e6461412d565b604051908082528060200260200182016040528015612ea957816020015b604080518082019091525f815260606020820152815260200190600190039081612e825790505b5090505f5b8151811015612fbc576040518060400160405280848381518110612ed457612ed4614963565b60200260200101518152602001856003015f868581518110612ef857612ef8614963565b602002602001015181526020019081526020015f208054612f1890614a11565b80601f0160208091040260200160405190810160405280929190818152602001828054612f4490614a11565b8015612f8f5780601f10612f6657610100808354040283529160200191612f8f565b820191905f5260205f20905b815481529060010190602001808311612f7257829003601f168201915b5050505050815250828281518110612fa957612fa9614963565b6020908102919091010152600101612eae565b506040805160e08101825263ffffffff8089165f818152600d6020818152868320548086168752948b168187015260ff680100000000000000008604811697870197909752690100000000000000000085048716151560608701529290915290526a010000000000000000000090049091161515608082015260a0810161304285613855565b81526020019190915295945050505050565b805163ffffffff9081165f908152600d602090815260408083208286015190941683526001909301905220608082015160ff1615806130a55750608082015185906130a0906001614f9f565b60ff16115b156130ee5760808201516040517f25b4d61800000000000000000000000000000000000000000000000000000000815260ff909116600482015260248101869052604401610602565b6001826020015163ffffffff1611156131ce57815163ffffffff165f908152600d60209081526040822090840151600191820191839161312e91906149bd565b63ffffffff1663ffffffff1681526020019081526020015f2090505f5b61315482612d75565b8110156131cb57613180845f015163ffffffff16600c5f61076085875f01612d7e90919063ffffffff16565b50600c5f61318e8484612d7e565b815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16905560010161314b565b50505b5f5b858110156133fe576131fd8787838181106131ed576131ed614963565b859260209091020135905061384a565b61325e57825187878381811061321557613215614963565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610602565b8260600151156133ae57825163ffffffff16600c5f89898581811061328557613285614963565b602090810292909201358352508101919091526040015f205468010000000000000000900463ffffffff16148015906132fc5750600c5f8888848181106132ce576132ce614963565b602090810292909201358352508101919091526040015f205468010000000000000000900463ffffffff1615155b1561335e57825187878381811061331557613315614963565b6040517f60b9df7300000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610602565b8251600c5f89898581811061337557613375614963565b9050602002013581526020019081526020015f205f0160086101000a81548163ffffffff021916908363ffffffff1602179055506133f6565b82516133f49063ffffffff16600c5f8a8a868181106133cf576133cf614963565b9050602002013581526020019081526020015f2060050161384a90919063ffffffff16565b505b6001016131d0565b505f5b838110156137fe573685858381811061341c5761341c614963565b905060200281019061342e9190614bdb565b905061343c60038235612cd9565b613475576040517fe181733f00000000000000000000000000000000000000000000000000000000815281356004820152602401610602565b61348160058235612cd9565b156134bb576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815281356004820152602401610602565b80355f908152600384016020526040812080546134d790614a11565b905011156135235783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015281356024820152604401610602565b5f5b87811015613625576135c28235600c5f8c8c8681811061354757613547614963565b9050602002013581526020019081526020015f206004015f600c5f8e8e8881811061357457613574614963565b9050602002013581526020019081526020015f205f0160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020019081526020015f20612cd990919063ffffffff16565b61361d578888828181106135d8576135d8614963565b6040517fa7e792500000000000000000000000000000000000000000000000000000000081526020909102929092013560048301525082356024820152604401610602565b600101613525565b506002830180546001810182555f918252602091829020833591015561364d90820182614fb8565b82355f90815260038601602052604090209161366a919083615019565b50604080850151855163ffffffff9081165f908152600d602090815284822080549415156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff90951694909417909355606088015188518316825284822080549115156a0100000000000000000000027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff9092169190911790556080880151885183168252848220805460ff9290921668010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909216919091179055828801805189518416835294909120805494909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff909416939093179055855191516137f592918435908c908c906137bc90880188614fb8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250613c4492505050565b50600101613401565b50815160208084015160405163ffffffff91821681529216917ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a2505050505050565b5f612cec8383613d1e565b60605f612cec83613d6a565b608081015173ffffffffffffffffffffffffffffffffffffffff1615613903576138af81608001517f78bea72100000000000000000000000000000000000000000000000000000000613dc3565b6139035760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610602565b5f828152600260205260409020815182919081906139219082614cc7565b50602082015160018201906139369082614cc7565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360038111156139785761397861474b565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101008360018111156139bf576139bf61474b565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae905f90a25050565b3373ffffffffffffffffffffffffffffffffffffffff821603613ac6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610602565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8381169182179092555f8054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b5f825f018281548110613b5057613b50614963565b905f5260205f200154905092915050565b5f8181526001830160205260408120548015613c3b575f613b8360018361512f565b85549091505f90613b969060019061512f565b9050818114613bf5575f865f018281548110613bb457613bb4614963565b905f5260205f200154905080875f018481548110613bd457613bd4614963565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080613c0657613c06615142565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610617565b5f915050610617565b5f848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff16156127cc575f84815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c90613ce9908690869086908b908d9060040161516f565b5f604051808303815f87803b158015613d00575f80fd5b505af1158015613d12573d5f803e3d5ffd5b50505050505050505050565b5f818152600183016020526040812054613d6357508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610617565b505f610617565b6060815f01805480602002602001604051908101604052809291908181526020018280548015613db757602002820191905f5260205f20905b815481526020019060010190808311613da3575b50505050509050919050565b5f613dcd83613dde565b8015612cec5750612cec8383613e41565b5f613e09827f01ffc9a700000000000000000000000000000000000000000000000000000000613e41565b80156106175750613e3a827fffffffff00000000000000000000000000000000000000000000000000000000613e41565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017815282515f9392849283928392918391908a617530fa92503d91505f519050828015613ef7575060208210155b8015613f0257505f81115b979650505050505050565b508054613f1990614a11565b5f825580601f10613f28575050565b601f0160209004905f5260205f2090810190612cd69190613f5b565b5080545f8255905f5260205f2090810190612cd691905b5b80821115613f6f575f8155600101613f5c565b5090565b5f8083601f840112613f83575f80fd5b50813567ffffffffffffffff811115613f9a575f80fd5b6020830191508360208260051b8501011115611a20575f80fd5b5f8060208385031215613fc5575f80fd5b823567ffffffffffffffff811115613fdb575f80fd5b613fe785828601613f73565b90969095509350505050565b5f815180845260208085019450602084015f5b8381101561402257815187529582019590820190600101614006565b509495945050505050565b5f61010063ffffffff80845116855280602085015116602086015280604085015116604086015250606083015160608501526080830151608085015260a083015160a085015260c08301518160c086015261408a82860182613ff3565b91505060e083015184820360e08601526140a48282613ff3565b95945050505050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261410e85835161402d565b945092850192908501906001016140d4565b5092979650505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160a0810167ffffffffffffffff8111828210171561417d5761417d61412d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156141ca576141ca61412d565b604052919050565b5f67ffffffffffffffff8211156141eb576141eb61412d565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112614226575f80fd5b8135614239614234826141d2565b614183565b81815284602083860101111561424d575f80fd5b816020850160208301375f918101602001919091529392505050565b5f806040838503121561427a575f80fd5b823567ffffffffffffffff80821115614291575f80fd5b61429d86838701614217565b935060208501359150808211156142b2575f80fd5b506142bf85828601614217565b9150509250929050565b5f602082840312156142d9575f80fd5b5035919050565b5f5b838110156142fa5781810151838201526020016142e2565b50505f910152565b5f81518084526143198160208601602086016142e0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f612cec6020830184614302565b5f82825180855260208086019550808260051b8401018186015f5b848110156143d8578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051845284015160408585018190526143c481860183614302565b9a86019a9450505090830190600101614378565b5090979650505050505050565b5f63ffffffff8083511684528060208401511660208501525060ff604083015116604084015260608201511515606084015260808201511515608084015260a082015160e060a085015261443c60e0850182613ff3565b905060c083015184820360c08601526140a4828261435d565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526144b68583516143e5565b9450928501929085019060010161447c565b803563ffffffff811681146144db575f80fd5b919050565b5f602082840312156144f0575f80fd5b612cec826144c8565b73ffffffffffffffffffffffffffffffffffffffff81511682525f60208201516040602085015261452d6040850182614302565b949350505050565b602081525f612cec60208301846144f9565b602081525f612cec60208301846143e5565b803580151581146144db575f80fd5b803560ff811681146144db575f80fd5b5f805f805f805f60a0888a03121561458e575f80fd5b614597886144c8565b9650602088013567ffffffffffffffff808211156145b3575f80fd5b6145bf8b838c01613f73565b909850965060408a01359150808211156145d7575f80fd5b506145e48a828b01613f73565b90955093506145f7905060608901614559565b915061460560808901614568565b905092959891949750929550565b5f8060408385031215614624575f80fd5b61462d836144c8565b946020939093013593505050565b604081525f61464d6040830185614302565b82810360208401526140a48185614302565b602081525f612cec602083018461402d565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526146d28583516144f9565b94509285019290850190600101614698565b5f805f80604085870312156146f7575f80fd5b843567ffffffffffffffff8082111561470e575f80fd5b61471a88838901613f73565b90965094506020870135915080821115614732575f80fd5b5061473f87828801613f73565b95989497509550505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b805182525f602082015160e0602085015261479660e0850182614302565b9050604083015184820360408601526147af8282614302565b9150506060830151600481106147c7576147c761474b565b60608501526080830151600281106147e1576147e161474b565b8060808601525060a083015161480f60a086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015161061360c086018215159052565b602081525f612cec6020830184614778565b5f805f805f805f60a0888a03121561484b575f80fd5b873567ffffffffffffffff80821115614862575f80fd5b61486e8b838c01613f73565b909950975060208a0135915080821115614886575f80fd5b506148938a828b01613f73565b90965094506148a6905060408901614559565b92506145f760608901614559565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614915858351614778565b945092850192908501906001016148db565b803573ffffffffffffffffffffffffffffffffffffffff811681146144db575f80fd5b5f6020828403121561495a575f80fd5b612cec82614927565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b63ffffffff8281168282160390808211156109ac576109ac614990565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614a0a57614a0a614990565b5060010190565b600181811c90821680614a2557607f821691505b602082108103614a5c577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f63ffffffff808316818103614a7a57614a7a614990565b6001019392505050565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112614ab6575f80fd5b9190910192915050565b5f60a08236031215614ad0575f80fd5b614ad861415a565b614ae1836144c8565b8152602080840135818301526040840135604083015260608401356060830152608084013567ffffffffffffffff80821115614b1b575f80fd5b9085019036601f830112614b2d575f80fd5b813581811115614b3f57614b3f61412d565b8060051b9150614b50848301614183565b8181529183018401918481019036841115614b69575f80fd5b938501935b83851015614b8757843582529385019390850190614b6e565b608087015250939695505050505050565b602080825282518282018190525f9190848201906040850190845b81811015614bcf57835183529284019291840191600101614bb3565b50909695505050505050565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112614ab6575f80fd5b5f60408236031215614c1d575f80fd5b6040516040810167ffffffffffffffff8282108183111715614c4157614c4161412d565b81604052614c4e85614927565b83526020850135915080821115614c63575f80fd5b50614c7036828601614217565b60208301525092915050565b601f82111561085557805f5260205f20601f840160051c81016020851015614ca15750805b601f840160051c820191505b81811015614cc0575f8155600101614cad565b5050505050565b815167ffffffffffffffff811115614ce157614ce161412d565b614cf581614cef8454614a11565b84614c7c565b602080601f831160018114614d47575f8415614d115750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556127cc565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614d9357888601518255948401946001909101908401614d74565b5085821015614dcf57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b5f60208284031215614def575f80fd5b815167ffffffffffffffff811115614e05575f80fd5b8201601f81018413614e15575f80fd5b8051614e23614234826141d2565b818152856020838501011115614e37575f80fd5b6140a48260208301602086016142e0565b8035600281106144db575f80fd5b5f60a08236031215614e66575f80fd5b614e6e61415a565b823567ffffffffffffffff80821115614e85575f80fd5b614e9136838701614217565b83526020850135915080821115614ea6575f80fd5b50614eb336828601614217565b602083015250604083013560048110614eca575f80fd5b6040820152614edb60608401614e48565b6060820152614eec60808401614927565b608082015292915050565b5f60208083525f8454614f0981614a11565b806020870152604060018084165f8114614f2a5760018114614f6457614f91565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a01019550614f91565b895f5260205f205f5b85811015614f885781548b8201860152908301908801614f6d565b8a016040019650505b509398975050505050505050565b60ff818116838216019081111561061757610617614990565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614feb575f80fd5b83018035915067ffffffffffffffff821115615005575f80fd5b602001915036819003821315611a20575f80fd5b67ffffffffffffffff8311156150315761503161412d565b6150458361503f8354614a11565b83614c7c565b5f601f841160018114615095575f851561505f5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614cc0565b5f838152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08716915b828110156150e257868501358255602094850194600190920191016150c2565b508682101561511d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b8181038181111561061757610617614990565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b608081528460808201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8611156151a6575f80fd5b8560051b808860a0850137820182810360a090810160208501526151cc90820187614302565b91505063ffffffff8085166040840152808416606084015250969550505050505056fea164736f6c6343000818000a

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

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