Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 8 from a total of 8 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Add DON | 21925505 | 397 days ago | IN | 0 ETH | 0.00101892 | ||||
| Add DON | 21925503 | 397 days ago | IN | 0 ETH | 0.00284959 | ||||
| Add DON | 21925502 | 397 days ago | IN | 0 ETH | 0.00188454 | ||||
| Add DON | 21925501 | 397 days ago | IN | 0 ETH | 0.00142728 | ||||
| Add Nodes | 21925429 | 397 days ago | IN | 0 ETH | 0.00264853 | ||||
| Add Nodes | 21925074 | 397 days ago | IN | 0 ETH | 0.01740676 | ||||
| Add Node Operato... | 21925032 | 397 days ago | IN | 0 ETH | 0.00128416 | ||||
| Add Capabilities | 21925025 | 397 days ago | IN | 0 ETH | 0.00101797 |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
CapabilitiesRegistry
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// 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
});
}
}// 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;
}// 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);
}// 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;
}{
"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
- No Contract Security Audit Submitted- Submit Audit Here
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"}]Contract Creation Code
6080604052600e80546001600160401b03191664010000000117905534801562000027575f80fd5b5033805f816200007e5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b5f80546001600160a01b0319166001600160a01b0384811691909117909155811615620000b057620000b081620000b9565b50505062000163565b336001600160a01b03821603620001135760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000075565b600180546001600160a01b0319166001600160a01b038381169182179092555f8054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6151fc80620001715f395ff3fe608060405234801561000f575f80fd5b50600436106101bb575f3560e01c806350c946fe116100f35780638da5cb5b11610093578063ddbe4f821161006e578063ddbe4f8214610442578063e29581aa14610457578063f2fde38b1461045f578063fcdc8efe14610472575f80fd5b80638da5cb5b146103e85780639cb7c5f41461040f578063d8bc7b681461042f575f80fd5b8063715f5295116100ce578063715f5295146103a757806379ba5097146103ba57806384f5ed8a146103c257806386fa4246146103d5575f80fd5b806350c946fe1461035f5780635d83d9671461037f57806366acaa3314610392575f80fd5b8063235374051161015e5780632c01a1e8116101395780632c01a1e814610305578063358039f414610318578063398f37731461032b5780633f2a13c91461033e575f80fd5b806323537405146102bf578063275459f2146102df5780632a852933146102f2575f80fd5b8063181f5a7711610199578063181f5a771461022c5780631d05394c14610275578063214502431461028a57806322bdbcbc1461029f575f80fd5b806305a51966146101bf5780630fe5800a146101e85780631257001114610209575b5f80fd5b6101d26101cd366004613fb4565b610498565b6040516101df91906140ad565b60405180910390f35b6101fb6101f6366004614269565b61061d565b6040519081526020016101df565b61021c6102173660046142c9565b61064f565b60405190151581526020016101df565b6102686040518060400160405280601a81526020017f4361706162696c6974696573526567697374727920312e312e3000000000000081525081565b6040516101df919061434b565b610288610283366004613fb4565b61065b565b005b61029261085a565b6040516101df9190614455565b6102b26102ad3660046144e0565b6109b3565b6040516101df9190614535565b6102d26102cd3660046144e0565b610a9c565b6040516101df9190614547565b6102886102ed366004613fb4565b610adf565b610288610300366004614578565b610bb2565b610288610313366004613fb4565b610c91565b610288610326366004613fb4565b610f2e565b610288610339366004613fb4565b61168a565b61035161034c366004614613565b611844565b6040516101df92919061463b565b61037261036d3660046142c9565b611a27565b6040516101df919061465f565b61028861038d366004613fb4565b611b10565b61039a611c02565b6040516101df9190614671565b6102886103b5366004613fb4565b611dde565b610288611e8c565b6102886103d0366004613fb4565b611f88565b6102886103e33660046146e4565b612499565b5f5460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101df565b61042261041d3660046142c9565b6127d4565b6040516101df9190614823565b61028861043d366004614835565b612a02565b61044a612aca565b6040516101df91906148b4565b6101d2612bb8565b61028861046d36600461494a565b612cc5565b600e54640100000000900463ffffffff1660405163ffffffff90911681526020016101df565b60605f8267ffffffffffffffff8111156104b4576104b461412d565b60405190808252806020026020018201604052801561054257816020015b60408051610100810182525f808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816104d25790505b5090505f5b838110156106135761057085858381811061056457610564614963565b90506020020135611a27565b82828151811061058257610582614963565b60200260200101819052505f8019168282815181106105a3576105a3614963565b6020026020010151608001510361060b578484828181106105c6576105c6614963565b905060200201356040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b60405180910390fd5b600101610547565b5090505b92915050565b5f828260405160200161063192919061463b565b60405160208183030381529060405280519060200120905092915050565b5f610617600583612cd9565b610663612cf3565b5f5b81811015610855575f83838381811061068057610680614963565b905060200201602081019061069591906144e0565b63ffffffff8181165f908152600d60209081526040808320805464010000000081049095168085526001820190935290832094955093909290916a010000000000000000000090910460ff16905b6106ec83612d75565b81101561078857811561074057600c5f6107068584612d7e565b815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff169055610780565b61077e8663ffffffff16600c5f6107608588612d7e90919063ffffffff16565b81526020019081526020015f20600501612d8990919063ffffffff16565b505b6001016106e3565b508354640100000000900463ffffffff165f036107d9576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff86166004820152602401610602565b63ffffffff85165f818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffff0000000000000000000000169055519182527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a25050505050806001019050610665565b505050565b600e54606090640100000000900463ffffffff165f61087a6001836149bd565b63ffffffff1667ffffffffffffffff8111156108985761089861412d565b60405190808252806020026020018201604052801561091e57816020015b6040805160e0810182525f80825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816108b65790505b5090505f60015b8363ffffffff168163ffffffff1610156109905763ffffffff8082165f908152600d602052604090205416156109885761095e81612d94565b83838151811061097057610970614963565b602002602001018190525081610985906149da565b91505b600101610925565b5061099c6001846149bd565b63ffffffff1681146109ac578082525b5092915050565b604080518082019091525f81526060602082015263ffffffff82165f908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610a1590614a11565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4190614a11565b8015610a8c5780601f10610a6357610100808354040283529160200191610a8c565b820191905f5260205f20905b815481529060010190602001808311610a6f57829003601f168201915b5050505050815250509050919050565b6040805160e0810182525f808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261061782612d94565b610ae7612cf3565b5f5b63ffffffff8116821115610855575f83838363ffffffff16818110610b1057610b10614963565b9050602002016020810190610b2591906144e0565b63ffffffff81165f908152600b6020526040812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155919250610b6f6001830182613f0d565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a905f90a250610bab81614a62565b9050610ae9565b610bba612cf3565b63ffffffff8088165f908152600d60205260408120805490926401000000009091041690819003610c1f576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a166004820152602401610602565b610c86888888886040518060a001604052808f63ffffffff16815260200187610c4790614a62565b63ffffffff811682528b15156020830152895460ff6a01000000000000000000009091048116151560408401528b166060909201919091529650613054565b505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f28575f848483818110610cc957610cc9614963565b602090810292909201355f818152600c90935260409092206001810154929350919050610d25576040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260048101839052602401610602565b5f610d3282600501612d75565b1115610d8757610d456005820184612d7e565b6040517f60a6d89800000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101839052604401610602565b805468010000000000000000900463ffffffff1615610def5780546040517f60b9df730000000000000000000000000000000000000000000000000000000081526801000000000000000090910463ffffffff16600482015260248101839052604401610602565b83158015610e285750805463ffffffff165f908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610e61576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b6001810154610e7290600790612d89565b506002810154610e8490600990612d89565b505f828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001681556001810182905560028101829055600381018290559060058201818181610edf8282613f44565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610f1691815260200190565b60405180910390a15050600101610cae565b50505050565b5f805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f28575f848483818110610f6657610f66614963565b9050602002810190610f789190614a84565b610f8190614ac0565b6040808201515f908152600c6020908152828220805463ffffffff168352600b82528383208451808601909552805473ffffffffffffffffffffffffffffffffffffffff1685526001810180549697509195939493909284019190610fe590614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461101190614a11565b801561105c5780601f106110335761010080835404028352916020019161105c565b820191905f5260205f20905b81548152906001019060200180831161103f57829003601f168201915b5050509190925250505060018301549091506110ac5782604001516040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b841580156110d15750805173ffffffffffffffffffffffffffffffffffffffff163314155b1561110a576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b6020830151611145576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001820154602084015181146111c657602084015161116690600790612cd9565b1561119d576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084015160018401556111b2600782612d89565b5060208401516111c49060079061384a565b505b60608401516112095783606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b608084015180515f0361124a57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b83545f90859060049061126a90640100000000900463ffffffff16614a62565b91906101000a81548163ffffffff021916908363ffffffff160217905590505f5b825181101561134c576112c18382815181106112a9576112a9614963565b60200260200101516003612cd990919063ffffffff16565b6112f957826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b61134383828151811061130e5761130e614963565b6020026020010151876004015f8563ffffffff1663ffffffff1681526020019081526020015f2061384a90919063ffffffff16565b5060010161128b565b50845468010000000000000000900463ffffffff1680156114a75763ffffffff8082165f908152600d6020908152604080832080546401000000009004909416835260019093018152828220600201805484518184028101840190955280855292939290918301828280156113de57602002820191905f5260205f20905b8154815260200190600101908083116113ca575b505050505090505f5b81518110156114a45761143a82828151811061140557611405614963565b6020026020010151896004015f8763ffffffff1663ffffffff1681526020019081526020015f20612cd990919063ffffffff16565b61149c5781818151811061145057611450614963565b6020026020010151836040517f03dcd86200000000000000000000000000000000000000000000000000000000815260040161060292919091825263ffffffff16602082015260400190565b6001016113e7565b50505b5f6114b487600501613855565b90505f5b81518163ffffffff1610156115f2575f828263ffffffff16815181106114e0576114e0614963565b60209081029190910181015163ffffffff8082165f908152600d8452604080822080546401000000009004909316825260019092018452818120600201805483518187028101870190945280845293955090939192909183018282801561156457602002820191905f5260205f20905b815481526020019060010190808311611550575b505050505090505f5b81518110156115de576115c082828151811061158b5761158b614963565b60200260200101518c6004015f8a63ffffffff1663ffffffff1681526020019081526020015f20612cd990919063ffffffff16565b6115d65781818151811061145057611450614963565b60010161156d565b505050806115eb90614a62565b90506114b8565b50875187547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90911690811788556040808a015160028a0181905560608b015160038b01556020808c01518351928352908201527f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a25050505050505050806001019050610f4b565b611692612cf3565b5f5b81811015610855575f8383838181106116af576116af614963565b90506020028101906116c19190614bdb565b6116ca90614c0d565b805190915073ffffffffffffffffffffffffffffffffffffffff1661171b576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095165f818152600b909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815592519192909160018201906117a69082614cc7565b5050600e80549091505f906117c09063ffffffff16614a62565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e8460200151604051611832919061434b565b60405180910390a35050600101611694565b63ffffffff8083165f908152600d6020908152604080832080546401000000009004909416808452600190940182528083208584526003019091528120805460609384939092909161189590614a11565b80601f01602080910402602001604051908101604052809291908181526020018280546118c190614a11565b801561190c5780601f106118e35761010080835404028352916020019161190c565b820191905f5260205f20905b8154815290600101906020018083116118ef57829003601f168201915b5050505f888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff16159150611a199050575f86815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d906024015f60405180830381865afa1580156119d1573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a169190810190614ddf565b90505b9093509150505b9250929050565b60408051610100810182525f8082526020820181905291810182905260608082018390526080820183905260a082019290925260c0810182905260e081019190915260408051610100810182525f848152600c6020908152838220805463ffffffff8082168652640100000000820481168487018190526801000000000000000090920416858701526001820154606086015260028201546080860152600382015460a0860152835260040190529190912060c0820190611ae790613855565b8152602001611b08600c5f8681526020019081526020015f20600501613855565b905292915050565b611b18612cf3565b5f5b81811015610855575f838383818110611b3557611b35614963565b905060200201359050611b52816003612cd990919063ffffffff16565b611b8b576040517fe181733f00000000000000000000000000000000000000000000000000000000815260048101829052602401610602565b611b9660058261384a565b611bcf576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815260048101829052602401610602565b60405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf21905f90a250600101611b1a565b600e5460609063ffffffff165f611c1a6001836149bd565b63ffffffff1667ffffffffffffffff811115611c3857611c3861412d565b604051908082528060200260200182016040528015611c7d57816020015b604080518082019091525f815260606020820152815260200190600190039081611c565790505b5090505f60015b8363ffffffff168163ffffffff161015611dc85763ffffffff81165f908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611dc05763ffffffff81165f908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191611d1690614a11565b80601f0160208091040260200160405190810160405280929190818152602001828054611d4290614a11565b8015611d8d5780601f10611d6457610100808354040283529160200191611d8d565b820191905f5260205f20905b815481529060010190602001808311611d7057829003601f168201915b505050505081525050838381518110611da857611da8614963565b602002602001018190525081611dbd906149da565b91505b600101611c84565b50600e5461099c9060019063ffffffff166149bd565b611de6612cf3565b5f5b81811015610855575f838383818110611e0357611e03614963565b9050602002810190611e159190614a84565b611e1e90614e56565b90505f611e32825f0151836020015161061d565b9050611e3f60038261384a565b611e78576040517febf5255100000000000000000000000000000000000000000000000000000000815260048101829052602401610602565b611e828183613861565b5050600101611de8565b60015473ffffffffffffffffffffffffffffffffffffffff163314611f0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610602565b5f8054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b5f805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f28575f848483818110611fc057611fc0614963565b9050602002810190611fd29190614a84565b611fdb90614ac0565b805163ffffffff165f908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff16825260018101805495965093949193909284019161203090614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461205c90614a11565b80156120a75780601f1061207e576101008083540402835291602001916120a7565b820191905f5260205f20905b81548152906001019060200180831161208a57829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff1661210d5781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610602565b831580156121325750805173ffffffffffffffffffffffffffffffffffffffff163314155b1561216b576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b6040808301515f908152600c602052206001810154156121bf5782604001516040517f5461848300000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b60408301516122025782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b6020830151158061221f5750602083015161221f90600790612cd9565b15612256576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301516122995782606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b608083015180515f036122da57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b815482906004906122f890640100000000900463ffffffff16614a62565b82546101009290920a63ffffffff81810219909316918316021790915582546401000000009004165f5b82518110156123cb576123408382815181106112a9576112a9614963565b61237857826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b6123c283828151811061238d5761238d614963565b6020026020010151856004015f8563ffffffff1663ffffffff1681526020019081526020015f2061384a90919063ffffffff16565b50600101612322565b5060608501516003840155845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9182161784556040860151600285015560208601516001850181905561242b916007919061384a16565b50604085015161243d9060099061384a565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a25050505050806001019050611fa5565b8281146124dc576040517fab8b67c60000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610602565b5f805473ffffffffffffffffffffffffffffffffffffffff16905b848110156127cc575f86868381811061251257612512614963565b905060200201602081019061252791906144e0565b63ffffffff81165f908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff16612595576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610602565b5f8686858181106125a8576125a8614963565b90506020028101906125ba9190614bdb565b6125c390614c0d565b805190915073ffffffffffffffffffffffffffffffffffffffff16612614576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815473ffffffffffffffffffffffffffffffffffffffff16331480159061265157503373ffffffffffffffffffffffffffffffffffffffff861614155b1561268a576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b8051825473ffffffffffffffffffffffffffffffffffffffff908116911614158061270657506020808201516040516126c3920161434b565b60405160208183030381529060405280519060200120826001016040516020016126ed9190614ef7565b6040516020818303038152906040528051906020012014155b156127be57805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602081015160018301906127609082614cc7565b50805f015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a2883602001516040516127b5919061434b565b60405180910390a35b5050508060010190506124f7565b505050505050565b6128126040805160e0810182525f808252606060208301819052928201839052909182019081526020015f81525f6020820181905260409091015290565b6040805160e0810182528381525f848152600260209081529290208054919283019161283d90614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461286990614a11565b80156128b45780601f1061288b576101008083540402835291602001916128b4565b820191905f5260205f20905b81548152906001019060200180831161289757829003601f168201915b5050505050815260200160025f8581526020019081526020015f2060010180546128dd90614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461290990614a11565b80156129545780601f1061292b57610100808354040283529160200191612954565b820191905f5260205f20905b81548152906001019060200180831161293757829003601f168201915b50505091835250505f848152600260208181526040909220015491019060ff1660038111156129855761298561474b565b81525f8481526002602081815260409092200154910190610100900460ff1660018111156129b5576129b561474b565b81525f848152600260208181526040928390209091015462010000900473ffffffffffffffffffffffffffffffffffffffff1690830152016129f8600585612cd9565b1515905292915050565b612a0a612cf3565b600e80545f9164010000000090910463ffffffff16906004612a2b83614a62565b82546101009290920a63ffffffff81810219909316918316021790915581165f818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a08101835292835260019083015286151590820152841515606082015260ff84166080820152909150612ac0908990899089908990613054565b5050505050505050565b60605f612ad76003613855565b90505f815167ffffffffffffffff811115612af457612af461412d565b604051908082528060200260200182016040528015612b6357816020015b612b506040805160e0810182525f808252606060208301819052928201839052909182019081526020015f81525f6020820181905260409091015290565b815260200190600190039081612b125790505b5090505f5b82518110156109ac57612b93838281518110612b8657612b86614963565b60200260200101516127d4565b828281518110612ba557612ba5614963565b6020908102919091010152600101612b68565b60605f612bc56009613855565b90505f815167ffffffffffffffff811115612be257612be261412d565b604051908082528060200260200182016040528015612c7057816020015b60408051610100810182525f808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181612c005790505b5090505f5b82518110156109ac57612ca0838281518110612c9357612c93614963565b6020026020010151611a27565b828281518110612cb257612cb2614963565b6020908102919091010152600101612c75565b612ccd612cf3565b612cd681613a47565b50565b5f81815260018301602052604081205415155b9392505050565b5f5473ffffffffffffffffffffffffffffffffffffffff163314612d73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610602565b565b5f610617825490565b5f612cec8383613b3b565b5f612cec8383613b61565b6040805160e0810182525f808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d8252848320805464010000000090049091168084526001909101825284832060028101805487518186028101860190985280885295969295919493909190830182828015612e4257602002820191905f5260205f20905b815481526020019060010190808311612e2e575b505050505090505f815167ffffffffffffffff811115612e6457612e6461412d565b604051908082528060200260200182016040528015612ea957816020015b604080518082019091525f815260606020820152815260200190600190039081612e825790505b5090505f5b8151811015612fbc576040518060400160405280848381518110612ed457612ed4614963565b60200260200101518152602001856003015f868581518110612ef857612ef8614963565b602002602001015181526020019081526020015f208054612f1890614a11565b80601f0160208091040260200160405190810160405280929190818152602001828054612f4490614a11565b8015612f8f5780601f10612f6657610100808354040283529160200191612f8f565b820191905f5260205f20905b815481529060010190602001808311612f7257829003601f168201915b5050505050815250828281518110612fa957612fa9614963565b6020908102919091010152600101612eae565b506040805160e08101825263ffffffff8089165f818152600d6020818152868320548086168752948b168187015260ff680100000000000000008604811697870197909752690100000000000000000085048716151560608701529290915290526a010000000000000000000090049091161515608082015260a0810161304285613855565b81526020019190915295945050505050565b805163ffffffff9081165f908152600d602090815260408083208286015190941683526001909301905220608082015160ff1615806130a55750608082015185906130a0906001614f9f565b60ff16115b156130ee5760808201516040517f25b4d61800000000000000000000000000000000000000000000000000000000815260ff909116600482015260248101869052604401610602565b6001826020015163ffffffff1611156131ce57815163ffffffff165f908152600d60209081526040822090840151600191820191839161312e91906149bd565b63ffffffff1663ffffffff1681526020019081526020015f2090505f5b61315482612d75565b8110156131cb57613180845f015163ffffffff16600c5f61076085875f01612d7e90919063ffffffff16565b50600c5f61318e8484612d7e565b815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16905560010161314b565b50505b5f5b858110156133fe576131fd8787838181106131ed576131ed614963565b859260209091020135905061384a565b61325e57825187878381811061321557613215614963565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610602565b8260600151156133ae57825163ffffffff16600c5f89898581811061328557613285614963565b602090810292909201358352508101919091526040015f205468010000000000000000900463ffffffff16148015906132fc5750600c5f8888848181106132ce576132ce614963565b602090810292909201358352508101919091526040015f205468010000000000000000900463ffffffff1615155b1561335e57825187878381811061331557613315614963565b6040517f60b9df7300000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610602565b8251600c5f89898581811061337557613375614963565b9050602002013581526020019081526020015f205f0160086101000a81548163ffffffff021916908363ffffffff1602179055506133f6565b82516133f49063ffffffff16600c5f8a8a868181106133cf576133cf614963565b9050602002013581526020019081526020015f2060050161384a90919063ffffffff16565b505b6001016131d0565b505f5b838110156137fe573685858381811061341c5761341c614963565b905060200281019061342e9190614bdb565b905061343c60038235612cd9565b613475576040517fe181733f00000000000000000000000000000000000000000000000000000000815281356004820152602401610602565b61348160058235612cd9565b156134bb576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815281356004820152602401610602565b80355f908152600384016020526040812080546134d790614a11565b905011156135235783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015281356024820152604401610602565b5f5b87811015613625576135c28235600c5f8c8c8681811061354757613547614963565b9050602002013581526020019081526020015f206004015f600c5f8e8e8881811061357457613574614963565b9050602002013581526020019081526020015f205f0160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020019081526020015f20612cd990919063ffffffff16565b61361d578888828181106135d8576135d8614963565b6040517fa7e792500000000000000000000000000000000000000000000000000000000081526020909102929092013560048301525082356024820152604401610602565b600101613525565b506002830180546001810182555f918252602091829020833591015561364d90820182614fb8565b82355f90815260038601602052604090209161366a919083615019565b50604080850151855163ffffffff9081165f908152600d602090815284822080549415156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff90951694909417909355606088015188518316825284822080549115156a0100000000000000000000027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff9092169190911790556080880151885183168252848220805460ff9290921668010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909216919091179055828801805189518416835294909120805494909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff909416939093179055855191516137f592918435908c908c906137bc90880188614fb8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250613c4492505050565b50600101613401565b50815160208084015160405163ffffffff91821681529216917ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a2505050505050565b5f612cec8383613d1e565b60605f612cec83613d6a565b608081015173ffffffffffffffffffffffffffffffffffffffff1615613903576138af81608001517f78bea72100000000000000000000000000000000000000000000000000000000613dc3565b6139035760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610602565b5f828152600260205260409020815182919081906139219082614cc7565b50602082015160018201906139369082614cc7565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360038111156139785761397861474b565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101008360018111156139bf576139bf61474b565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae905f90a25050565b3373ffffffffffffffffffffffffffffffffffffffff821603613ac6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610602565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8381169182179092555f8054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b5f825f018281548110613b5057613b50614963565b905f5260205f200154905092915050565b5f8181526001830160205260408120548015613c3b575f613b8360018361512f565b85549091505f90613b969060019061512f565b9050818114613bf5575f865f018281548110613bb457613bb4614963565b905f5260205f200154905080875f018481548110613bd457613bd4614963565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080613c0657613c06615142565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610617565b5f915050610617565b5f848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff16156127cc575f84815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c90613ce9908690869086908b908d9060040161516f565b5f604051808303815f87803b158015613d00575f80fd5b505af1158015613d12573d5f803e3d5ffd5b50505050505050505050565b5f818152600183016020526040812054613d6357508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610617565b505f610617565b6060815f01805480602002602001604051908101604052809291908181526020018280548015613db757602002820191905f5260205f20905b815481526020019060010190808311613da3575b50505050509050919050565b5f613dcd83613dde565b8015612cec5750612cec8383613e41565b5f613e09827f01ffc9a700000000000000000000000000000000000000000000000000000000613e41565b80156106175750613e3a827fffffffff00000000000000000000000000000000000000000000000000000000613e41565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017815282515f9392849283928392918391908a617530fa92503d91505f519050828015613ef7575060208210155b8015613f0257505f81115b979650505050505050565b508054613f1990614a11565b5f825580601f10613f28575050565b601f0160209004905f5260205f2090810190612cd69190613f5b565b5080545f8255905f5260205f2090810190612cd691905b5b80821115613f6f575f8155600101613f5c565b5090565b5f8083601f840112613f83575f80fd5b50813567ffffffffffffffff811115613f9a575f80fd5b6020830191508360208260051b8501011115611a20575f80fd5b5f8060208385031215613fc5575f80fd5b823567ffffffffffffffff811115613fdb575f80fd5b613fe785828601613f73565b90969095509350505050565b5f815180845260208085019450602084015f5b8381101561402257815187529582019590820190600101614006565b509495945050505050565b5f61010063ffffffff80845116855280602085015116602086015280604085015116604086015250606083015160608501526080830151608085015260a083015160a085015260c08301518160c086015261408a82860182613ff3565b91505060e083015184820360e08601526140a48282613ff3565b95945050505050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261410e85835161402d565b945092850192908501906001016140d4565b5092979650505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160a0810167ffffffffffffffff8111828210171561417d5761417d61412d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156141ca576141ca61412d565b604052919050565b5f67ffffffffffffffff8211156141eb576141eb61412d565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112614226575f80fd5b8135614239614234826141d2565b614183565b81815284602083860101111561424d575f80fd5b816020850160208301375f918101602001919091529392505050565b5f806040838503121561427a575f80fd5b823567ffffffffffffffff80821115614291575f80fd5b61429d86838701614217565b935060208501359150808211156142b2575f80fd5b506142bf85828601614217565b9150509250929050565b5f602082840312156142d9575f80fd5b5035919050565b5f5b838110156142fa5781810151838201526020016142e2565b50505f910152565b5f81518084526143198160208601602086016142e0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f612cec6020830184614302565b5f82825180855260208086019550808260051b8401018186015f5b848110156143d8578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051845284015160408585018190526143c481860183614302565b9a86019a9450505090830190600101614378565b5090979650505050505050565b5f63ffffffff8083511684528060208401511660208501525060ff604083015116604084015260608201511515606084015260808201511515608084015260a082015160e060a085015261443c60e0850182613ff3565b905060c083015184820360c08601526140a4828261435d565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526144b68583516143e5565b9450928501929085019060010161447c565b803563ffffffff811681146144db575f80fd5b919050565b5f602082840312156144f0575f80fd5b612cec826144c8565b73ffffffffffffffffffffffffffffffffffffffff81511682525f60208201516040602085015261452d6040850182614302565b949350505050565b602081525f612cec60208301846144f9565b602081525f612cec60208301846143e5565b803580151581146144db575f80fd5b803560ff811681146144db575f80fd5b5f805f805f805f60a0888a03121561458e575f80fd5b614597886144c8565b9650602088013567ffffffffffffffff808211156145b3575f80fd5b6145bf8b838c01613f73565b909850965060408a01359150808211156145d7575f80fd5b506145e48a828b01613f73565b90955093506145f7905060608901614559565b915061460560808901614568565b905092959891949750929550565b5f8060408385031215614624575f80fd5b61462d836144c8565b946020939093013593505050565b604081525f61464d6040830185614302565b82810360208401526140a48185614302565b602081525f612cec602083018461402d565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526146d28583516144f9565b94509285019290850190600101614698565b5f805f80604085870312156146f7575f80fd5b843567ffffffffffffffff8082111561470e575f80fd5b61471a88838901613f73565b90965094506020870135915080821115614732575f80fd5b5061473f87828801613f73565b95989497509550505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b805182525f602082015160e0602085015261479660e0850182614302565b9050604083015184820360408601526147af8282614302565b9150506060830151600481106147c7576147c761474b565b60608501526080830151600281106147e1576147e161474b565b8060808601525060a083015161480f60a086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015161061360c086018215159052565b602081525f612cec6020830184614778565b5f805f805f805f60a0888a03121561484b575f80fd5b873567ffffffffffffffff80821115614862575f80fd5b61486e8b838c01613f73565b909950975060208a0135915080821115614886575f80fd5b506148938a828b01613f73565b90965094506148a6905060408901614559565b92506145f760608901614559565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614915858351614778565b945092850192908501906001016148db565b803573ffffffffffffffffffffffffffffffffffffffff811681146144db575f80fd5b5f6020828403121561495a575f80fd5b612cec82614927565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b63ffffffff8281168282160390808211156109ac576109ac614990565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614a0a57614a0a614990565b5060010190565b600181811c90821680614a2557607f821691505b602082108103614a5c577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f63ffffffff808316818103614a7a57614a7a614990565b6001019392505050565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112614ab6575f80fd5b9190910192915050565b5f60a08236031215614ad0575f80fd5b614ad861415a565b614ae1836144c8565b8152602080840135818301526040840135604083015260608401356060830152608084013567ffffffffffffffff80821115614b1b575f80fd5b9085019036601f830112614b2d575f80fd5b813581811115614b3f57614b3f61412d565b8060051b9150614b50848301614183565b8181529183018401918481019036841115614b69575f80fd5b938501935b83851015614b8757843582529385019390850190614b6e565b608087015250939695505050505050565b602080825282518282018190525f9190848201906040850190845b81811015614bcf57835183529284019291840191600101614bb3565b50909695505050505050565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112614ab6575f80fd5b5f60408236031215614c1d575f80fd5b6040516040810167ffffffffffffffff8282108183111715614c4157614c4161412d565b81604052614c4e85614927565b83526020850135915080821115614c63575f80fd5b50614c7036828601614217565b60208301525092915050565b601f82111561085557805f5260205f20601f840160051c81016020851015614ca15750805b601f840160051c820191505b81811015614cc0575f8155600101614cad565b5050505050565b815167ffffffffffffffff811115614ce157614ce161412d565b614cf581614cef8454614a11565b84614c7c565b602080601f831160018114614d47575f8415614d115750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556127cc565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614d9357888601518255948401946001909101908401614d74565b5085821015614dcf57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b5f60208284031215614def575f80fd5b815167ffffffffffffffff811115614e05575f80fd5b8201601f81018413614e15575f80fd5b8051614e23614234826141d2565b818152856020838501011115614e37575f80fd5b6140a48260208301602086016142e0565b8035600281106144db575f80fd5b5f60a08236031215614e66575f80fd5b614e6e61415a565b823567ffffffffffffffff80821115614e85575f80fd5b614e9136838701614217565b83526020850135915080821115614ea6575f80fd5b50614eb336828601614217565b602083015250604083013560048110614eca575f80fd5b6040820152614edb60608401614e48565b6060820152614eec60808401614927565b608082015292915050565b5f60208083525f8454614f0981614a11565b806020870152604060018084165f8114614f2a5760018114614f6457614f91565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a01019550614f91565b895f5260205f205f5b85811015614f885781548b8201860152908301908801614f6d565b8a016040019650505b509398975050505050505050565b60ff818116838216019081111561061757610617614990565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614feb575f80fd5b83018035915067ffffffffffffffff821115615005575f80fd5b602001915036819003821315611a20575f80fd5b67ffffffffffffffff8311156150315761503161412d565b6150458361503f8354614a11565b83614c7c565b5f601f841160018114615095575f851561505f5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614cc0565b5f838152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08716915b828110156150e257868501358255602094850194600190920191016150c2565b508682101561511d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b8181038181111561061757610617614990565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b608081528460808201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8611156151a6575f80fd5b8560051b808860a0850137820182810360a090810160208501526151cc90820187614302565b91505063ffffffff8085166040840152808416606084015250969550505050505056fea164736f6c6343000818000a
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106101bb575f3560e01c806350c946fe116100f35780638da5cb5b11610093578063ddbe4f821161006e578063ddbe4f8214610442578063e29581aa14610457578063f2fde38b1461045f578063fcdc8efe14610472575f80fd5b80638da5cb5b146103e85780639cb7c5f41461040f578063d8bc7b681461042f575f80fd5b8063715f5295116100ce578063715f5295146103a757806379ba5097146103ba57806384f5ed8a146103c257806386fa4246146103d5575f80fd5b806350c946fe1461035f5780635d83d9671461037f57806366acaa3314610392575f80fd5b8063235374051161015e5780632c01a1e8116101395780632c01a1e814610305578063358039f414610318578063398f37731461032b5780633f2a13c91461033e575f80fd5b806323537405146102bf578063275459f2146102df5780632a852933146102f2575f80fd5b8063181f5a7711610199578063181f5a771461022c5780631d05394c14610275578063214502431461028a57806322bdbcbc1461029f575f80fd5b806305a51966146101bf5780630fe5800a146101e85780631257001114610209575b5f80fd5b6101d26101cd366004613fb4565b610498565b6040516101df91906140ad565b60405180910390f35b6101fb6101f6366004614269565b61061d565b6040519081526020016101df565b61021c6102173660046142c9565b61064f565b60405190151581526020016101df565b6102686040518060400160405280601a81526020017f4361706162696c6974696573526567697374727920312e312e3000000000000081525081565b6040516101df919061434b565b610288610283366004613fb4565b61065b565b005b61029261085a565b6040516101df9190614455565b6102b26102ad3660046144e0565b6109b3565b6040516101df9190614535565b6102d26102cd3660046144e0565b610a9c565b6040516101df9190614547565b6102886102ed366004613fb4565b610adf565b610288610300366004614578565b610bb2565b610288610313366004613fb4565b610c91565b610288610326366004613fb4565b610f2e565b610288610339366004613fb4565b61168a565b61035161034c366004614613565b611844565b6040516101df92919061463b565b61037261036d3660046142c9565b611a27565b6040516101df919061465f565b61028861038d366004613fb4565b611b10565b61039a611c02565b6040516101df9190614671565b6102886103b5366004613fb4565b611dde565b610288611e8c565b6102886103d0366004613fb4565b611f88565b6102886103e33660046146e4565b612499565b5f5460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101df565b61042261041d3660046142c9565b6127d4565b6040516101df9190614823565b61028861043d366004614835565b612a02565b61044a612aca565b6040516101df91906148b4565b6101d2612bb8565b61028861046d36600461494a565b612cc5565b600e54640100000000900463ffffffff1660405163ffffffff90911681526020016101df565b60605f8267ffffffffffffffff8111156104b4576104b461412d565b60405190808252806020026020018201604052801561054257816020015b60408051610100810182525f808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816104d25790505b5090505f5b838110156106135761057085858381811061056457610564614963565b90506020020135611a27565b82828151811061058257610582614963565b60200260200101819052505f8019168282815181106105a3576105a3614963565b6020026020010151608001510361060b578484828181106105c6576105c6614963565b905060200201356040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b60405180910390fd5b600101610547565b5090505b92915050565b5f828260405160200161063192919061463b565b60405160208183030381529060405280519060200120905092915050565b5f610617600583612cd9565b610663612cf3565b5f5b81811015610855575f83838381811061068057610680614963565b905060200201602081019061069591906144e0565b63ffffffff8181165f908152600d60209081526040808320805464010000000081049095168085526001820190935290832094955093909290916a010000000000000000000090910460ff16905b6106ec83612d75565b81101561078857811561074057600c5f6107068584612d7e565b815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff169055610780565b61077e8663ffffffff16600c5f6107608588612d7e90919063ffffffff16565b81526020019081526020015f20600501612d8990919063ffffffff16565b505b6001016106e3565b508354640100000000900463ffffffff165f036107d9576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff86166004820152602401610602565b63ffffffff85165f818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffff0000000000000000000000169055519182527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a25050505050806001019050610665565b505050565b600e54606090640100000000900463ffffffff165f61087a6001836149bd565b63ffffffff1667ffffffffffffffff8111156108985761089861412d565b60405190808252806020026020018201604052801561091e57816020015b6040805160e0810182525f80825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816108b65790505b5090505f60015b8363ffffffff168163ffffffff1610156109905763ffffffff8082165f908152600d602052604090205416156109885761095e81612d94565b83838151811061097057610970614963565b602002602001018190525081610985906149da565b91505b600101610925565b5061099c6001846149bd565b63ffffffff1681146109ac578082525b5092915050565b604080518082019091525f81526060602082015263ffffffff82165f908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610a1590614a11565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4190614a11565b8015610a8c5780601f10610a6357610100808354040283529160200191610a8c565b820191905f5260205f20905b815481529060010190602001808311610a6f57829003601f168201915b5050505050815250509050919050565b6040805160e0810182525f808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261061782612d94565b610ae7612cf3565b5f5b63ffffffff8116821115610855575f83838363ffffffff16818110610b1057610b10614963565b9050602002016020810190610b2591906144e0565b63ffffffff81165f908152600b6020526040812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155919250610b6f6001830182613f0d565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a905f90a250610bab81614a62565b9050610ae9565b610bba612cf3565b63ffffffff8088165f908152600d60205260408120805490926401000000009091041690819003610c1f576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a166004820152602401610602565b610c86888888886040518060a001604052808f63ffffffff16815260200187610c4790614a62565b63ffffffff811682528b15156020830152895460ff6a01000000000000000000009091048116151560408401528b166060909201919091529650613054565b505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f28575f848483818110610cc957610cc9614963565b602090810292909201355f818152600c90935260409092206001810154929350919050610d25576040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260048101839052602401610602565b5f610d3282600501612d75565b1115610d8757610d456005820184612d7e565b6040517f60a6d89800000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101839052604401610602565b805468010000000000000000900463ffffffff1615610def5780546040517f60b9df730000000000000000000000000000000000000000000000000000000081526801000000000000000090910463ffffffff16600482015260248101839052604401610602565b83158015610e285750805463ffffffff165f908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610e61576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b6001810154610e7290600790612d89565b506002810154610e8490600990612d89565b505f828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001681556001810182905560028101829055600381018290559060058201818181610edf8282613f44565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610f1691815260200190565b60405180910390a15050600101610cae565b50505050565b5f805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f28575f848483818110610f6657610f66614963565b9050602002810190610f789190614a84565b610f8190614ac0565b6040808201515f908152600c6020908152828220805463ffffffff168352600b82528383208451808601909552805473ffffffffffffffffffffffffffffffffffffffff1685526001810180549697509195939493909284019190610fe590614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461101190614a11565b801561105c5780601f106110335761010080835404028352916020019161105c565b820191905f5260205f20905b81548152906001019060200180831161103f57829003601f168201915b5050509190925250505060018301549091506110ac5782604001516040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b841580156110d15750805173ffffffffffffffffffffffffffffffffffffffff163314155b1561110a576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b6020830151611145576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001820154602084015181146111c657602084015161116690600790612cd9565b1561119d576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084015160018401556111b2600782612d89565b5060208401516111c49060079061384a565b505b60608401516112095783606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b608084015180515f0361124a57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b83545f90859060049061126a90640100000000900463ffffffff16614a62565b91906101000a81548163ffffffff021916908363ffffffff160217905590505f5b825181101561134c576112c18382815181106112a9576112a9614963565b60200260200101516003612cd990919063ffffffff16565b6112f957826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b61134383828151811061130e5761130e614963565b6020026020010151876004015f8563ffffffff1663ffffffff1681526020019081526020015f2061384a90919063ffffffff16565b5060010161128b565b50845468010000000000000000900463ffffffff1680156114a75763ffffffff8082165f908152600d6020908152604080832080546401000000009004909416835260019093018152828220600201805484518184028101840190955280855292939290918301828280156113de57602002820191905f5260205f20905b8154815260200190600101908083116113ca575b505050505090505f5b81518110156114a45761143a82828151811061140557611405614963565b6020026020010151896004015f8763ffffffff1663ffffffff1681526020019081526020015f20612cd990919063ffffffff16565b61149c5781818151811061145057611450614963565b6020026020010151836040517f03dcd86200000000000000000000000000000000000000000000000000000000815260040161060292919091825263ffffffff16602082015260400190565b6001016113e7565b50505b5f6114b487600501613855565b90505f5b81518163ffffffff1610156115f2575f828263ffffffff16815181106114e0576114e0614963565b60209081029190910181015163ffffffff8082165f908152600d8452604080822080546401000000009004909316825260019092018452818120600201805483518187028101870190945280845293955090939192909183018282801561156457602002820191905f5260205f20905b815481526020019060010190808311611550575b505050505090505f5b81518110156115de576115c082828151811061158b5761158b614963565b60200260200101518c6004015f8a63ffffffff1663ffffffff1681526020019081526020015f20612cd990919063ffffffff16565b6115d65781818151811061145057611450614963565b60010161156d565b505050806115eb90614a62565b90506114b8565b50875187547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90911690811788556040808a015160028a0181905560608b015160038b01556020808c01518351928352908201527f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a25050505050505050806001019050610f4b565b611692612cf3565b5f5b81811015610855575f8383838181106116af576116af614963565b90506020028101906116c19190614bdb565b6116ca90614c0d565b805190915073ffffffffffffffffffffffffffffffffffffffff1661171b576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095165f818152600b909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815592519192909160018201906117a69082614cc7565b5050600e80549091505f906117c09063ffffffff16614a62565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e8460200151604051611832919061434b565b60405180910390a35050600101611694565b63ffffffff8083165f908152600d6020908152604080832080546401000000009004909416808452600190940182528083208584526003019091528120805460609384939092909161189590614a11565b80601f01602080910402602001604051908101604052809291908181526020018280546118c190614a11565b801561190c5780601f106118e35761010080835404028352916020019161190c565b820191905f5260205f20905b8154815290600101906020018083116118ef57829003601f168201915b5050505f888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff16159150611a199050575f86815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d906024015f60405180830381865afa1580156119d1573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a169190810190614ddf565b90505b9093509150505b9250929050565b60408051610100810182525f8082526020820181905291810182905260608082018390526080820183905260a082019290925260c0810182905260e081019190915260408051610100810182525f848152600c6020908152838220805463ffffffff8082168652640100000000820481168487018190526801000000000000000090920416858701526001820154606086015260028201546080860152600382015460a0860152835260040190529190912060c0820190611ae790613855565b8152602001611b08600c5f8681526020019081526020015f20600501613855565b905292915050565b611b18612cf3565b5f5b81811015610855575f838383818110611b3557611b35614963565b905060200201359050611b52816003612cd990919063ffffffff16565b611b8b576040517fe181733f00000000000000000000000000000000000000000000000000000000815260048101829052602401610602565b611b9660058261384a565b611bcf576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815260048101829052602401610602565b60405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf21905f90a250600101611b1a565b600e5460609063ffffffff165f611c1a6001836149bd565b63ffffffff1667ffffffffffffffff811115611c3857611c3861412d565b604051908082528060200260200182016040528015611c7d57816020015b604080518082019091525f815260606020820152815260200190600190039081611c565790505b5090505f60015b8363ffffffff168163ffffffff161015611dc85763ffffffff81165f908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611dc05763ffffffff81165f908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191611d1690614a11565b80601f0160208091040260200160405190810160405280929190818152602001828054611d4290614a11565b8015611d8d5780601f10611d6457610100808354040283529160200191611d8d565b820191905f5260205f20905b815481529060010190602001808311611d7057829003601f168201915b505050505081525050838381518110611da857611da8614963565b602002602001018190525081611dbd906149da565b91505b600101611c84565b50600e5461099c9060019063ffffffff166149bd565b611de6612cf3565b5f5b81811015610855575f838383818110611e0357611e03614963565b9050602002810190611e159190614a84565b611e1e90614e56565b90505f611e32825f0151836020015161061d565b9050611e3f60038261384a565b611e78576040517febf5255100000000000000000000000000000000000000000000000000000000815260048101829052602401610602565b611e828183613861565b5050600101611de8565b60015473ffffffffffffffffffffffffffffffffffffffff163314611f0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610602565b5f8054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b5f805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f28575f848483818110611fc057611fc0614963565b9050602002810190611fd29190614a84565b611fdb90614ac0565b805163ffffffff165f908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff16825260018101805495965093949193909284019161203090614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461205c90614a11565b80156120a75780601f1061207e576101008083540402835291602001916120a7565b820191905f5260205f20905b81548152906001019060200180831161208a57829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff1661210d5781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610602565b831580156121325750805173ffffffffffffffffffffffffffffffffffffffff163314155b1561216b576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b6040808301515f908152600c602052206001810154156121bf5782604001516040517f5461848300000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b60408301516122025782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b6020830151158061221f5750602083015161221f90600790612cd9565b15612256576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301516122995782606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161060291815260200190565b608083015180515f036122da57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b815482906004906122f890640100000000900463ffffffff16614a62565b82546101009290920a63ffffffff81810219909316918316021790915582546401000000009004165f5b82518110156123cb576123408382815181106112a9576112a9614963565b61237857826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106029190614b98565b6123c283828151811061238d5761238d614963565b6020026020010151856004015f8563ffffffff1663ffffffff1681526020019081526020015f2061384a90919063ffffffff16565b50600101612322565b5060608501516003840155845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9182161784556040860151600285015560208601516001850181905561242b916007919061384a16565b50604085015161243d9060099061384a565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a25050505050806001019050611fa5565b8281146124dc576040517fab8b67c60000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610602565b5f805473ffffffffffffffffffffffffffffffffffffffff16905b848110156127cc575f86868381811061251257612512614963565b905060200201602081019061252791906144e0565b63ffffffff81165f908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff16612595576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610602565b5f8686858181106125a8576125a8614963565b90506020028101906125ba9190614bdb565b6125c390614c0d565b805190915073ffffffffffffffffffffffffffffffffffffffff16612614576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815473ffffffffffffffffffffffffffffffffffffffff16331480159061265157503373ffffffffffffffffffffffffffffffffffffffff861614155b1561268a576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610602565b8051825473ffffffffffffffffffffffffffffffffffffffff908116911614158061270657506020808201516040516126c3920161434b565b60405160208183030381529060405280519060200120826001016040516020016126ed9190614ef7565b6040516020818303038152906040528051906020012014155b156127be57805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602081015160018301906127609082614cc7565b50805f015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a2883602001516040516127b5919061434b565b60405180910390a35b5050508060010190506124f7565b505050505050565b6128126040805160e0810182525f808252606060208301819052928201839052909182019081526020015f81525f6020820181905260409091015290565b6040805160e0810182528381525f848152600260209081529290208054919283019161283d90614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461286990614a11565b80156128b45780601f1061288b576101008083540402835291602001916128b4565b820191905f5260205f20905b81548152906001019060200180831161289757829003601f168201915b5050505050815260200160025f8581526020019081526020015f2060010180546128dd90614a11565b80601f016020809104026020016040519081016040528092919081815260200182805461290990614a11565b80156129545780601f1061292b57610100808354040283529160200191612954565b820191905f5260205f20905b81548152906001019060200180831161293757829003601f168201915b50505091835250505f848152600260208181526040909220015491019060ff1660038111156129855761298561474b565b81525f8481526002602081815260409092200154910190610100900460ff1660018111156129b5576129b561474b565b81525f848152600260208181526040928390209091015462010000900473ffffffffffffffffffffffffffffffffffffffff1690830152016129f8600585612cd9565b1515905292915050565b612a0a612cf3565b600e80545f9164010000000090910463ffffffff16906004612a2b83614a62565b82546101009290920a63ffffffff81810219909316918316021790915581165f818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a08101835292835260019083015286151590820152841515606082015260ff84166080820152909150612ac0908990899089908990613054565b5050505050505050565b60605f612ad76003613855565b90505f815167ffffffffffffffff811115612af457612af461412d565b604051908082528060200260200182016040528015612b6357816020015b612b506040805160e0810182525f808252606060208301819052928201839052909182019081526020015f81525f6020820181905260409091015290565b815260200190600190039081612b125790505b5090505f5b82518110156109ac57612b93838281518110612b8657612b86614963565b60200260200101516127d4565b828281518110612ba557612ba5614963565b6020908102919091010152600101612b68565b60605f612bc56009613855565b90505f815167ffffffffffffffff811115612be257612be261412d565b604051908082528060200260200182016040528015612c7057816020015b60408051610100810182525f808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181612c005790505b5090505f5b82518110156109ac57612ca0838281518110612c9357612c93614963565b6020026020010151611a27565b828281518110612cb257612cb2614963565b6020908102919091010152600101612c75565b612ccd612cf3565b612cd681613a47565b50565b5f81815260018301602052604081205415155b9392505050565b5f5473ffffffffffffffffffffffffffffffffffffffff163314612d73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610602565b565b5f610617825490565b5f612cec8383613b3b565b5f612cec8383613b61565b6040805160e0810182525f808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d8252848320805464010000000090049091168084526001909101825284832060028101805487518186028101860190985280885295969295919493909190830182828015612e4257602002820191905f5260205f20905b815481526020019060010190808311612e2e575b505050505090505f815167ffffffffffffffff811115612e6457612e6461412d565b604051908082528060200260200182016040528015612ea957816020015b604080518082019091525f815260606020820152815260200190600190039081612e825790505b5090505f5b8151811015612fbc576040518060400160405280848381518110612ed457612ed4614963565b60200260200101518152602001856003015f868581518110612ef857612ef8614963565b602002602001015181526020019081526020015f208054612f1890614a11565b80601f0160208091040260200160405190810160405280929190818152602001828054612f4490614a11565b8015612f8f5780601f10612f6657610100808354040283529160200191612f8f565b820191905f5260205f20905b815481529060010190602001808311612f7257829003601f168201915b5050505050815250828281518110612fa957612fa9614963565b6020908102919091010152600101612eae565b506040805160e08101825263ffffffff8089165f818152600d6020818152868320548086168752948b168187015260ff680100000000000000008604811697870197909752690100000000000000000085048716151560608701529290915290526a010000000000000000000090049091161515608082015260a0810161304285613855565b81526020019190915295945050505050565b805163ffffffff9081165f908152600d602090815260408083208286015190941683526001909301905220608082015160ff1615806130a55750608082015185906130a0906001614f9f565b60ff16115b156130ee5760808201516040517f25b4d61800000000000000000000000000000000000000000000000000000000815260ff909116600482015260248101869052604401610602565b6001826020015163ffffffff1611156131ce57815163ffffffff165f908152600d60209081526040822090840151600191820191839161312e91906149bd565b63ffffffff1663ffffffff1681526020019081526020015f2090505f5b61315482612d75565b8110156131cb57613180845f015163ffffffff16600c5f61076085875f01612d7e90919063ffffffff16565b50600c5f61318e8484612d7e565b815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16905560010161314b565b50505b5f5b858110156133fe576131fd8787838181106131ed576131ed614963565b859260209091020135905061384a565b61325e57825187878381811061321557613215614963565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610602565b8260600151156133ae57825163ffffffff16600c5f89898581811061328557613285614963565b602090810292909201358352508101919091526040015f205468010000000000000000900463ffffffff16148015906132fc5750600c5f8888848181106132ce576132ce614963565b602090810292909201358352508101919091526040015f205468010000000000000000900463ffffffff1615155b1561335e57825187878381811061331557613315614963565b6040517f60b9df7300000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610602565b8251600c5f89898581811061337557613375614963565b9050602002013581526020019081526020015f205f0160086101000a81548163ffffffff021916908363ffffffff1602179055506133f6565b82516133f49063ffffffff16600c5f8a8a868181106133cf576133cf614963565b9050602002013581526020019081526020015f2060050161384a90919063ffffffff16565b505b6001016131d0565b505f5b838110156137fe573685858381811061341c5761341c614963565b905060200281019061342e9190614bdb565b905061343c60038235612cd9565b613475576040517fe181733f00000000000000000000000000000000000000000000000000000000815281356004820152602401610602565b61348160058235612cd9565b156134bb576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815281356004820152602401610602565b80355f908152600384016020526040812080546134d790614a11565b905011156135235783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015281356024820152604401610602565b5f5b87811015613625576135c28235600c5f8c8c8681811061354757613547614963565b9050602002013581526020019081526020015f206004015f600c5f8e8e8881811061357457613574614963565b9050602002013581526020019081526020015f205f0160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020019081526020015f20612cd990919063ffffffff16565b61361d578888828181106135d8576135d8614963565b6040517fa7e792500000000000000000000000000000000000000000000000000000000081526020909102929092013560048301525082356024820152604401610602565b600101613525565b506002830180546001810182555f918252602091829020833591015561364d90820182614fb8565b82355f90815260038601602052604090209161366a919083615019565b50604080850151855163ffffffff9081165f908152600d602090815284822080549415156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff90951694909417909355606088015188518316825284822080549115156a0100000000000000000000027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff9092169190911790556080880151885183168252848220805460ff9290921668010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909216919091179055828801805189518416835294909120805494909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff909416939093179055855191516137f592918435908c908c906137bc90880188614fb8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250613c4492505050565b50600101613401565b50815160208084015160405163ffffffff91821681529216917ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a2505050505050565b5f612cec8383613d1e565b60605f612cec83613d6a565b608081015173ffffffffffffffffffffffffffffffffffffffff1615613903576138af81608001517f78bea72100000000000000000000000000000000000000000000000000000000613dc3565b6139035760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610602565b5f828152600260205260409020815182919081906139219082614cc7565b50602082015160018201906139369082614cc7565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360038111156139785761397861474b565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101008360018111156139bf576139bf61474b565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae905f90a25050565b3373ffffffffffffffffffffffffffffffffffffffff821603613ac6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610602565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8381169182179092555f8054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b5f825f018281548110613b5057613b50614963565b905f5260205f200154905092915050565b5f8181526001830160205260408120548015613c3b575f613b8360018361512f565b85549091505f90613b969060019061512f565b9050818114613bf5575f865f018281548110613bb457613bb4614963565b905f5260205f200154905080875f018481548110613bd457613bd4614963565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080613c0657613c06615142565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610617565b5f915050610617565b5f848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff16156127cc575f84815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c90613ce9908690869086908b908d9060040161516f565b5f604051808303815f87803b158015613d00575f80fd5b505af1158015613d12573d5f803e3d5ffd5b50505050505050505050565b5f818152600183016020526040812054613d6357508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610617565b505f610617565b6060815f01805480602002602001604051908101604052809291908181526020018280548015613db757602002820191905f5260205f20905b815481526020019060010190808311613da3575b50505050509050919050565b5f613dcd83613dde565b8015612cec5750612cec8383613e41565b5f613e09827f01ffc9a700000000000000000000000000000000000000000000000000000000613e41565b80156106175750613e3a827fffffffff00000000000000000000000000000000000000000000000000000000613e41565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017815282515f9392849283928392918391908a617530fa92503d91505f519050828015613ef7575060208210155b8015613f0257505f81115b979650505050505050565b508054613f1990614a11565b5f825580601f10613f28575050565b601f0160209004905f5260205f2090810190612cd69190613f5b565b5080545f8255905f5260205f2090810190612cd691905b5b80821115613f6f575f8155600101613f5c565b5090565b5f8083601f840112613f83575f80fd5b50813567ffffffffffffffff811115613f9a575f80fd5b6020830191508360208260051b8501011115611a20575f80fd5b5f8060208385031215613fc5575f80fd5b823567ffffffffffffffff811115613fdb575f80fd5b613fe785828601613f73565b90969095509350505050565b5f815180845260208085019450602084015f5b8381101561402257815187529582019590820190600101614006565b509495945050505050565b5f61010063ffffffff80845116855280602085015116602086015280604085015116604086015250606083015160608501526080830151608085015260a083015160a085015260c08301518160c086015261408a82860182613ff3565b91505060e083015184820360e08601526140a48282613ff3565b95945050505050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261410e85835161402d565b945092850192908501906001016140d4565b5092979650505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b60405160a0810167ffffffffffffffff8111828210171561417d5761417d61412d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156141ca576141ca61412d565b604052919050565b5f67ffffffffffffffff8211156141eb576141eb61412d565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112614226575f80fd5b8135614239614234826141d2565b614183565b81815284602083860101111561424d575f80fd5b816020850160208301375f918101602001919091529392505050565b5f806040838503121561427a575f80fd5b823567ffffffffffffffff80821115614291575f80fd5b61429d86838701614217565b935060208501359150808211156142b2575f80fd5b506142bf85828601614217565b9150509250929050565b5f602082840312156142d9575f80fd5b5035919050565b5f5b838110156142fa5781810151838201526020016142e2565b50505f910152565b5f81518084526143198160208601602086016142e0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f612cec6020830184614302565b5f82825180855260208086019550808260051b8401018186015f5b848110156143d8578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051845284015160408585018190526143c481860183614302565b9a86019a9450505090830190600101614378565b5090979650505050505050565b5f63ffffffff8083511684528060208401511660208501525060ff604083015116604084015260608201511515606084015260808201511515608084015260a082015160e060a085015261443c60e0850182613ff3565b905060c083015184820360c08601526140a4828261435d565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526144b68583516143e5565b9450928501929085019060010161447c565b803563ffffffff811681146144db575f80fd5b919050565b5f602082840312156144f0575f80fd5b612cec826144c8565b73ffffffffffffffffffffffffffffffffffffffff81511682525f60208201516040602085015261452d6040850182614302565b949350505050565b602081525f612cec60208301846144f9565b602081525f612cec60208301846143e5565b803580151581146144db575f80fd5b803560ff811681146144db575f80fd5b5f805f805f805f60a0888a03121561458e575f80fd5b614597886144c8565b9650602088013567ffffffffffffffff808211156145b3575f80fd5b6145bf8b838c01613f73565b909850965060408a01359150808211156145d7575f80fd5b506145e48a828b01613f73565b90955093506145f7905060608901614559565b915061460560808901614568565b905092959891949750929550565b5f8060408385031215614624575f80fd5b61462d836144c8565b946020939093013593505050565b604081525f61464d6040830185614302565b82810360208401526140a48185614302565b602081525f612cec602083018461402d565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526146d28583516144f9565b94509285019290850190600101614698565b5f805f80604085870312156146f7575f80fd5b843567ffffffffffffffff8082111561470e575f80fd5b61471a88838901613f73565b90965094506020870135915080821115614732575f80fd5b5061473f87828801613f73565b95989497509550505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b805182525f602082015160e0602085015261479660e0850182614302565b9050604083015184820360408601526147af8282614302565b9150506060830151600481106147c7576147c761474b565b60608501526080830151600281106147e1576147e161474b565b8060808601525060a083015161480f60a086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015161061360c086018215159052565b602081525f612cec6020830184614778565b5f805f805f805f60a0888a03121561484b575f80fd5b873567ffffffffffffffff80821115614862575f80fd5b61486e8b838c01613f73565b909950975060208a0135915080821115614886575f80fd5b506148938a828b01613f73565b90965094506148a6905060408901614559565b92506145f760608901614559565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015614120577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614915858351614778565b945092850192908501906001016148db565b803573ffffffffffffffffffffffffffffffffffffffff811681146144db575f80fd5b5f6020828403121561495a575f80fd5b612cec82614927565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b63ffffffff8281168282160390808211156109ac576109ac614990565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614a0a57614a0a614990565b5060010190565b600181811c90821680614a2557607f821691505b602082108103614a5c577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f63ffffffff808316818103614a7a57614a7a614990565b6001019392505050565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112614ab6575f80fd5b9190910192915050565b5f60a08236031215614ad0575f80fd5b614ad861415a565b614ae1836144c8565b8152602080840135818301526040840135604083015260608401356060830152608084013567ffffffffffffffff80821115614b1b575f80fd5b9085019036601f830112614b2d575f80fd5b813581811115614b3f57614b3f61412d565b8060051b9150614b50848301614183565b8181529183018401918481019036841115614b69575f80fd5b938501935b83851015614b8757843582529385019390850190614b6e565b608087015250939695505050505050565b602080825282518282018190525f9190848201906040850190845b81811015614bcf57835183529284019291840191600101614bb3565b50909695505050505050565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112614ab6575f80fd5b5f60408236031215614c1d575f80fd5b6040516040810167ffffffffffffffff8282108183111715614c4157614c4161412d565b81604052614c4e85614927565b83526020850135915080821115614c63575f80fd5b50614c7036828601614217565b60208301525092915050565b601f82111561085557805f5260205f20601f840160051c81016020851015614ca15750805b601f840160051c820191505b81811015614cc0575f8155600101614cad565b5050505050565b815167ffffffffffffffff811115614ce157614ce161412d565b614cf581614cef8454614a11565b84614c7c565b602080601f831160018114614d47575f8415614d115750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556127cc565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614d9357888601518255948401946001909101908401614d74565b5085821015614dcf57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b5f60208284031215614def575f80fd5b815167ffffffffffffffff811115614e05575f80fd5b8201601f81018413614e15575f80fd5b8051614e23614234826141d2565b818152856020838501011115614e37575f80fd5b6140a48260208301602086016142e0565b8035600281106144db575f80fd5b5f60a08236031215614e66575f80fd5b614e6e61415a565b823567ffffffffffffffff80821115614e85575f80fd5b614e9136838701614217565b83526020850135915080821115614ea6575f80fd5b50614eb336828601614217565b602083015250604083013560048110614eca575f80fd5b6040820152614edb60608401614e48565b6060820152614eec60808401614927565b608082015292915050565b5f60208083525f8454614f0981614a11565b806020870152604060018084165f8114614f2a5760018114614f6457614f91565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a01019550614f91565b895f5260205f205f5b85811015614f885781548b8201860152908301908801614f6d565b8a016040019650505b509398975050505050505050565b60ff818116838216019081111561061757610617614990565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614feb575f80fd5b83018035915067ffffffffffffffff821115615005575f80fd5b602001915036819003821315611a20575f80fd5b67ffffffffffffffff8311156150315761503161412d565b6150458361503f8354614a11565b83614c7c565b5f601f841160018114615095575f851561505f5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614cc0565b5f838152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08716915b828110156150e257868501358255602094850194600190920191016150c2565b508682101561511d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b8181038181111561061757610617614990565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603160045260245ffd5b608081528460808201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8611156151a6575f80fd5b8560051b808860a0850137820182810360a090810160208501526151cc90820187614302565b91505063ffffffff8085166040840152808416606084015250969550505050505056fea164736f6c6343000818000a
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.