ETH Price: $3,284.10 (-0.84%)

Contract

0x48b6af7B12C71f09e2fC8aF4855De4Ff54e775cA
 

Overview

ETH Balance

0.340040019017000021 ETH

Eth Value

$1,116.72 (@ $3,284.10/ETH)

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Safe Transfer Fr...214184792024-12-16 23:49:5933 days ago1734392999IN
Fake_Phishing297699
0 ETH0.0005977110.42756906
Set Approval For...212989662024-11-30 7:20:5949 days ago1732951259IN
Fake_Phishing297699
0 ETH0.000339867.36250486
Transfer From211089052024-11-03 18:28:3576 days ago1730658515IN
Fake_Phishing297699
0 ETH0.000178564.76722277
Transfer From192259872024-02-14 11:43:47339 days ago1707911027IN
Fake_Phishing297699
0 ETH0.0005373721.69555226
Transfer From192259832024-02-14 11:42:59339 days ago1707910979IN
Fake_Phishing297699
0 ETH0.000904224.13983022
Transfer From192259812024-02-14 11:42:35339 days ago1707910955IN
Fake_Phishing297699
0 ETH0.00091121.55864367
Transfer From192259792024-02-14 11:42:11339 days ago1707910931IN
Fake_Phishing297699
0 ETH0.0010393624.59633797
Transfer From192115852024-02-12 11:15:23341 days ago1707736523IN
Fake_Phishing297699
0 ETH0.0006935516.41272214
Transfer From192115382024-02-12 11:05:59341 days ago1707735959IN
Fake_Phishing297699
0 ETH0.0007740518.31778793
Transfer From184195652023-10-24 10:36:47452 days ago1698143807IN
Fake_Phishing297699
0 ETH0.001121520.5566444
Set Approval For...178191012023-08-01 8:57:11536 days ago1690880231IN
Fake_Phishing297699
0 ETH0.0006875314.89400791
Transfer From171867672023-05-04 10:39:47625 days ago1683196787IN
Fake_Phishing297699
0 ETH0.0042622871.80765499
Change Owner160329792022-11-23 13:25:35787 days ago1669209935IN
Fake_Phishing297699
0 ETH0.0003817413.52597289
Change Multisig ...154521662022-09-01 9:45:03870 days ago1662025503IN
Fake_Phishing297699
0 ETH0.000451789.71307814
Change Multisig ...153586692022-08-17 12:17:03885 days ago1660738623IN
Fake_Phishing297699
0 ETH0.000372278.0036329
Change Multisig ...153586572022-08-17 12:14:52885 days ago1660738492IN
Fake_Phishing297699
0 ETH0.0002696610.96172145
Change Multisig ...151790922022-07-20 11:03:29913 days ago1658315009IN
Fake_Phishing297699
0 ETH0.0010136221.79232598
Change Multisig ...151790722022-07-20 10:57:34913 days ago1658314654IN
Fake_Phishing297699
0 ETH0.000451318.35410039
Change Multisig ...151785192022-07-20 8:51:15913 days ago1658307075IN
Fake_Phishing297699
0 ETH0.0006891214.81949226
Change Manager151785162022-07-20 8:50:37913 days ago1658307037IN
Fake_Phishing297699
0 ETH0.000704514.8805243

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
215423612025-01-03 7:07:4715 days ago1735888067
Fake_Phishing297699
0.001 ETH
215423482025-01-03 7:05:1115 days ago1735887911
Fake_Phishing297699
0.001 ETH
213953532024-12-13 18:22:2336 days ago1734114143
Fake_Phishing297699
0.004 ETH
213836842024-12-12 3:17:3538 days ago1733973455
Fake_Phishing297699
0.001 ETH
213836792024-12-12 3:16:3538 days ago1733973395
Fake_Phishing297699
0.001 ETH
213836422024-12-12 3:09:1138 days ago1733972951
Fake_Phishing297699
0.001 ETH
213836422024-12-12 3:09:1138 days ago1733972951
Fake_Phishing297699
0.001 ETH
213836422024-12-12 3:09:1138 days ago1733972951
Fake_Phishing297699
0.001 ETH
213836422024-12-12 3:09:1138 days ago1733972951
Fake_Phishing297699
0.001 ETH
211704192024-11-12 8:30:4767 days ago1731400247
Fake_Phishing297699
1 wei
211704172024-11-12 8:30:2367 days ago1731400223
Fake_Phishing297699
1 wei
211704132024-11-12 8:29:2367 days ago1731400163
Fake_Phishing297699
1 wei
211704122024-11-12 8:29:1167 days ago1731400151
Fake_Phishing297699
1 wei
211233942024-11-05 18:59:3574 days ago1730833175
Fake_Phishing297699
1 wei
211233932024-11-05 18:59:2374 days ago1730833163
Fake_Phishing297699
1 wei
211233902024-11-05 18:58:4774 days ago1730833127
Fake_Phishing297699
1 wei
211233892024-11-05 18:58:3574 days ago1730833115
Fake_Phishing297699
1 wei
211220962024-11-05 14:38:3574 days ago1730817515
Fake_Phishing297699
1 wei
211220942024-11-05 14:38:1174 days ago1730817491
Fake_Phishing297699
1 wei
210981052024-11-02 6:15:1178 days ago1730528111
Fake_Phishing297699
0.005 ETH
210981022024-11-02 6:14:3578 days ago1730528075
Fake_Phishing297699
0.005 ETH
210845392024-10-31 8:52:1179 days ago1730364731
Fake_Phishing297699
0.001 ETH
210789822024-10-30 14:15:2380 days ago1730297723
Fake_Phishing297699
0.001 ETH
210787662024-10-30 13:30:3580 days ago1730295035
Fake_Phishing297699
0.001 ETH
210786202024-10-30 13:00:5980 days ago1730293259
Fake_Phishing297699
0.001 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ServiceRegistry

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 750 runs

Other Settings:
default evmVersion
File 1 of 6 : ServiceRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import "./GenericRegistry.sol";
import "./interfaces/IMultisig.sol";
import "./interfaces/IRegistry.sol";

// This struct is 128 bits in total
struct AgentParams {
    // Number of agent instances. This number is limited by the number of agent instances
    uint32 slots;
    // Bond per agent instance. This is enough for 1b+ ETH or 1e27
    uint96 bond;
}

// This struct is 192 bits in total
struct AgentInstance {
    // Address of an agent instance
    address instance;
    // Canonical agent Id. This number is limited by the max number of agent Ids (see UnitRegistry contract)
    uint32 agentId;
}

/// @title Service Registry - Smart contract for registering services
/// @author Aleksandr Kuperman - <[email protected]>
contract ServiceRegistry is GenericRegistry {
    event DrainerUpdated(address indexed drainer);
    event Deposit(address indexed sender, uint256 amount);
    event Refund(address indexed receiver, uint256 amount);
    event CreateService(uint256 indexed serviceId);
    event UpdateService(uint256 indexed serviceId, bytes32 configHash);
    event RegisterInstance(address indexed operator, uint256 indexed serviceId, address indexed agentInstance, uint256 agentId);
    event CreateMultisigWithAgents(uint256 indexed serviceId, address indexed multisig);
    event ActivateRegistration(uint256 indexed serviceId);
    event TerminateService(uint256 indexed serviceId);
    event OperatorSlashed(uint256 amount, address indexed operator, uint256 indexed serviceId);
    event OperatorUnbond(address indexed operator, uint256 indexed serviceId);
    event DeployService(uint256 indexed serviceId);
    event Drain(address indexed drainer, uint256 amount);

    enum ServiceState {
        NonExistent,
        PreRegistration,
        ActiveRegistration,
        FinishedRegistration,
        Deployed,
        TerminatedBonded
    }

    // Service parameters
    struct Service {
        // Registration activation deposit
        // This is enough for 1b+ ETH or 1e27
        uint96 securityDeposit;
        // Multisig address for agent instances
        address multisig;
        // IPFS hashes pointing to the config metadata
        bytes32 configHash;
        // Agent instance signers threshold: must no less than ceil((n * 2 + 1) / 3) of all the agent instances combined
        // This number will be enough to have ((2^32 - 1) * 3 - 1) / 2, which is bigger than 6.44b
        uint32 threshold;
        // Total number of agent instances. We assume that the number of instances is bounded by 2^32 - 1
        uint32 maxNumAgentInstances;
        // Actual number of agent instances. This number is less or equal to maxNumAgentInstances
        uint32 numAgentInstances;
        // Service state
        ServiceState state;
        // Canonical agent Ids for the service. Individual agent Id is bounded by the max number of agent Id
        uint32[] agentIds;
    }

    // Agent Registry address
    address public immutable agentRegistry;
    // The amount of funds slashed. This is enough for 1b+ ETH or 1e27
    uint96 public slashedFunds;
    // Drainer address: set by the government and is allowed to drain ETH funds accumulated in this contract
    address public drainer;
    // Service registry version number
    string public constant VERSION = "1.0.0";
    // Map of service Id => set of IPFS hashes pointing to the config metadata
    mapping (uint256 => bytes32[]) public mapConfigHashes;
    // Map of operator address and serviceId => set of registered agent instance addresses
    mapping(uint256 => AgentInstance[]) public mapOperatorAndServiceIdAgentInstances;
    // Service Id and canonical agent Id => number of agent instances and correspondent instance registration bond
    mapping(uint256 => AgentParams) public mapServiceAndAgentIdAgentParams;
    // Actual agent instance addresses. Service Id and canonical agent Id => Set of agent instance addresses.
    mapping(uint256 => address[]) public mapServiceAndAgentIdAgentInstances;
    // Map of operator address and serviceId => agent instance bonding / escrow balance
    mapping(uint256 => uint96) public mapOperatorAndServiceIdOperatorBalances;
    // Map of agent instance address => service id it is registered with and operator address that supplied the instance
    mapping (address => address) public mapAgentInstanceOperators;
    // Map of service Id => set of unique component Ids
    // Updated during the service deployment via deploy() function
    mapping (uint256 => uint32[]) public mapServiceIdSetComponentIds;
    // Map of service Id => set of unique agent Ids
    mapping (uint256 => uint32[]) public mapServiceIdSetAgentIds;
    // Map of policy for multisig implementations
    mapping (address => bool) public mapMultisigs;
    // Map of service counter => service
    mapping (uint256 => Service) public mapServices;

    /// @dev Service registry constructor.
    /// @param _name Service contract name.
    /// @param _symbol Agent contract symbol.
    /// @param _baseURI Agent registry token base URI.
    /// @param _agentRegistry Agent registry address.
    constructor(string memory _name, string memory _symbol, string memory _baseURI, address _agentRegistry)
        ERC721(_name, _symbol)
    {
        baseURI = _baseURI;
        agentRegistry = _agentRegistry;
        owner = msg.sender;
    }

    /// @dev Changes the drainer.
    /// @param newDrainer Address of a drainer.
    function changeDrainer(address newDrainer) external {
        if (msg.sender != owner) {
            revert OwnerOnly(msg.sender, owner);
        }

        // Check for the zero address
        if (newDrainer == address(0)) {
            revert ZeroAddress();
        }

        drainer = newDrainer;
        emit DrainerUpdated(newDrainer);
    }

    /// @dev Going through basic initial service checks.
    /// @param configHash IPFS hash pointing to the config metadata.
    /// @param agentIds Canonical agent Ids.
    /// @param agentParams Number of agent instances and required required bond to register an instance in the service.
    function _initialChecks(
        bytes32 configHash,
        uint32[] memory agentIds,
        AgentParams[] memory agentParams
    ) private view
    {
        // Check for the non-zero hash value
        if (configHash == 0) {
            revert ZeroValue();
        }

        // Checking for non-empty arrays and correct number of values in them
        if (agentIds.length == 0 || agentIds.length != agentParams.length) {
            revert WrongArrayLength(agentIds.length, agentParams.length);
        }

        // Check for duplicate canonical agent Ids
        uint256 agentTotalSupply = IRegistry(agentRegistry).totalSupply();
        uint256 lastId;
        for (uint256 i = 0; i < agentIds.length; i++) {
            if (agentIds[i] < (lastId + 1) || agentIds[i] > agentTotalSupply) {
                revert WrongAgentId(agentIds[i]);
            }
            lastId = agentIds[i];
        }
    }

    /// @dev Sets the service data.
    /// @param service A service instance to fill the data for.
    /// @param agentIds Canonical agent Ids.
    /// @param agentParams Number of agent instances and required required bond to register an instance in the service.
    /// @param size Size of a canonical agent ids set.
    /// @param serviceId ServiceId.
    function _setServiceData(
        Service memory service,
        uint32[] memory agentIds,
        AgentParams[] memory agentParams,
        uint256 size,
        uint256 serviceId
    ) private
    {
        // Security deposit
        uint96 securityDeposit;
        // Add canonical agent Ids for the service and the slots map
        service.agentIds = new uint32[](size);
        for (uint256 i = 0; i < size; i++) {
            service.agentIds[i] = agentIds[i];
            // Push a pair of key defining variables into one key. Service or agent Ids are not enough by themselves
            // As with other units, we assume that the system is not expected to support more than than 2^32-1 services
            // Need to carefully check pairings, since it's hard to find if something is incorrectly misplaced bitwise
            // serviceId occupies first 32 bits
            uint256 serviceAgent = serviceId;
            // agentId takes the second 32 bits
            serviceAgent |= uint256(agentIds[i]) << 32;
            mapServiceAndAgentIdAgentParams[serviceAgent] = agentParams[i];
            service.maxNumAgentInstances += agentParams[i].slots;
            // Security deposit is the maximum of the canonical agent registration bond
            if (agentParams[i].bond > securityDeposit) {
                securityDeposit = agentParams[i].bond;
            }
        }
        service.securityDeposit = securityDeposit;

        // Check for the correct threshold: no less than ceil((n * 2 + 1) / 3) of all the agent instances combined
        uint256 checkThreshold = uint256(service.maxNumAgentInstances * 2 + 1);
        if (checkThreshold % 3 == 0) {
            checkThreshold = checkThreshold / 3;
        } else {
            checkThreshold = checkThreshold / 3 + 1;
        }
        if (service.threshold < checkThreshold || service.threshold > service.maxNumAgentInstances) {
            revert WrongThreshold(service.threshold, checkThreshold, service.maxNumAgentInstances);
        }
    }

    /// @dev Creates a new service.
    /// @param serviceOwner Individual that creates and controls a service.
    /// @param configHash IPFS hash pointing to the config metadata.
    /// @param agentIds Canonical agent Ids in a sorted ascending order.
    /// @param agentParams Number of agent instances and required required bond to register an instance in the service.
    /// @param threshold Signers threshold for a multisig composed by agent instances.
    /// @return serviceId Created service Id.
    function create(
        address serviceOwner,
        bytes32 configHash,
        uint32[] memory agentIds,
        AgentParams[] memory agentParams,
        uint32 threshold
    ) external returns (uint256 serviceId)
    {
        // Reentrancy guard
        if (_locked > 1) {
            revert ReentrancyGuard();
        }
        _locked = 2;

        // Check for the manager privilege for a service management
        if (manager != msg.sender) {
            revert ManagerOnly(msg.sender, manager);
        }

        // Check for the non-empty service owner address
        if (serviceOwner == address(0)) {
            revert ZeroAddress();
        }

        // Execute initial checks
        _initialChecks(configHash, agentIds, agentParams);

        // Check that there are no zero number of slots for a specific canonical agent id and no zero registration bond
        for (uint256 i = 0; i < agentIds.length; i++) {
            if (agentParams[i].slots == 0 || agentParams[i].bond == 0) {
                revert ZeroValue();
            }
        }

        // Create a new service Id
        serviceId = totalSupply;
        serviceId++;

        // Set high-level data components of the service instance
        Service memory service;
        // Updating high-level data components of the service
        service.threshold = threshold;
        // Assigning the initial hash
        service.configHash = configHash;
        // Set the initial service state
        service.state = ServiceState.PreRegistration;

        // Set service data
        _setServiceData(service, agentIds, agentParams, agentIds.length, serviceId);
        mapServices[serviceId] = service;
        totalSupply = serviceId;

        // Mint the service instance to the service owner and record the service structure
        _safeMint(serviceOwner, serviceId);

        emit CreateService(serviceId);

        _locked = 1;
    }

    /// @dev Updates a service in a CRUD way.
    /// @param serviceOwner Individual that creates and controls a service.
    /// @param configHash IPFS hash pointing to the config metadata.
    /// @param agentIds Canonical agent Ids in a sorted ascending order.
    /// @param agentParams Number of agent instances and required required bond to register an instance in the service.
    /// @param threshold Signers threshold for a multisig composed by agent instances.
    /// @param serviceId Service Id to be updated.
    /// @return success True, if function executed successfully.
    function update(
        address serviceOwner,
        bytes32 configHash,
        uint32[] memory agentIds,
        AgentParams[] memory agentParams,
        uint32 threshold,
        uint256 serviceId
    ) external returns (bool success)
    {
        // Check for the manager privilege for a service management
        if (manager != msg.sender) {
            revert ManagerOnly(msg.sender, manager);
        }

        // Check for the service ownership
        address actualOwner = ownerOf(serviceId);
        if (actualOwner != serviceOwner) {
            revert OwnerOnly(serviceOwner, actualOwner);
        }

        Service memory service = mapServices[serviceId];
        if (service.state != ServiceState.PreRegistration) {
            revert WrongServiceState(uint256(service.state), serviceId);
        }

        // Execute initial checks
        _initialChecks(configHash, agentIds, agentParams);

        // Updating high-level data components of the service
        service.threshold = threshold;
        service.maxNumAgentInstances = 0;

        // Collect non-zero canonical agent ids and slots / costs, remove any canonical agent Ids from the params map
        uint32[] memory newAgentIds = new uint32[](agentIds.length);
        AgentParams[] memory newAgentParams = new AgentParams[](agentIds.length);
        uint256 size;
        for (uint256 i = 0; i < agentIds.length; i++) {
            if (agentParams[i].slots == 0) {
                // Push a pair of key defining variables into one key. Service or agent Ids are not enough by themselves
                // serviceId occupies first 32 bits, agentId gets the next 32 bits
                uint256 serviceAgent = serviceId;
                serviceAgent |= uint256(agentIds[i]) << 32;
                delete mapServiceAndAgentIdAgentParams[serviceAgent];
            } else {
                newAgentIds[size] = agentIds[i];
                newAgentParams[size] = agentParams[i];
                size++;
            }
        }
        // Check if the previous hash is the same / hash was not updated
        bytes32 lastConfigHash = service.configHash;
        if (lastConfigHash != configHash) {
            mapConfigHashes[serviceId].push(lastConfigHash);
            service.configHash = configHash;
        }

        // Set service data and record the modified service struct
        _setServiceData(service, newAgentIds, newAgentParams, size, serviceId);
        mapServices[serviceId] = service;

        emit UpdateService(serviceId, configHash);
        success = true;
    }

    /// @dev Activates the service.
    /// @param serviceOwner Individual that creates and controls a service.
    /// @param serviceId Correspondent service Id.
    /// @return success True, if function executed successfully.
    function activateRegistration(address serviceOwner, uint256 serviceId) external payable returns (bool success)
    {
        // Check for the manager privilege for a service management
        if (manager != msg.sender) {
            revert ManagerOnly(msg.sender, manager);
        }

        // Check for the service ownership
        address actualOwner = ownerOf(serviceId);
        if (actualOwner != serviceOwner) {
            revert OwnerOnly(serviceOwner, actualOwner);
        }

        Service storage service = mapServices[serviceId];
        // Service must be inactive
        if (service.state != ServiceState.PreRegistration) {
            revert ServiceMustBeInactive(serviceId);
        }

        if (msg.value != service.securityDeposit) {
            revert IncorrectRegistrationDepositValue(msg.value, service.securityDeposit, serviceId);
        }

        // Activate the agent instance registration
        service.state = ServiceState.ActiveRegistration;

        emit ActivateRegistration(serviceId);
        success = true;
    }

    /// @dev Registers agent instances.
    /// @param operator Address of the operator.
    /// @param serviceId Service Id to be updated.
    /// @param agentInstances Agent instance addresses.
    /// @param agentIds Canonical Ids of the agent correspondent to the agent instance.
    /// @return success True, if function executed successfully.
    function registerAgents(
        address operator,
        uint256 serviceId,
        address[] memory agentInstances,
        uint32[] memory agentIds
    ) external payable returns (bool success)
    {
        // Check for the manager privilege for a service management
        if (manager != msg.sender) {
            revert ManagerOnly(msg.sender, manager);
        }

        // Check if the length of canonical agent instance addresses array and ids array have the same length
        if (agentInstances.length != agentIds.length) {
            revert WrongArrayLength(agentInstances.length, agentIds.length);
        }

        Service storage service = mapServices[serviceId];
        // The service has to be active to register agents
        if (service.state != ServiceState.ActiveRegistration) {
            revert WrongServiceState(uint256(service.state), serviceId);
        }

        // Check for the sufficient amount of bond fee is provided
        uint256 numAgents = agentInstances.length;
        uint256 totalBond = 0;
        for (uint256 i = 0; i < numAgents; ++i) {
            // Check if canonical agent Id exists in the service
            // Push a pair of key defining variables into one key. Service or agent Ids are not enough by themselves
            // serviceId occupies first 32 bits, agentId gets the next 32 bits
            uint256 serviceAgent = serviceId;
            serviceAgent |= uint256(agentIds[i]) << 32;
            AgentParams memory agentParams = mapServiceAndAgentIdAgentParams[serviceAgent];
            if (agentParams.slots == 0) {
                revert AgentNotInService(agentIds[i], serviceId);
            }
            totalBond += agentParams.bond;
        }
        if (msg.value != totalBond) {
            revert IncorrectAgentBondingValue(msg.value, totalBond, serviceId);
        }

        // Operator address must not be used as an agent instance anywhere else
        if (mapAgentInstanceOperators[operator] != address(0)) {
            revert WrongOperator(serviceId);
        }

        // Push a pair of key defining variables into one key. Service Id or operator are not enough by themselves
        // operator occupies first 160 bits
        uint256 operatorService = uint256(uint160(operator));
        // serviceId occupies next 32 bits assuming it is not greater than 2^32 - 1 in value
        operatorService |= serviceId << 160;
        for (uint256 i = 0; i < numAgents; ++i) {
            address agentInstance = agentInstances[i];
            uint32 agentId = agentIds[i];

            // Operator address must be different from agent instance one
            if (operator == agentInstance) {
                revert WrongOperator(serviceId);
            }

            // Check if the agent instance is already engaged with another service
            if (mapAgentInstanceOperators[agentInstance] != address(0)) {
                revert AgentInstanceRegistered(mapAgentInstanceOperators[agentInstance]);
            }

            // Check if there is an empty slot for the agent instance in this specific service
            // serviceId occupies first 32 bits, agentId gets the next 32 bits
            uint256 serviceAgent = serviceId;
            serviceAgent |= uint256(agentIds[i]) << 32;
            if (mapServiceAndAgentIdAgentInstances[serviceAgent].length == mapServiceAndAgentIdAgentParams[serviceAgent].slots) {
                revert AgentInstancesSlotsFilled(serviceId);
            }

            // Add agent instance and operator and set the instance engagement
            mapServiceAndAgentIdAgentInstances[serviceAgent].push(agentInstance);
            mapOperatorAndServiceIdAgentInstances[operatorService].push(AgentInstance(agentInstance, agentId));
            service.numAgentInstances++;
            mapAgentInstanceOperators[agentInstance] = operator;

            emit RegisterInstance(operator, serviceId, agentInstance, agentId);
        }

        // If the service agent instance capacity is reached, the service becomes finished-registration
        if (service.numAgentInstances == service.maxNumAgentInstances) {
            service.state = ServiceState.FinishedRegistration;
        }

        // Update operator's bonding balance
        mapOperatorAndServiceIdOperatorBalances[operatorService] += uint96(msg.value);

        emit Deposit(operator, msg.value);
        success = true;
    }

    /// @dev Creates multisig instance controlled by the set of service agent instances and deploys the service.
    /// @param serviceOwner Individual that creates and controls a service.
    /// @param serviceId Correspondent service Id.
    /// @param multisigImplementation Multisig implementation address.
    /// @param data Data payload for the multisig creation.
    /// @return multisig Address of the created multisig.
    function deploy(
        address serviceOwner,
        uint256 serviceId,
        address multisigImplementation,
        bytes memory data
    ) external returns (address multisig)
    {
        // Reentrancy guard
        if (_locked > 1) {
            revert ReentrancyGuard();
        }
        _locked = 2;

        // Check for the manager privilege for a service management
        if (manager != msg.sender) {
            revert ManagerOnly(msg.sender, manager);
        }

        // Check for the service ownership
        address actualOwner = ownerOf(serviceId);
        if (actualOwner != serviceOwner) {
            revert OwnerOnly(serviceOwner, actualOwner);
        }

        // Check for the whitelisted multisig implementation
        if (!mapMultisigs[multisigImplementation]) {
            revert UnauthorizedMultisig(multisigImplementation);
        }

        Service storage service = mapServices[serviceId];
        if (service.state != ServiceState.FinishedRegistration) {
            revert WrongServiceState(uint256(service.state), serviceId);
        }

        // Get all agent instances for the multisig
        address[] memory agentInstances = _getAgentInstances(service, serviceId);

        // Create a multisig with agent instances
        multisig = IMultisig(multisigImplementation).create(agentInstances, service.threshold, data);

        // Update maps of service Id to subcomponent and agent Ids
        mapServiceIdSetAgentIds[serviceId] = service.agentIds;
        mapServiceIdSetComponentIds[serviceId] = IRegistry(agentRegistry).calculateSubComponents(service.agentIds);

        service.multisig = multisig;
        service.state = ServiceState.Deployed;

        emit CreateMultisigWithAgents(serviceId, multisig);
        emit DeployService(serviceId);

        _locked = 1;
    }

    /// @dev Slashes a specified agent instance.
    /// @param agentInstances Agent instances to slash.
    /// @param amounts Correspondent amounts to slash.
    /// @param serviceId Service Id.
    /// @return success True, if function executed successfully.
    function slash(address[] memory agentInstances, uint96[] memory amounts, uint256 serviceId) external
        returns (bool success)
    {
        // Check if the service is deployed
        // Since we do not kill (burn) services, we want this check to happen in a right service state.
        // If the service is deployed, it definitely exists and is running. We do not want this function to be abused
        // when the service was deployed, then terminated, then in a sleep mode or before next deployment somebody
        // could use this function and try to slash operators.
        Service memory service = mapServices[serviceId];
        if (service.state != ServiceState.Deployed) {
            revert WrongServiceState(uint256(service.state), serviceId);
        }

        // Check for the array size
        if (agentInstances.length != amounts.length) {
            revert WrongArrayLength(agentInstances.length, amounts.length);
        }

        // Only the multisig of a correspondent address can slash its agent instances
        if (msg.sender != service.multisig) {
            revert OnlyOwnServiceMultisig(msg.sender, service.multisig, serviceId);
        }

        // Loop over each agent instance
        uint256 numInstancesToSlash = agentInstances.length;
        for (uint256 i = 0; i < numInstancesToSlash; ++i) {
            // Get the service Id from the agentInstance map
            address operator = mapAgentInstanceOperators[agentInstances[i]];
            // Push a pair of key defining variables into one key. Service Id or operator are not enough by themselves
            // operator occupies first 160 bits
            uint256 operatorService = uint256(uint160(operator));
            // serviceId occupies next 32 bits
            operatorService |= serviceId << 160;
            // Slash the balance of the operator, make sure it does not go below zero
            uint96 balance = mapOperatorAndServiceIdOperatorBalances[operatorService];
            if ((amounts[i] + 1) > balance) {
                // We cannot add to the slashed amount more than the balance of the operator
                slashedFunds += balance;
                balance = 0;
            } else {
                slashedFunds += amounts[i];
                balance -= amounts[i];
            }
            mapOperatorAndServiceIdOperatorBalances[operatorService] = balance;

            emit OperatorSlashed(amounts[i], operator, serviceId);
        }
        success = true;
    }

    /// @dev Terminates the service.
    /// @param serviceOwner Owner of the service.
    /// @param serviceId Service Id to be updated.
    /// @return success True, if function executed successfully.
    /// @return refund Refund to return to the service owner.
    function terminate(address serviceOwner, uint256 serviceId) external returns (bool success, uint256 refund)
    {
        // Reentrancy guard
        if (_locked > 1) {
            revert ReentrancyGuard();
        }
        _locked = 2;

        // Check for the manager privilege for a service management
        if (manager != msg.sender) {
            revert ManagerOnly(msg.sender, manager);
        }

        // Check for the service ownership
        address actualOwner = ownerOf(serviceId);
        if (actualOwner != serviceOwner) {
            revert OwnerOnly(serviceOwner, actualOwner);
        }

        Service storage service = mapServices[serviceId];
        // Check if the service is already terminated
        if (service.state == ServiceState.PreRegistration || service.state == ServiceState.TerminatedBonded) {
            revert WrongServiceState(uint256(service.state), serviceId);
        }
        // Define the state of the service depending on the number of bonded agent instances
        if (service.numAgentInstances > 0) {
            service.state = ServiceState.TerminatedBonded;
        } else {
            service.state = ServiceState.PreRegistration;
        }
        
        // Delete the sensitive data
        delete mapServiceIdSetComponentIds[serviceId];
        delete mapServiceIdSetAgentIds[serviceId];
        for (uint256 i = 0; i < service.agentIds.length; ++i) {
            // serviceId occupies first 32 bits, agentId gets the next 32 bits
            uint256 serviceAgent = serviceId;
            serviceAgent |= uint256(service.agentIds[i]) << 32;
            delete mapServiceAndAgentIdAgentInstances[serviceAgent];
        }

        // Return registration deposit back to the service owner
        refund = service.securityDeposit;
        // By design, the refund is always a non-zero value, so no check is needed here fo that
        (bool result, ) = serviceOwner.call{value: refund}("");
        if (!result) {
            revert TransferFailed(address(0), address(this), serviceOwner, refund);
        }

        emit Refund(serviceOwner, refund);
        emit TerminateService(serviceId);
        success = true;

        _locked = 1;
    }

    /// @dev Unbonds agent instances of the operator from the service.
    /// @param operator Operator of agent instances.
    /// @param serviceId Service Id.
    /// @return success True, if function executed successfully.
    /// @return refund The amount of refund returned to the operator.
    function unbond(address operator, uint256 serviceId) external returns (bool success, uint256 refund) {
        // Reentrancy guard
        if (_locked > 1) {
            revert ReentrancyGuard();
        }
        _locked = 2;

        // Check for the manager privilege for a service management
        if (manager != msg.sender) {
            revert ManagerOnly(msg.sender, manager);
        }

        // Checks if the operator address is not zero
        if (operator == address(0)) {
            revert ZeroAddress();
        }

        Service storage service = mapServices[serviceId];
        // Service can only be in the terminated-bonded state or expired-registration in order to proceed
        if (service.state != ServiceState.TerminatedBonded) {
            revert WrongServiceState(uint256(service.state), serviceId);
        }

        // Check for the operator and unbond all its agent instances
        // Push a pair of key defining variables into one key. Service Id or operator are not enough by themselves
        // operator occupies first 160 bits
        uint256 operatorService = uint256(uint160(operator));
        // serviceId occupies next 32 bits
        operatorService |= serviceId << 160;
        AgentInstance[] memory agentInstances = mapOperatorAndServiceIdAgentInstances[operatorService];
        uint256 numAgentsUnbond = agentInstances.length;
        if (numAgentsUnbond == 0) {
            revert OperatorHasNoInstances(operator, serviceId);
        }

        // Subtract number of unbonded agent instances
        service.numAgentInstances -= uint32(numAgentsUnbond);
        // When number of instances is equal to zero, all the operators have unbonded and the service is moved into
        // the PreRegistration state, from where it can be updated / start registration / get deployed again
        if (service.numAgentInstances == 0) {
            service.state = ServiceState.PreRegistration;
        }
        // else condition is redundant here, since the service is either in the TerminatedBonded state, or moved
        // into the PreRegistration state and unbonding is not possible before the new TerminatedBonded state is reached

        // Calculate registration refund and free all agent instances
        for (uint256 i = 0; i < numAgentsUnbond; i++) {
            // serviceId occupies first 32 bits, agentId gets the next 32 bits
            uint256 serviceAgent = serviceId;
            serviceAgent |= uint256(agentInstances[i].agentId) << 32;
            refund += mapServiceAndAgentIdAgentParams[serviceAgent].bond;
            // Clean-up the sensitive data such that it is not reused later
            delete mapAgentInstanceOperators[agentInstances[i].instance];
        }
        // Clean all the operator agent instances records for this service
        delete mapOperatorAndServiceIdAgentInstances[operatorService];

        // Calculate the refund
        uint96 balance = mapOperatorAndServiceIdOperatorBalances[operatorService];
        // This situation is possible if the operator was slashed for the agent instance misbehavior
        if (refund > balance) {
            refund = balance;
        }

        // Refund the operator
        if (refund > 0) {
            // Operator's balance is essentially zero after the refund
            mapOperatorAndServiceIdOperatorBalances[operatorService] = 0;
            // Send the refund
            (bool result, ) = operator.call{value: refund}("");
            if (!result) {
                revert TransferFailed(address(0), address(this), operator, refund);
            }
            emit Refund(operator, refund);
        }

        emit OperatorUnbond(operator, serviceId);
        success = true;

        _locked = 1;
    }

    /// @dev Gets the service instance.
    /// @param serviceId Service Id.
    /// @return service Corresponding Service struct.
    function getService(uint256 serviceId) external view returns (Service memory service) {
        service = mapServices[serviceId];
    }

    /// @dev Gets service agent parameters: number of agent instances (slots) and a bond amount.
    /// @param serviceId Service Id.
    /// @return numAgentIds Number of canonical agent Ids in the service.
    /// @return agentParams Set of agent parameters for each canonical agent Id.
    function getAgentParams(uint256 serviceId) external view
        returns (uint256 numAgentIds, AgentParams[] memory agentParams)
    {
        Service memory service = mapServices[serviceId];
        numAgentIds = service.agentIds.length;
        agentParams = new AgentParams[](numAgentIds);
        for (uint256 i = 0; i < numAgentIds; ++i) {
            uint256 serviceAgent = serviceId;
            serviceAgent |= uint256(service.agentIds[i]) << 32;
            agentParams[i] = mapServiceAndAgentIdAgentParams[serviceAgent];
        }
    }

    /// @dev Lists all the instances of a given canonical agent Id if the service.
    /// @param serviceId Service Id.
    /// @param agentId Canonical agent Id.
    /// @return numAgentInstances Number of agent instances.
    /// @return agentInstances Set of agent instances for a specified canonical agent Id.
    function getInstancesForAgentId(uint256 serviceId, uint256 agentId) external view
        returns (uint256 numAgentInstances, address[] memory agentInstances)
    {
        uint256 serviceAgent = serviceId;
        serviceAgent |= agentId << 32;
        numAgentInstances = mapServiceAndAgentIdAgentInstances[serviceAgent].length;
        agentInstances = new address[](numAgentInstances);
        for (uint256 i = 0; i < numAgentInstances; i++) {
            agentInstances[i] = mapServiceAndAgentIdAgentInstances[serviceAgent][i];
        }
    }

    /// @dev Gets all agent instances.
    /// @param service Service instance.
    /// @param serviceId ServiceId.
    /// @return agentInstances Pre-allocated list of agent instance addresses.
    function _getAgentInstances(Service memory service, uint256 serviceId) private view
        returns (address[] memory agentInstances)
    {
        agentInstances = new address[](service.numAgentInstances);
        uint256 count;
        for (uint256 i = 0; i < service.agentIds.length; i++) {
            // serviceId occupies first 32 bits, agentId gets the next 32 bits
            uint256 serviceAgent = serviceId;
            serviceAgent |= uint256(service.agentIds[i]) << 32;
            for (uint256 j = 0; j < mapServiceAndAgentIdAgentInstances[serviceAgent].length; j++) {
                agentInstances[count] = mapServiceAndAgentIdAgentInstances[serviceAgent][j];
                count++;
            }
        }
    }

    /// @dev Gets service agent instances.
    /// @param serviceId ServiceId.
    /// @return numAgentInstances Number of agent instances.
    /// @return agentInstances Pre-allocated list of agent instance addresses.
    function getAgentInstances(uint256 serviceId) external view
        returns (uint256 numAgentInstances, address[] memory agentInstances)
    {
        Service memory service = mapServices[serviceId];
        agentInstances = _getAgentInstances(service, serviceId);
        numAgentInstances = agentInstances.length;
    }

    /// @dev Gets previous service config hashes.
    /// @param serviceId Service Id.
    /// @return numHashes Number of hashes.
    /// @return configHashes The list of previous component hashes (excluding the current one).
    function getPreviousHashes(uint256 serviceId) external view
        returns (uint256 numHashes, bytes32[] memory configHashes)
    {
        configHashes = mapConfigHashes[serviceId];
        numHashes = configHashes.length;
    }

    /// @dev Gets the full set of linearized components / canonical agent Ids for a specified service.
    /// @notice The service must be / have been deployed in order to get the actual data.
    /// @param serviceId Service Id.
    /// @return numUnitIds Number of component / agent Ids.
    /// @return unitIds Set of component / agent Ids.
    function getUnitIdsOfService(IRegistry.UnitType unitType, uint256 serviceId) external view
        returns (uint256 numUnitIds, uint32[] memory unitIds)
    {
        if (unitType == IRegistry.UnitType.Component) {
            unitIds = mapServiceIdSetComponentIds[serviceId];
        } else {
            unitIds = mapServiceIdSetAgentIds[serviceId];
        }
        numUnitIds = unitIds.length;
    }

    /// @dev Gets the operator's balance in a specific service.
    /// @param operator Operator address.
    /// @param serviceId Service Id.
    /// @return balance The balance of the operator.
    function getOperatorBalance(address operator, uint256 serviceId) external view returns (uint256 balance)
    {
        uint256 operatorService = uint256(uint160(operator));
        operatorService |= serviceId << 160;
        balance = mapOperatorAndServiceIdOperatorBalances[operatorService];
    }

    /// @dev Controls multisig implementation address permission.
    /// @param multisig Address of a multisig implementation.
    /// @param permission Grant or revoke permission.
    /// @return success True, if function executed successfully.
    function changeMultisigPermission(address multisig, bool permission) external returns (bool success) {
        // Check for the contract ownership
        if (msg.sender != owner) {
            revert OwnerOnly(msg.sender, owner);
        }

        if (multisig == address(0)) {
            revert ZeroAddress();
        }
        mapMultisigs[multisig] = permission;
        success = true;
    }

    /// @dev Drains slashed funds.
    /// @return amount Drained amount.
    function drain() external returns (uint256 amount) {
        // Reentrancy guard
        if (_locked > 1) {
            revert ReentrancyGuard();
        }
        _locked = 2;

        // Check for the drainer address
        if (msg.sender != drainer) {
            revert ManagerOnly(msg.sender, drainer);
        }

        // Drain the slashed funds
        amount = slashedFunds;
        if (amount > 0) {
            slashedFunds = 0;
            // Send the refund
            (bool result, ) = msg.sender.call{value: amount}("");
            if (!result) {
                revert TransferFailed(address(0), address(this), msg.sender, amount);
            }
            emit Drain(msg.sender, amount);
        }

        _locked = 1;
    }

    /// @dev Gets the hash of the service.
    /// @param serviceId Service Id.
    /// @return Service hash.
    function _getUnitHash(uint256 serviceId) internal view override returns (bytes32) {
        return mapServices[serviceId].configHash;
    }
}

File 2 of 6 : GenericRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import "../lib/solmate/src/tokens/ERC721.sol";
import "./interfaces/IErrorsRegistries.sol";

/// @title Generic Registry - Smart contract for generic registry template
/// @author Aleksandr Kuperman - <[email protected]>
abstract contract GenericRegistry is IErrorsRegistries, ERC721 {
    event OwnerUpdated(address indexed owner);
    event ManagerUpdated(address indexed manager);
    event BaseURIChanged(string baseURI);

    // Owner address
    address public owner;
    // Unit manager
    address public manager;
    // Base URI
    string public baseURI;
    // Unit counter
    uint256 public totalSupply;
    // Reentrancy lock
    uint256 internal _locked = 1;
    // To better understand the CID anatomy, please refer to: https://proto.school/anatomy-of-a-cid/05
    // CID = <multibase_encoding>multibase_encoding(<cid-version><multicodec><multihash-algorithm><multihash-length><multihash-hash>)
    // CID prefix = <multibase_encoding>multibase_encoding(<cid-version><multicodec><multihash-algorithm><multihash-length>)
    // to complement the multibase_encoding(<multihash-hash>)
    // multibase_encoding = base16 = "f"
    // cid-version = version 1 = "0x01"
    // multicodec = dag-pb = "0x70"
    // multihash-algorithm = sha2-256 = "0x12"
    // multihash-length = 256 bits = "0x20"
    string public constant CID_PREFIX = "f01701220";

    /// @dev Changes the owner address.
    /// @param newOwner Address of a new owner.
    function changeOwner(address newOwner) external virtual {
        // Check for the ownership
        if (msg.sender != owner) {
            revert OwnerOnly(msg.sender, owner);
        }

        // Check for the zero address
        if (newOwner == address(0)) {
            revert ZeroAddress();
        }

        owner = newOwner;
        emit OwnerUpdated(newOwner);
    }

    /// @dev Changes the unit manager.
    /// @param newManager Address of a new unit manager.
    function changeManager(address newManager) external virtual {
        if (msg.sender != owner) {
            revert OwnerOnly(msg.sender, owner);
        }

        // Check for the zero address
        if (newManager == address(0)) {
            revert ZeroAddress();
        }

        manager = newManager;
        emit ManagerUpdated(newManager);
    }

    /// @dev Checks for the unit existence.
    /// @notice Unit counter starts from 1.
    /// @param unitId Unit Id.
    /// @return true if the unit exists, false otherwise.
    function exists(uint256 unitId) external view virtual returns (bool) {
        return unitId > 0 && unitId < (totalSupply + 1);
    }
    
    /// @dev Sets unit base URI.
    /// @param bURI Base URI string.
    function setBaseURI(string memory bURI) external virtual {
        // Check for the ownership
        if (msg.sender != owner) {
            revert OwnerOnly(msg.sender, owner);
        }

        // Check for the zero value
        if (bytes(bURI).length == 0) {
            revert ZeroValue();
        }

        baseURI = bURI;
        emit BaseURIChanged(bURI);
    }

    /// @dev Gets the valid unit Id from the provided index.
    /// @notice Unit counter starts from 1.
    /// @param id Unit counter.
    /// @return unitId Unit Id.
    function tokenByIndex(uint256 id) external view virtual returns (uint256 unitId) {
        unitId = id + 1;
        if (unitId > totalSupply) {
            revert Overflow(unitId, totalSupply);
        }
    }

    // Open sourced from: https://stackoverflow.com/questions/67893318/solidity-how-to-represent-bytes32-as-string
    /// @dev Converts bytes16 input data to hex16.
    /// @notice This method converts bytes into the same bytes-character hex16 representation.
    /// @param data bytes16 input data.
    /// @return result hex16 conversion from the input bytes16 data.
    function _toHex16(bytes16 data) internal pure returns (bytes32 result) {
        result = bytes32 (data) & 0xFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000 |
        (bytes32 (data) & 0x0000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000) >> 64;
        result = result & 0xFFFFFFFF000000000000000000000000FFFFFFFF000000000000000000000000 |
        (result & 0x00000000FFFFFFFF000000000000000000000000FFFFFFFF0000000000000000) >> 32;
        result = result & 0xFFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000 |
        (result & 0x0000FFFF000000000000FFFF000000000000FFFF000000000000FFFF00000000) >> 16;
        result = result & 0xFF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000 |
        (result & 0x00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000) >> 8;
        result = (result & 0xF000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000) >> 4 |
        (result & 0x0F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F00) >> 8;
        result = bytes32 (0x3030303030303030303030303030303030303030303030303030303030303030 +
        uint256 (result) +
            (uint256 (result) + 0x0606060606060606060606060606060606060606060606060606060606060606 >> 4 &
            0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F) * 39);
    }

    /// @dev Gets the hash of the unit.
    /// @param unitId Unit Id.
    /// @return Unit hash.
    function _getUnitHash(uint256 unitId) internal view virtual returns (bytes32);

    /// @dev Returns unit token URI.
    /// @notice Expected multicodec: dag-pb; hashing function: sha2-256, with base16 encoding and leading CID_PREFIX removed.
    /// @param unitId Unit Id.
    /// @return Unit token URI string.
    function tokenURI(uint256 unitId) public view virtual override returns (string memory) {
        bytes32 unitHash = _getUnitHash(unitId);
        // Parse 2 parts of bytes32 into left and right hex16 representation, and concatenate into string
        // adding the base URI and a cid prefix for the full base16 multibase prefix IPFS hash representation
        return string(abi.encodePacked(baseURI, CID_PREFIX, _toHex16(bytes16(unitHash)),
            _toHex16(bytes16(unitHash << 128))));
    }
}

File 3 of 6 : IMultisig.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

/// @dev Generic multisig.
interface IMultisig {
    /// @dev Creates a multisig.
    /// @param owners Set of multisig owners.
    /// @param threshold Number of required confirmations for a multisig transaction.
    /// @param data Packed data related to the creation of a chosen multisig.
    /// @return multisig Address of a created multisig.
    function create(
        address[] memory owners,
        uint256 threshold,
        bytes memory data
    ) external returns (address multisig);
}

File 4 of 6 : IRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

/// @dev Required interface for the component / agent manipulation.
interface IRegistry {
    enum UnitType {
        Component,
        Agent
    }

    /// @dev Creates component / agent.
    /// @param unitOwner Owner of the component / agent.
    /// @param unitHash IPFS hash of the component / agent.
    /// @param dependencies Set of component dependencies in a sorted ascending order.
    /// @return The id of a minted component / agent.
    function create(
        address unitOwner,
        bytes32 unitHash,
        uint32[] memory dependencies
    ) external returns (uint256);

    /// @dev Updates the component / agent hash.
    /// @param owner Owner of the component / agent.
    /// @param unitId Unit Id.
    /// @param unitHash Updated IPFS hash of the component / agent.
    /// @return success True, if function executed successfully.
    function updateHash(address owner, uint256 unitId, bytes32 unitHash) external returns (bool success);

    /// @dev Gets subcomponents of a provided unit Id from a local public map.
    /// @param unitId Unit Id.
    /// @return subComponentIds Set of subcomponents.
    /// @return numSubComponents Number of subcomponents.
    function getLocalSubComponents(uint256 unitId) external view returns (uint32[] memory subComponentIds, uint256 numSubComponents);

    /// @dev Calculates the set of subcomponent Ids.
    /// @param unitIds Set of unit Ids.
    /// @return subComponentIds Subcomponent Ids.
    function calculateSubComponents(uint32[] memory unitIds) external view returns (uint32[] memory subComponentIds);

    /// @dev Gets updated component / agent hashes.
    /// @param unitId Unit Id.
    /// @return numHashes Number of hashes.
    /// @return unitHashes The list of component / agent hashes.
    function getUpdatedHashes(uint256 unitId) external view returns (uint256 numHashes, bytes32[] memory unitHashes);

    /// @dev Gets the total supply of components / agents.
    /// @return Total supply.
    function totalSupply() external view returns (uint256);
}

File 5 of 6 : ERC721.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*//////////////////////////////////////////////////////////////
                         METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                      ERC721 BALANCE/OWNER STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) internal _ownerOf;

    mapping(address => uint256) internal _balanceOf;

    function ownerOf(uint256 id) public view virtual returns (address owner) {
        require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
    }

    function balanceOf(address owner) public view virtual returns (uint256) {
        require(owner != address(0), "ZERO_ADDRESS");

        return _balanceOf[owner];
    }

    /*//////////////////////////////////////////////////////////////
                         ERC721 APPROVAL STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) public virtual {
        address owner = _ownerOf[id];

        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        require(from == _ownerOf[id], "WRONG_FROM");

        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
            "NOT_AUTHORIZED"
        );

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            _balanceOf[from]--;

            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        transferFrom(from, to, id);

        if (to.code.length != 0)
            require(
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
                    ERC721TokenReceiver.onERC721Received.selector,
                "UNSAFE_RECIPIENT"
            );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes calldata data
    ) public virtual {
        transferFrom(from, to, id);

        if (to.code.length != 0)
            require(
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
                    ERC721TokenReceiver.onERC721Received.selector,
                "UNSAFE_RECIPIENT"
            );
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal virtual {
        require(to != address(0), "INVALID_RECIPIENT");

        require(_ownerOf[id] == address(0), "ALREADY_MINTED");

        // Counter overflow is incredibly unrealistic.
        unchecked {
            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        emit Transfer(address(0), to, id);
    }

    function _burn(uint256 id) internal virtual {
        address owner = _ownerOf[id];

        require(owner != address(0), "NOT_MINTED");

        // Ownership check above ensures no underflow.
        unchecked {
            _balanceOf[owner]--;
        }

        delete _ownerOf[id];

        delete getApproved[id];

        emit Transfer(owner, address(0), id);
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL SAFE MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _safeMint(address to, uint256 id) internal virtual {
        _mint(to, id);

        if (to.code.length != 0)
            require(
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
                    ERC721TokenReceiver.onERC721Received.selector,
                "UNSAFE_RECIPIENT"
            );
    }

    function _safeMint(
        address to,
        uint256 id,
        bytes memory data
    ) internal virtual {
        _mint(to, id);

        if (to.code.length != 0)
            require(
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
                    ERC721TokenReceiver.onERC721Received.selector,
                "UNSAFE_RECIPIENT"
            );
    }
}

/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721TokenReceiver {
    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC721TokenReceiver.onERC721Received.selector;
    }
}

File 6 of 6 : IErrorsRegistries.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

/// @dev Errors.
interface IErrorsRegistries {
    /// @dev Only `manager` has a privilege, but the `sender` was provided.
    /// @param sender Sender address.
    /// @param manager Required sender address as a manager.
    error ManagerOnly(address sender, address manager);

    /// @dev Only `owner` has a privilege, but the `sender` was provided.
    /// @param sender Sender address.
    /// @param owner Required sender address as an owner.
    error OwnerOnly(address sender, address owner);

    /// @dev Hash already exists in the records.
    error HashExists();

    /// @dev Provided zero address.
    error ZeroAddress();

    /// @dev Agent Id is not correctly provided for the current routine.
    /// @param agentId Component Id.
    error WrongAgentId(uint256 agentId);

    /// @dev Wrong length of two arrays.
    /// @param numValues1 Number of values in a first array.
    /// @param numValues2 Numberf of values in a second array.
    error WrongArrayLength(uint256 numValues1, uint256 numValues2);

    /// @dev Canonical agent Id is not found.
    /// @param agentId Canonical agent Id.
    error AgentNotFound(uint256 agentId);

    /// @dev Component Id is not found.
    /// @param componentId Component Id.
    error ComponentNotFound(uint256 componentId);

    /// @dev Multisig threshold is out of bounds.
    /// @param currentThreshold Current threshold value.
    /// @param minThreshold Minimum possible threshold value.
    /// @param maxThreshold Maximum possible threshold value.
    error WrongThreshold(uint256 currentThreshold, uint256 minThreshold, uint256 maxThreshold);

    /// @dev Agent instance is already registered with a specified `operator`.
    /// @param operator Operator that registered an instance.
    error AgentInstanceRegistered(address operator);

    /// @dev Wrong operator is specified when interacting with a specified `serviceId`.
    /// @param serviceId Service Id.
    error WrongOperator(uint256 serviceId);

    /// @dev Operator has no registered instances in the service.
    /// @param operator Operator address.
    /// @param serviceId Service Id.
    error OperatorHasNoInstances(address operator, uint256 serviceId);

    /// @dev Canonical `agentId` is not found as a part of `serviceId`.
    /// @param agentId Canonical agent Id.
    /// @param serviceId Service Id.
    error AgentNotInService(uint256 agentId, uint256 serviceId);

    /// @dev The contract is paused.
    error Paused();

    /// @dev Zero value when it has to be different from zero.
    error ZeroValue();

    /// @dev Value overflow.
    /// @param provided Overflow value.
    /// @param max Maximum possible value.
    error Overflow(uint256 provided, uint256 max);

    /// @dev Service must be inactive.
    /// @param serviceId Service Id.
    error ServiceMustBeInactive(uint256 serviceId);

    /// @dev All the agent instance slots for a specific `serviceId` are filled.
    /// @param serviceId Service Id.
    error AgentInstancesSlotsFilled(uint256 serviceId);

    /// @dev Wrong state of a service.
    /// @param state Service state.
    /// @param serviceId Service Id.
    error WrongServiceState(uint256 state, uint256 serviceId);

    /// @dev Only own service multisig is allowed.
    /// @param provided Provided address.
    /// @param expected Expected multisig address.
    /// @param serviceId Service Id.
    error OnlyOwnServiceMultisig(address provided, address expected, uint256 serviceId);

    /// @dev Multisig is not whitelisted.
    /// @param multisig Address of a multisig implementation.
    error UnauthorizedMultisig(address multisig);

    /// @dev Incorrect deposit provided for the registration activation.
    /// @param sent Sent amount.
    /// @param expected Expected amount.
    /// @param serviceId Service Id.
    error IncorrectRegistrationDepositValue(uint256 sent, uint256 expected, uint256 serviceId);

    /// @dev Insufficient value provided for the agent instance bonding.
    /// @param sent Sent amount.
    /// @param expected Expected amount.
    /// @param serviceId Service Id.
    error IncorrectAgentBondingValue(uint256 sent, uint256 expected, uint256 serviceId);

    /// @dev Failure of a transfer.
    /// @param token Address of a token.
    /// @param from Address `from`.
    /// @param to Address `to`.
    /// @param value Value.
    error TransferFailed(address token, address from, address to, uint256 value);

    /// @dev Caught reentrancy violation.
    error ReentrancyGuard();
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_baseURI","type":"string"},{"internalType":"address","name":"_agentRegistry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"AgentInstanceRegistered","type":"error"},{"inputs":[{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"AgentInstancesSlotsFilled","type":"error"},{"inputs":[{"internalType":"uint256","name":"agentId","type":"uint256"}],"name":"AgentNotFound","type":"error"},{"inputs":[{"internalType":"uint256","name":"agentId","type":"uint256"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"AgentNotInService","type":"error"},{"inputs":[{"internalType":"uint256","name":"componentId","type":"uint256"}],"name":"ComponentNotFound","type":"error"},{"inputs":[],"name":"HashExists","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"IncorrectAgentBondingValue","type":"error"},{"inputs":[{"internalType":"uint256","name":"sent","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"IncorrectRegistrationDepositValue","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"manager","type":"address"}],"name":"ManagerOnly","type":"error"},{"inputs":[{"internalType":"address","name":"provided","type":"address"},{"internalType":"address","name":"expected","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"OnlyOwnServiceMultisig","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"OperatorHasNoInstances","type":"error"},{"inputs":[{"internalType":"uint256","name":"provided","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"Overflow","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"OwnerOnly","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"ReentrancyGuard","type":"error"},{"inputs":[{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"ServiceMustBeInactive","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferFailed","type":"error"},{"inputs":[{"internalType":"address","name":"multisig","type":"address"}],"name":"UnauthorizedMultisig","type":"error"},{"inputs":[{"internalType":"uint256","name":"agentId","type":"uint256"}],"name":"WrongAgentId","type":"error"},{"inputs":[{"internalType":"uint256","name":"numValues1","type":"uint256"},{"internalType":"uint256","name":"numValues2","type":"uint256"}],"name":"WrongArrayLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"WrongOperator","type":"error"},{"inputs":[{"internalType":"uint256","name":"state","type":"uint256"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"WrongServiceState","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentThreshold","type":"uint256"},{"internalType":"uint256","name":"minThreshold","type":"uint256"},{"internalType":"uint256","name":"maxThreshold","type":"uint256"}],"name":"WrongThreshold","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroValue","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"ActivateRegistration","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"baseURI","type":"string"}],"name":"BaseURIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"serviceId","type":"uint256"},{"indexed":true,"internalType":"address","name":"multisig","type":"address"}],"name":"CreateMultisigWithAgents","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"CreateService","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"DeployService","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"drainer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Drain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"drainer","type":"address"}],"name":"DrainerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"manager","type":"address"}],"name":"ManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"OperatorSlashed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"OperatorUnbond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Refund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"uint256","name":"serviceId","type":"uint256"},{"indexed":true,"internalType":"address","name":"agentInstance","type":"address"},{"indexed":false,"internalType":"uint256","name":"agentId","type":"uint256"}],"name":"RegisterInstance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"TerminateService","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"serviceId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"configHash","type":"bytes32"}],"name":"UpdateService","type":"event"},{"inputs":[],"name":"CID_PREFIX","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"serviceOwner","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"activateRegistration","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"agentRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newDrainer","type":"address"}],"name":"changeDrainer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newManager","type":"address"}],"name":"changeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"multisig","type":"address"},{"internalType":"bool","name":"permission","type":"bool"}],"name":"changeMultisigPermission","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"changeOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"serviceOwner","type":"address"},{"internalType":"bytes32","name":"configHash","type":"bytes32"},{"internalType":"uint32[]","name":"agentIds","type":"uint32[]"},{"components":[{"internalType":"uint32","name":"slots","type":"uint32"},{"internalType":"uint96","name":"bond","type":"uint96"}],"internalType":"struct AgentParams[]","name":"agentParams","type":"tuple[]"},{"internalType":"uint32","name":"threshold","type":"uint32"}],"name":"create","outputs":[{"internalType":"uint256","name":"serviceId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"serviceOwner","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"},{"internalType":"address","name":"multisigImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"deploy","outputs":[{"internalType":"address","name":"multisig","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"drain","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"drainer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"unitId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"getAgentInstances","outputs":[{"internalType":"uint256","name":"numAgentInstances","type":"uint256"},{"internalType":"address[]","name":"agentInstances","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"getAgentParams","outputs":[{"internalType":"uint256","name":"numAgentIds","type":"uint256"},{"components":[{"internalType":"uint32","name":"slots","type":"uint32"},{"internalType":"uint96","name":"bond","type":"uint96"}],"internalType":"struct AgentParams[]","name":"agentParams","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"serviceId","type":"uint256"},{"internalType":"uint256","name":"agentId","type":"uint256"}],"name":"getInstancesForAgentId","outputs":[{"internalType":"uint256","name":"numAgentInstances","type":"uint256"},{"internalType":"address[]","name":"agentInstances","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"getOperatorBalance","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"getPreviousHashes","outputs":[{"internalType":"uint256","name":"numHashes","type":"uint256"},{"internalType":"bytes32[]","name":"configHashes","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"getService","outputs":[{"components":[{"internalType":"uint96","name":"securityDeposit","type":"uint96"},{"internalType":"address","name":"multisig","type":"address"},{"internalType":"bytes32","name":"configHash","type":"bytes32"},{"internalType":"uint32","name":"threshold","type":"uint32"},{"internalType":"uint32","name":"maxNumAgentInstances","type":"uint32"},{"internalType":"uint32","name":"numAgentInstances","type":"uint32"},{"internalType":"enum ServiceRegistry.ServiceState","name":"state","type":"uint8"},{"internalType":"uint32[]","name":"agentIds","type":"uint32[]"}],"internalType":"struct ServiceRegistry.Service","name":"service","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IRegistry.UnitType","name":"unitType","type":"uint8"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"getUnitIdsOfService","outputs":[{"internalType":"uint256","name":"numUnitIds","type":"uint256"},{"internalType":"uint32[]","name":"unitIds","type":"uint32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mapAgentInstanceOperators","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"mapConfigHashes","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mapMultisigs","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"mapOperatorAndServiceIdAgentInstances","outputs":[{"internalType":"address","name":"instance","type":"address"},{"internalType":"uint32","name":"agentId","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"mapOperatorAndServiceIdOperatorBalances","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"mapServiceAndAgentIdAgentInstances","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"mapServiceAndAgentIdAgentParams","outputs":[{"internalType":"uint32","name":"slots","type":"uint32"},{"internalType":"uint96","name":"bond","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"mapServiceIdSetAgentIds","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"mapServiceIdSetComponentIds","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"mapServices","outputs":[{"internalType":"uint96","name":"securityDeposit","type":"uint96"},{"internalType":"address","name":"multisig","type":"address"},{"internalType":"bytes32","name":"configHash","type":"bytes32"},{"internalType":"uint32","name":"threshold","type":"uint32"},{"internalType":"uint32","name":"maxNumAgentInstances","type":"uint32"},{"internalType":"uint32","name":"numAgentInstances","type":"uint32"},{"internalType":"enum ServiceRegistry.ServiceState","name":"state","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"},{"internalType":"address[]","name":"agentInstances","type":"address[]"},{"internalType":"uint32[]","name":"agentIds","type":"uint32[]"}],"name":"registerAgents","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"bURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"agentInstances","type":"address[]"},{"internalType":"uint96[]","name":"amounts","type":"uint96[]"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"slash","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slashedFunds","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"serviceOwner","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"terminate","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"refund","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"unitId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"unitId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"unbond","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"refund","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"serviceOwner","type":"address"},{"internalType":"bytes32","name":"configHash","type":"bytes32"},{"internalType":"uint32[]","name":"agentIds","type":"uint32[]"},{"components":[{"internalType":"uint32","name":"slots","type":"uint32"},{"internalType":"uint96","name":"bond","type":"uint96"}],"internalType":"struct AgentParams[]","name":"agentParams","type":"tuple[]"},{"internalType":"uint32","name":"threshold","type":"uint32"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"update","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

60a06040526001600a553480156200001657600080fd5b506040516200636638038062006366833981016040819052620000399162000160565b83836000620000498382620002a2565b506001620000588282620002a2565b50600891506200006b90508382620002a2565b506001600160a01b03166080525050600680546001600160a01b03191633179055506200036e565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000bb57600080fd5b81516001600160401b0380821115620000d857620000d862000093565b604051601f8301601f19908116603f0116810190828211818310171562000103576200010362000093565b816040528381526020925086838588010111156200012057600080fd5b600091505b8382101562000144578582018301518183018401529082019062000125565b83821115620001565760008385830101525b9695505050505050565b600080600080608085870312156200017757600080fd5b84516001600160401b03808211156200018f57600080fd5b6200019d88838901620000a9565b95506020870151915080821115620001b457600080fd5b620001c288838901620000a9565b94506040870151915080821115620001d957600080fd5b50620001e887828801620000a9565b606087015190935090506001600160a01b03811681146200020857600080fd5b939692955090935050565b600181811c908216806200022857607f821691505b6020821081036200024957634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029d57600081815260208120601f850160051c81016020861015620002785750805b601f850160051c820191505b81811015620002995782815560010162000284565b5050505b505050565b81516001600160401b03811115620002be57620002be62000093565b620002d681620002cf845462000213565b846200024f565b602080601f8311600181146200030e5760008415620002f55750858301515b600019600386901b1c1916600185901b17855562000299565b600085815260208120601f198616915b828110156200033f578886015182559484019460019091019084016200031e565b50858210156200035e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b608051615fce620003986000396000818161043e01528181613e9e01526146600152615fce6000f3fe6080604052600436106103605760003560e01c80636f99f15c116101c6578063a5d059ca116100f7578063dff7672411610095578063ef0e239b1161006f578063ef0e239b14610bda578063f908bc7714610c07578063fbdeb3d714610c27578063ffa1ad7414610c4757600080fd5b8063dff7672414610b79578063e23f6fb414610b8c578063e985e9c514610b9f57600080fd5b8063b88d4fde116100d1578063b88d4fde14610af9578063c87b56dd14610b19578063cbf994f814610b39578063ccc9305d14610b5957600080fd5b8063a5d059ca14610a74578063a60e4c3c14610aab578063a6f9dae114610ad957600080fd5b80638a2bd86f1161016457806395d89b411161013e57806395d89b4114610a0a5780639890220b14610a1f578063a22cb46514610a34578063a3fbbaae14610a5457600080fd5b80638a2bd86f146109775780638da5cb5b146109bc57806392080b23146109dc57600080fd5b806373b8b6a2116101a057806373b8b6a2146108e25780637c5e63e01461090257806382694b1d1461093757806386a2bdd41461095757600080fd5b80636f99f15c1461085e57806370a082311461087e578063718934d81461089e57600080fd5b806342144854116102a05780634f6ccce71161023e5780635e4507fa116102185780635e4507fa1461079f5780636352211e146107bf57806363dd7615146107df5780636c0360eb1461084957600080fd5b80634f6ccce71461073857806355f804b31461075857806357838e851461077857600080fd5b8063481c6a751161027a578063481c6a75146106a25780634d486f85146106c25780634eb780da146106e25780634f558e791461071857600080fd5b806342144854146105a55780634236aff8146105f357806342842e0e1461068257600080fd5b806317351f7e1161030d57806321e4f7bb116102e757806321e4f7bb1461050257806323b872dd14610530578063323e010714610550578063406f14ad1461058557600080fd5b806317351f7e1461048057806318160ddd146104b05780631de286ba146104d457600080fd5b8063095ea7b31161033e578063095ea7b31461040a5780630d1cfcae1461042c57806310c6aa191461046057600080fd5b806301ffc9a71461036557806306fdde031461039a578063081812fc146103bc575b600080fd5b34801561037157600080fd5b50610385610380366004614e43565b610c78565b60405190151581526020015b60405180910390f35b3480156103a657600080fd5b506103af610cca565b6040516103919190614ec3565b3480156103c857600080fd5b506103f26103d7366004614ed6565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610391565b34801561041657600080fd5b5061042a610425366004614f04565b610d58565b005b34801561043857600080fd5b506103f27f000000000000000000000000000000000000000000000000000000000000000081565b34801561046c57600080fd5b5061042a61047b366004614f30565b610e3f565b34801561048c57600080fd5b5061038561049b366004614f30565b60146020526000908152604090205460ff1681565b3480156104bc57600080fd5b506104c660095481565b604051908152602001610391565b3480156104e057600080fd5b506104f46104ef366004614ed6565b610ef8565b604051610391929190614f4d565b34801561050e57600080fd5b5061052261051d366004614fb4565b61114e565b60405161039192919061501a565b34801561053c57600080fd5b5061042a61054b36600461503b565b61123c565b34801561055c57600080fd5b5061057061056b366004614fb4565b611416565b60405163ffffffff9091168152602001610391565b34801561059157600080fd5b506105706105a0366004614fb4565b61145f565b3480156105b157600080fd5b506105db6105c0366004614ed6565b6010602052600090815260409020546001600160601b031681565b6040516001600160601b039091168152602001610391565b3480156105ff57600080fd5b5061066f61060e366004614ed6565b6015602052600090815260409020805460018201546002909201546001600160601b03821692600160601b928390046001600160a01b031692909163ffffffff808216926401000000008304821692600160401b8104909216910460ff1687565b60405161039197969594939291906150b4565b34801561068e57600080fd5b5061042a61069d36600461503b565b61147b565b3480156106ae57600080fd5b506007546103f2906001600160a01b031681565b3480156106ce57600080fd5b506105226106dd366004614ed6565b611570565b3480156106ee57600080fd5b506103f26106fd366004614f30565b6011602052600090815260409020546001600160a01b031681565b34801561072457600080fd5b50610385610733366004614ed6565b6116c2565b34801561074457600080fd5b506104c6610753366004614ed6565b6116e4565b34801561076457600080fd5b5061042a6107733660046151d7565b611729565b34801561078457600080fd5b50600b546103f290600160601b90046001600160a01b031681565b3480156107ab57600080fd5b506103f26107ba366004614fb4565b6117d2565b3480156107cb57600080fd5b506103f26107da366004614ed6565b61180a565b3480156107eb57600080fd5b506108256107fa366004614ed6565b600e6020526000908152604090205463ffffffff81169064010000000090046001600160601b031682565b6040805163ffffffff90931683526001600160601b03909116602083015201610391565b34801561085557600080fd5b506103af61186f565b34801561086a57600080fd5b50600b546105db906001600160601b031681565b34801561088a57600080fd5b506104c6610899366004614f30565b61187c565b3480156108aa57600080fd5b506108be6108b9366004614fb4565b6118f0565b604080516001600160a01b03909316835263ffffffff909116602083015201610391565b3480156108ee57600080fd5b506103856108fd3660046152cf565b611936565b34801561090e57600080fd5b506103af6040518060400160405280600981526020016806630313730313232360bc1b81525081565b34801561094357600080fd5b50610385610952366004615399565b611d8b565b34801561096357600080fd5b506104c6610972366004614fb4565b611e24565b34801561098357600080fd5b506104c6610992366004614f04565b60a01b6001600160a01b03909116176000908152601060205260409020546001600160601b031690565b3480156109c857600080fd5b506006546103f2906001600160a01b031681565b3480156109e857600080fd5b506109fc6109f73660046153d7565b611e55565b60405161039192919061542f565b348015610a1657600080fd5b506103af611f90565b348015610a2b57600080fd5b506104c6611f9d565b348015610a4057600080fd5b5061042a610a4f366004615399565b6120fb565b348015610a6057600080fd5b5061042a610a6f366004614f30565b612167565b348015610a8057600080fd5b50610a94610a8f366004614f04565b612218565b604080519215158352602083019190915201610391565b348015610ab757600080fd5b50610acb610ac6366004614ed6565b6126b4565b604051610391929190615448565b348015610ae557600080fd5b5061042a610af4366004614f30565b612718565b348015610b0557600080fd5b5061042a610b14366004615496565b6127c9565b348015610b2557600080fd5b506103af610b34366004614ed6565b6128ae565b348015610b4557600080fd5b50610385610b5436600461563a565b612928565b348015610b6557600080fd5b50610a94610b74366004614f04565b612eb6565b610385610b873660046156d7565b613246565b610385610b9a366004614f04565b613841565b348015610bab57600080fd5b50610385610bba366004615757565b600560209081526000928352604080842090915290825290205460ff1681565b348015610be657600080fd5b50610bfa610bf5366004614ed6565b6139c0565b6040516103919190615785565b348015610c1357600080fd5b506103f2610c22366004615821565b613b40565b348015610c3357600080fd5b506104c6610c42366004615895565b613fe6565b348015610c5357600080fd5b506103af604051806040016040528060058152602001640312e302e360dc1b81525081565b60006301ffc9a760e01b6001600160e01b031983161480610ca957506380ac58cd60e01b6001600160e01b03198316145b80610cc45750635b5e139f60e01b6001600160e01b03198316145b92915050565b60008054610cd79061592a565b80601f0160208091040260200160405190810160405280929190818152602001828054610d039061592a565b8015610d505780601f10610d2557610100808354040283529160200191610d50565b820191906000526020600020905b815481529060010190602001808311610d3357829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b031633811480610da157506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b610de35760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064015b60405180910390fd5b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6006546001600160a01b03163314610e7f5760065460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6001600160a01b038116610ea65760405163d92e233d60e01b815260040160405180910390fd5b600b80546001600160601b0316600160601b6001600160a01b038416908102919091179091556040517f8d1e8547016120917daad7f81c42b48f7fee379badc48f1889f0f43bb619472590600090a250565b600081815260156020908152604080832081516101008101835281546001600160601b03811682526001600160a01b03600160601b918290041694820194909452600182015492810192909252600281015463ffffffff808216606085810191909152640100000000830482166080860152600160401b830490911660a0850152938593929160c084019160ff9104166005811115610f9957610f9961507c565b6005811115610faa57610faa61507c565b81526020016003820180548060200260200160405190810160405280929190818152602001828054801561102957602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411610fec5790505b50505050508152505090508060e001515192508267ffffffffffffffff8111156110555761105561510f565b60405190808252806020026020018201604052801561109a57816020015b60408051808201909152600080825260208201528152602001906001900390816110735790505b50915060005b8381101561114757600085905060208360e0015183815181106110c5576110c5615964565b60209081029190910181015163ffffffff90811690921b929092176000818152600e845260409081902081518083019092525492831681526401000000009092046001600160601b031692820192909252845185908490811061112a5761112a615964565b6020026020010181905250508061114090615990565b90506110a0565b5050915091565b602081811b83176000818152600f909252604090912054906060908267ffffffffffffffff8111156111825761118261510f565b6040519080825280602002602001820160405280156111ab578160200160208202803683370190505b50915060005b83811015611233576000828152600f602052604090208054829081106111d9576111d9615964565b9060005260206000200160009054906101000a90046001600160a01b031683828151811061120957611209615964565b6001600160a01b03909216602092830291909101909101528061122b81615990565b9150506111b1565b50509250929050565b6000818152600260205260409020546001600160a01b038481169116146112a55760405162461bcd60e51b815260206004820152600a60248201527f57524f4e475f46524f4d000000000000000000000000000000000000000000006044820152606401610dda565b6001600160a01b0382166112ef5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610dda565b336001600160a01b038416148061132957506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b8061134a57506000818152600460205260409020546001600160a01b031633145b6113875760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610dda565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6012602052816000526040600020818154811061143257600080fd5b9060005260206000209060089182820401919006600402915091509054906101000a900463ffffffff1681565b6013602052816000526040600020818154811061143257600080fd5b61148683838361123c565b6001600160a01b0382163b1561156b57604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af11580156114fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152191906159a9565b6001600160e01b0319161461156b5760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610dda565b505050565b600081815260156020908152604080832081516101008101835281546001600160601b03811682526001600160a01b03600160601b918290041694820194909452600182015492810192909252600281015463ffffffff808216606085810191909152640100000000830482166080860152600160401b830490911660a0850152938593929160c084019160ff91041660058111156116115761161161507c565b60058111156116225761162261507c565b8152602001600382018054806020026020016040519081016040528092919081815260200182805480156116a157602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff16815260200190600401906020826003010492830192600103820291508084116116645790505b50505050508152505090506116b681856142de565b91508151925050915091565b60008082118015610cc457506009546116dc9060016159c6565b821092915050565b60006116f18260016159c6565b905060095481111561172457600954604051637ae5968560e01b8152610dda918391600401918252602082015260400190565b919050565b6006546001600160a01b031633146117695760065460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610dda565b805160000361178b57604051637c946ed760e01b815260040160405180910390fd5b60086117978282615a24565b507f5411e8ebf1636d9e83d5fc4900bf80cbac82e8790da2a4c94db4895e889eedf6816040516117c79190614ec3565b60405180910390a150565b600f60205281600052604060002081815481106117ee57600080fd5b6000918252602090912001546001600160a01b03169150829050565b6000818152600260205260409020546001600160a01b0316806117245760405162461bcd60e51b815260206004820152600a60248201527f4e4f545f4d494e544544000000000000000000000000000000000000000000006044820152606401610dda565b60088054610cd79061592a565b60006001600160a01b0382166118d45760405162461bcd60e51b815260206004820152600c60248201527f5a45524f5f4144445245535300000000000000000000000000000000000000006044820152606401610dda565b506001600160a01b031660009081526003602052604090205490565b600d602052816000526040600020818154811061190c57600080fd5b6000918252602090912001546001600160a01b0381169250600160a01b900463ffffffff16905082565b600081815260156020908152604080832081516101008101835281546001600160601b0381168252600160601b908190046001600160a01b031694820194909452600182015492810192909252600281015463ffffffff8082166060850152640100000000820481166080850152600160401b82041660a0840152849360c08401910460ff1660058111156119cd576119cd61507c565b60058111156119de576119de61507c565b815260200160038201805480602002602001604051908101604052809291908181526020018280548015611a5d57602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411611a205790505b505050505081525050905060046005811115611a7b57611a7b61507c565b8160c001516005811115611a9157611a9161507c565b14611ad0578060c001516005811115611aac57611aac61507c565b604051633c053f9d60e21b8152600481019190915260248101849052604401610dda565b8351855114611aff57845184516040516308151c1160e41b815260048101929092526024820152604401610dda565b80602001516001600160a01b0316336001600160a01b031614611b535760208101516040516379f91cd360e01b81523360048201526001600160a01b03909116602482015260448101849052606401610dda565b845160005b81811015611d7e57600060116000898481518110611b7857611b78615964565b6020908102919091018101516001600160a01b03908116835282820193909352604091820160009081205490931660a08a901b81178085526010909252919092205489519193506001600160601b03169081908a9086908110611bdd57611bdd615964565b60200260200101516001611bf19190615ae4565b6001600160601b03161115611c4b57600b8054829190600090611c1e9084906001600160601b0316615ae4565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555060009050611ccf565b888481518110611c5d57611c5d615964565b6020908102919091010151600b8054600090611c839084906001600160601b0316615ae4565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550888481518110611cb957611cb9615964565b602002602001015181611ccc9190615b0f565b90505b600082815260106020526040902080546bffffffffffffffffffffffff19166001600160601b038316179055885188906001600160a01b038516907fa2e524bd0f71903485fbb3d6d50cb305f61005ceea2047c3ac92aa7e0d104306908c9088908110611d3e57611d3e615964565b6020026020010151604051611d6291906001600160601b0391909116815260200190565b60405180910390a350505080611d7790615990565b9050611b58565b5060019695505050505050565b6006546000906001600160a01b03163314611dce5760065460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6001600160a01b038316611df55760405163d92e233d60e01b815260040160405180910390fd5b506001600160a01b03919091166000908152601460205260409020805460ff1916911515919091179055600190565b600c6020528160005260406000208181548110611e4057600080fd5b90600052602060002001600091509150505481565b6000606081846001811115611e6c57611e6c61507c565b03611efd5760008381526012602090815260409182902080548351818402810184019094528084529091830182828015611ef157602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411611eb45790505b50505050509050611f85565b60008381526013602090815260409182902080548351818402810184019094528084529091830182828015611f7d57602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411611f405790505b505050505090505b805191509250929050565b60018054610cd79061592a565b60006001600a541115611fc3576040516345f5ce8b60e11b815260040160405180910390fd5b6002600a55600b54600160601b90046001600160a01b0316331461201557600b5460405163312d21ff60e11b8152336004820152600160601b9091046001600160a01b03166024820152604401610dda565b50600b546001600160601b031680156120f357600b80546bffffffffffffffffffffffff19169055604051600090339083908381818185875af1925050503d806000811461207f576040519150601f19603f3d011682016040523d82523d6000602084013e612084565b606091505b50509050806120bc5760405163cd3f165960e01b81526000600482015230602482015233604482015260648101839052608401610dda565b60405182815233907ff36f4d6622e16a536bbb049064af779cdd483a0b388d347d3752a65f1058bf5b9060200160405180910390a2505b6001600a5590565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6006546001600160a01b031633146121a75760065460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6001600160a01b0381166121ce5760405163d92e233d60e01b815260040160405180910390fd5b600780546001600160a01b0319166001600160a01b0383169081179091556040517f2c1c11af44aa5608f1dca38c00275c30ea091e02417d36e70e9a1538689c433d90600090a250565b6000806001600a54111561223f576040516345f5ce8b60e11b815260040160405180910390fd5b6002600a556007546001600160a01b031633146122845760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6001600160a01b0384166122ab5760405163d92e233d60e01b815260040160405180910390fd5b600083815260156020526040902060056002820154600160601b900460ff1660058111156122db576122db61507c565b14612324576002810154600160601b900460ff1660058111156123005761230061507c565b604051633c053f9d60e21b8152600481019190915260248101859052604401610dda565b60a084901b6001600160a01b038616176000818152600d6020908152604080832080548251818502810185019093528083529192909190849084015b828210156123ac57600084815260209081902060408051808201909152908401546001600160a01b0381168252600160a01b900463ffffffff1681830152825260019092019101612360565b50508251929350505060008190036123e95760405163df2ddd7360e01b81526001600160a01b038916600482015260248101889052604401610dda565b808460020160088282829054906101000a900463ffffffff1661240c9190615b37565b92506101000a81548163ffffffff021916908363ffffffff1602179055508360020160089054906101000a900463ffffffff1663ffffffff166000036124625760028401805460ff60601b1916600160601b1790555b60005b8181101561252a576000889050602084838151811061248657612486615964565b60209081029190910181015181015163ffffffff1690911b919091176000818152600e9092526040909120546124cd9064010000000090046001600160601b0316886159c6565b9650601160008584815181106124e5576124e5615964565b602090810291909101810151516001600160a01b0316825281019190915260400160002080546001600160a01b0319169055508061252281615990565b915050612465565b506000838152600d6020526040812061254291614c87565b6000838152601060205260409020546001600160601b03168086111561256f57806001600160601b031695505b85156126685760008481526010602052604080822080546bffffffffffffffffffffffff19169055516001600160a01b038b169088908381818185875af1925050503d80600081146125dd576040519150601f19603f3d011682016040523d82523d6000602084013e6125e2565b606091505b50509050806126235760405163cd3f165960e01b8152600060048201523060248201526001600160a01b038b16604482015260648101889052608401610dda565b896001600160a01b03167fbb28353e4598c3b9199101a66e0989549b659a59a54d2c27fbb183f1932c8e6d8860405161265e91815260200190565b60405180910390a2505b60405188906001600160a01b038b16907f5ebf7fe30be09f0f03b9195632508d95c8b67bf010c93abda67f70d5d9599d1e90600090a350506001600a8190559793965092945050505050565b6000818152600c60209081526040808320805482518185028101850190935280835260609383018282801561270857602002820191906000526020600020905b8154815260200190600101908083116126f4575b5050505050905080519150915091565b6006546001600160a01b031633146127585760065460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6001600160a01b03811661277f5760405163d92e233d60e01b815260040160405180910390fd5b600680546001600160a01b0319166001600160a01b0383169081179091556040517f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b90600090a250565b6127d485858561123c565b6001600160a01b0384163b156128a757604051630a85bd0160e11b808252906001600160a01b0386169063150b7a029061281a9033908a90899089908990600401615b54565b6020604051808303816000875af1158015612839573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061285d91906159a9565b6001600160e01b031916146128a75760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610dda565b5050505050565b6000818152601560205260408120600101546060915060086040518060400160405280600981526020016806630313730313232360bc1b8152506128f18361442f565b6128fe608085901b61442f565b6040516020016129119493929190615ba8565b604051602081830303815290604052915050919050565b6007546000906001600160a01b0316331461296b5760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b60006129768361180a565b9050876001600160a01b0316816001600160a01b0316146129bd5760405163521eb56d60e11b81526001600160a01b03808a16600483015282166024820152604401610dda565b600083815260156020908152604080832081516101008101835281546001600160601b03811682526001600160a01b03600160601b918290041694820194909452600182015492810192909252600281015463ffffffff8082166060850152640100000000820481166080850152600160401b82041660a08401529192909160c084019160ff9104166005811115612a5757612a5761507c565b6005811115612a6857612a6861507c565b815260200160038201805480602002602001604051908101604052809291908181526020018280548015612ae757602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411612aaa5790505b505050505081525050905060016005811115612b0557612b0561507c565b8160c001516005811115612b1b57612b1b61507c565b14612b36578060c0015160058111156123005761230061507c565b612b418888886145ff565b63ffffffff85166060820152600060808201819052875167ffffffffffffffff811115612b7057612b7061510f565b604051908082528060200260200182016040528015612b99578160200160208202803683370190505b5090506000885167ffffffffffffffff811115612bb857612bb861510f565b604051908082528060200260200182016040528015612bfd57816020015b6040805180820190915260008082526020820152815260200190600190039081612bd65790505b5090506000805b8a51811015612d3257898181518110612c1f57612c1f615964565b60200260200101516000015163ffffffff16600003612c9457600088905060208c8381518110612c5157612c51615964565b60209081029190910181015163ffffffff1690911b919091176000908152600e9091526040902080546fffffffffffffffffffffffffffffffff19169055612d20565b8a8181518110612ca657612ca6615964565b6020026020010151848381518110612cc057612cc0615964565b602002602001019063ffffffff16908163ffffffff1681525050898181518110612cec57612cec615964565b6020026020010151838381518110612d0657612d06615964565b60200260200101819052508180612d1c90615990565b9250505b80612d2a81615990565b915050612c04565b5060408401518b8114612d69576000888152600c602090815260408083208054600181018255908452919092200182905585018c90525b612d76858585858c6147c6565b6000888152601560209081526040918290208751918801516001600160a01b0316600160601b9081026001600160601b03909316929092178155918701516001830155606087015160028301805460808a015160a08b015163ffffffff908116600160401b026bffffffff0000000000000000199282166401000000000267ffffffffffffffff199094169190951617919091179081168317825560c08a01518a9594909360ff60601b19166cffffffffff0000000000000000199092169190911790836005811115612e4b57612e4b61507c565b021790555060e08201518051612e6b916003840191602090910190614ca8565b50506040518d81528991507fff312ce131c4d73ac90ece91266be7090486c5e15f78b7ea2b108c36dfd475299060200160405180910390a25060019c9b505050505050505050505050565b6000806001600a541115612edd576040516345f5ce8b60e11b815260040160405180910390fd5b6002600a556007546001600160a01b03163314612f225760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6000612f2d8461180a565b9050846001600160a01b0316816001600160a01b031614612f745760405163521eb56d60e11b81526001600160a01b03808716600483015282166024820152604401610dda565b600084815260156020526040902060016002820154600160601b900460ff166005811115612fa457612fa461507c565b1480612fcf575060056002820154600160601b900460ff166005811115612fcd57612fcd61507c565b145b15613018576002810154600160601b900460ff166005811115612ff457612ff461507c565b604051633c053f9d60e21b8152600481019190915260248101869052604401610dda565b6002810154600160401b900463ffffffff16156130525760028101805460ff60601b19166c05000000000000000000000000179055613068565b60028101805460ff60601b1916600160601b1790555b600085815260126020526040812061307f91614d57565b600085815260136020526040812061309691614d57565b60005b600382015481101561312357600086905060208360030183815481106130c1576130c1615964565b90600052602060002090600891828204019190066004029054906101000a900463ffffffff1663ffffffff16901b81179050600f600082815260200190815260200160002060006131129190614d7c565b5061311c81615990565b9050613099565b5080546040516001600160601b0390911693506000906001600160a01b0388169085908381818185875af1925050503d806000811461317e576040519150601f19603f3d011682016040523d82523d6000602084013e613183565b606091505b50509050806131c45760405163cd3f165960e01b8152600060048201523060248201526001600160a01b038816604482015260648101859052608401610dda565b866001600160a01b03167fbb28353e4598c3b9199101a66e0989549b659a59a54d2c27fbb183f1932c8e6d856040516131ff91815260200190565b60405180910390a260405186907fe45f5b9540df4f71b7e044809fa318806328c1ea2388a70c7373d97ccf8a0faa90600090a250506001600a819055959194509092505050565b6007546000906001600160a01b031633146132895760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b81518351146132b857825182516040516308151c1160e41b815260048101929092526024820152604401610dda565b6000848152601560205260409020600280820154600160601b900460ff1660058111156132e7576132e761507c565b1461330c576002810154600160601b900460ff166005811115612ff457612ff461507c565b83516000805b82811015613401576000889050602087838151811061333357613333615964565b60209081029190910181015163ffffffff90811690921b929092176000818152600e845260408082208151808301909252549384168082526401000000009094046001600160601b03169481019490945290929190036133d45787838151811061339f5761339f615964565b60200260200101518a6040516332832be560e21b8152600401610dda92919063ffffffff929092168252602082015260400190565b60208101516133ec906001600160601b0316856159c6565b93505050806133fa90615990565b9050613312565b5080341461343257604051637ebbcab960e11b81523460048201526024810182905260448101889052606401610dda565b6001600160a01b03888116600090815260116020526040902054161561346e576040516322ddebd960e21b815260048101889052602401610dda565b60a087901b6001600160a01b0389161760005b8381101561376257600088828151811061349d5761349d615964565b6020026020010151905060008883815181106134bb576134bb615964565b60200260200101519050816001600160a01b03168c6001600160a01b0316036134fa576040516322ddebd960e21b8152600481018c9052602401610dda565b6001600160a01b038281166000908152601160205260409020541615613551576001600160a01b038281166000908152601160205260409081902054905163631695bd60e01b815291166004820152602401610dda565b60008b905060208a858151811061356a5761356a615964565b60209081029190910181015163ffffffff90811690921b929092176000818152600e8452604080822054600f909552902054909290911690036135c3576040516304ad100760e21b8152600481018d9052602401610dda565b6000818152600f602090815260408083208054600181810183559185528385200180546001600160a01b03808a166001600160a01b031990921682179092558a8652600d8552838620845180860190955290845263ffffffff8089168587019081528254948501835591875294909520925192909101805494518416600160a01b0277ffffffffffffffffffffffffffffffffffffffffffffffff19909516929091169190911792909217909155600289018054600160401b900490911690600861368d83615c3a565b91906101000a81548163ffffffff021916908363ffffffff160217905550508c60116000856001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550826001600160a01b03168c8e6001600160a01b03167f6835389a6da5341647f18cbe0a89c56f473f4c17bfaee6e6d07d61f1928e0b7c85604051613746919063ffffffff91909116815260200190565b60405180910390a45050508061375b90615990565b9050613481565b50600284015463ffffffff64010000000082048116600160401b90920416036137a45760028401805460ff60601b19166c030000000000000000000000001790555b600081815260106020526040812080543492906137cb9084906001600160601b0316615ae4565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550886001600160a01b03167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c3460405161382a91815260200190565b60405180910390a250600198975050505050505050565b6007546000906001600160a01b031633146138845760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b600061388f8361180a565b9050836001600160a01b0316816001600160a01b0316146138d65760405163521eb56d60e11b81526001600160a01b03808616600483015282166024820152604401610dda565b600083815260156020526040902060016002820154600160601b900460ff1660058111156139065761390661507c565b1461392757604051635960d22f60e11b815260048101859052602401610dda565b80546001600160601b0316341461396c578054604051631c30abbb60e31b81523460048201526001600160601b03909116602482015260448101859052606401610dda565b60028101805460ff60601b19166c0200000000000000000000000017905560405184907fa48b531f972c0e4aca57afcc5c099c52a7bd21bc5e2a1b733eec3be9e88da97a90600090a2506001949350505050565b613a086040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a081018290529060c08201908152602001606081525090565b60008281526015602090815260409182902082516101008101845281546001600160601b0381168252600160601b908190046001600160a01b031693820193909352600182015493810193909352600281015463ffffffff8082166060860152640100000000820481166080860152600160401b82041660a0850152909160c08401910460ff166005811115613aa057613aa061507c565b6005811115613ab157613ab161507c565b815260200160038201805480602002602001604051908101604052809291908181526020018280548015613b3057602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411613af35790505b5050505050815250509050919050565b60006001600a541115613b66576040516345f5ce8b60e11b815260040160405180910390fd5b6002600a556007546001600160a01b03163314613bab5760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6000613bb68561180a565b9050856001600160a01b0316816001600160a01b031614613bfd5760405163521eb56d60e11b81526001600160a01b03808816600483015282166024820152604401610dda565b6001600160a01b03841660009081526014602052604090205460ff16613c405760405162a2307960e51b81526001600160a01b0385166004820152602401610dda565b600085815260156020526040902060036002820154600160601b900460ff166005811115613c7057613c7061507c565b14613cb9576002810154600160601b900460ff166005811115613c9557613c9561507c565b604051633c053f9d60e21b8152600481019190915260248101879052604401610dda565b604080516101008101825282546001600160601b0381168252600160601b908190046001600160a01b03166020830152600184015492820192909252600283015463ffffffff8082166060840152640100000000820481166080840152600160401b82041660a0830152600092613de69291859160c08401910460ff166005811115613d4757613d4761507c565b6005811115613d5857613d5861507c565b815260200160038201805480602002602001604051908101604052809291908181526020018280548015613dd757602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411613d9a5790505b505050505081525050886142de565b6002830154604051631e731b7560e31b81529192506001600160a01b0388169163f398dba891613e2391859163ffffffff16908a90600401615c5d565b6020604051808303816000875af1158015613e42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e669190615c98565b6000888152601360205260409020600384018054929650613e8692614d9a565b506040516304d9dc3f60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906309b3b87e90613ed6906003860190600401615cb5565b600060405180830381865afa158015613ef3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613f1b9190810190615e3d565b60008881526012602090815260409091208251613f3e9391929190910190614ca8565b5081546001600160601b0316600160601b6001600160a01b03861690810291909117835560028301805460ff60601b19166c0400000000000000000000000017905560405188907f2d53f895cd5faf3cddba94a25c2ced2105885b5b37450ff430ffa3cbdf332c7490600090a360405187907fa133ed72c03a7d008deaae618a61613c4fd41c67bba1cad1a6bc0a1c5a9c156e90600090a250506001600a5550949350505050565b60006001600a54111561400c576040516345f5ce8b60e11b815260040160405180910390fd5b6002600a556007546001600160a01b031633146140515760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6001600160a01b0386166140785760405163d92e233d60e01b815260040160405180910390fd5b6140838585856145ff565b60005b8451811015614117578381815181106140a1576140a1615964565b60200260200101516000015163ffffffff16600014806140e757508381815181106140ce576140ce615964565b6020026020010151602001516001600160601b03166000145b1561410557604051637c946ed760e01b815260040160405180910390fd5b8061410f81615990565b915050614086565b50506009548061412681615990565b9150506141716040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a081018290529060c08201908152602001606081525090565b63ffffffff8316606082015260408101869052600160c08201818152505061419d8186868851866147c6565b6000828152601560209081526040918290208351918401516001600160a01b0316600160601b9081026001600160601b039093169290921781559183015160018301556060830151600283018054608086015160a087015163ffffffff908116600160401b026bffffffff0000000000000000199282166401000000000267ffffffffffffffff199094169190951617919091179081168317825560c0860151869594909360ff60601b19166cffffffffff00000000000000001990921691909117908360058111156142725761427261507c565b021790555060e08201518051614292916003840191602090910190614ca8565b50505060098290556142a48783614a7d565b60405182907f9169d45eacd63571e315a0504da919b7c89de505493e7b34051802dd0816a06990600090a2506001600a5595945050505050565b60608260a0015163ffffffff1667ffffffffffffffff8111156143035761430361510f565b60405190808252806020026020018201604052801561432c578160200160208202803683370190505b5090506000805b8460e001515181101561442757600084905060208660e00151838151811061435d5761435d615964565b602002602001015163ffffffff16901b8117905060005b6000828152600f6020526040902054811015614412576000828152600f602052604090208054829081106143aa576143aa615964565b9060005260206000200160009054906101000a90046001600160a01b03168585815181106143da576143da615964565b6001600160a01b0390921660209283029190910190910152836143fc81615990565b945050808061440a90615990565b915050614374565b5050808061441f90615990565b915050614333565b505092915050565b7aff00000000000000ff00000000000000ff00000000000000ff00006bffffffff0000000000000000604083901c9081167bffffffff00000000000000000000000000000000000000000000000084161760201c6fffffffff000000000000000000000000919091166001600160e01b031984161717601081901c9182167eff00000000000000ff00000000000000ff00000000000000ff000000000000821617600890811c7bff00000000000000ff00000000000000ff00000000000000ff000000939093167fff00000000000000ff00000000000000ff00000000000000ff000000000000009290921691909117919091179081901c7e0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f167f0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00600492831c16179061459b827f06060606060606060606060606060606060606060606060606060606060606066159c6565b901c7f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f1660276145cb9190615ed7565b6145f5827f30303030303030303030303030303030303030303030303030303030303030306159c6565b610cc491906159c6565b600083900361462157604051637c946ed760e01b815260040160405180910390fd5b8151158061463157508051825114155b1561465c57815181516040516308151c1160e41b815260048101929092526024820152604401610dda565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156146bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146e09190615ef6565b90506000805b84518110156147be576146fa8260016159c6565b85828151811061470c5761470c615964565b602002602001015163ffffffff16108061474457508285828151811061473457614734615964565b602002602001015163ffffffff16115b156147895784818151811061475b5761475b615964565b6020026020010151604051632ab10b0b60e21b8152600401610dda919063ffffffff91909116815260200190565b84818151811061479b5761479b615964565b602002602001015163ffffffff16915080806147b690615990565b9150506146e6565b505050505050565b60008267ffffffffffffffff8111156147e1576147e161510f565b60405190808252806020026020018201604052801561480a578160200160208202803683370190505b5060e087015260005b8381101561499a5785818151811061482d5761482d615964565b60200260200101518760e00151828151811061484b5761484b615964565b63ffffffff909216602092830291909101820152865184919088908490811061487657614876615964565b602002602001015163ffffffff16901b8117905085828151811061489c5761489c615964565b6020908102919091018101516000838152600e8352604090208151815492909301516001600160601b0316640100000000026fffffffffffffffffffffffffffffffff1990921663ffffffff90931692909217179055855186908390811061490657614906615964565b602002602001015160000151886080018181516149239190615f0f565b63ffffffff1690525085516001600160601b0384169087908490811061494b5761494b615964565b6020026020010151602001516001600160601b031611156149875785828151811061497857614978615964565b60200260200101516020015192505b508061499281615990565b915050614813565b506001600160601b038116865260808601516000906149ba906002615f2e565b6149c5906001615f0f565b63ffffffff1690506149d8600382615f70565b6000036149f1576149ea600382615f84565b9050614a0a565b6149fc600382615f84565b614a079060016159c6565b90505b80876060015163ffffffff161080614a355750866080015163ffffffff16876060015163ffffffff16115b15614a74576060870151608088015160405163eb3a8ba360e01b815263ffffffff92831660048201526024810184905291166044820152606401610dda565b50505050505050565b614a878282614b6d565b6001600160a01b0382163b15614b6957604051630a85bd0160e11b80825233600483015260006024830181905260448301849052608060648401526084830152906001600160a01b0384169063150b7a029060a4016020604051808303816000875af1158015614afb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b1f91906159a9565b6001600160e01b03191614614b695760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610dda565b5050565b6001600160a01b038216614bb75760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610dda565b6000818152600260205260409020546001600160a01b031615614c1c5760405162461bcd60e51b815260206004820152600e60248201527f414c52454144595f4d494e5445440000000000000000000000000000000000006044820152606401610dda565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b5080546000825590600052602060002090810190614ca59190614de8565b50565b82805482825590600052602060002090600701600890048101928215614d475791602002820160005b83821115614d1557835183826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302614cd1565b8015614d455782816101000a81549063ffffffff0219169055600401602081600301049283019260010302614d15565b505b50614d53929150614e18565b5090565b508054600082556007016008900490600052602060002090810190614ca59190614e18565b5080546000825590600052602060002090810190614ca59190614e18565b82805482825590600052602060002090600701600890048101928215614d47576000526020600020916007016008900482015b82811115614d47578254825591600101919060010190614dcd565b5b80821115614d5357805477ffffffffffffffffffffffffffffffffffffffffffffffff19168155600101614de9565b5b80821115614d535760008155600101614e19565b6001600160e01b031981168114614ca557600080fd5b600060208284031215614e5557600080fd5b8135614e6081614e2d565b9392505050565b60005b83811015614e82578181015183820152602001614e6a565b83811115614e91576000848401525b50505050565b60008151808452614eaf816020860160208601614e67565b601f01601f19169290920160200192915050565b602081526000614e606020830184614e97565b600060208284031215614ee857600080fd5b5035919050565b6001600160a01b0381168114614ca557600080fd5b60008060408385031215614f1757600080fd5b8235614f2281614eef565b946020939093013593505050565b600060208284031215614f4257600080fd5b8135614e6081614eef565b6000604080830185845260208281860152818651808452606087019150828801935060005b81811015614fa6578451805163ffffffff1684528401516001600160601b0316848401529383019391850191600101614f72565b509098975050505050505050565b60008060408385031215614fc757600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b8381101561500f5781516001600160a01b031687529582019590820190600101614fea565b509495945050505050565b8281526040602082015260006150336040830184614fd6565b949350505050565b60008060006060848603121561505057600080fd5b833561505b81614eef565b9250602084013561506b81614eef565b929592945050506040919091013590565b634e487b7160e01b600052602160045260246000fd5b600681106150b057634e487b7160e01b600052602160045260246000fd5b9052565b6001600160601b03881681526001600160a01b03871660208201526040810186905263ffffffff85811660608301528481166080830152831660a082015260e0810161510360c0830184615092565b98975050505050505050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156151485761514861510f565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156151775761517761510f565b604052919050565b600067ffffffffffffffff8311156151995761519961510f565b6151ac601f8401601f191660200161514e565b90508281528383830111156151c057600080fd5b828260208301376000602084830101529392505050565b6000602082840312156151e957600080fd5b813567ffffffffffffffff81111561520057600080fd5b8201601f8101841361521157600080fd5b6150338482356020840161517f565b600067ffffffffffffffff82111561523a5761523a61510f565b5060051b60200190565b600082601f83011261525557600080fd5b8135602061526a61526583615220565b61514e565b82815260059290921b8401810191818101908684111561528957600080fd5b8286015b848110156152ad5780356152a081614eef565b835291830191830161528d565b509695505050505050565b80356001600160601b038116811461172457600080fd5b6000806000606084860312156152e457600080fd5b833567ffffffffffffffff808211156152fc57600080fd5b61530887838801615244565b945060209150818601358181111561531f57600080fd5b86019050601f8101871361533257600080fd5b803561534061526582615220565b81815260059190911b8201830190838101908983111561535f57600080fd5b928401925b8284101561538457615375846152b8565b82529284019290840190615364565b96999698505050506040949094013593505050565b600080604083850312156153ac57600080fd5b82356153b781614eef565b9150602083013580151581146153cc57600080fd5b809150509250929050565b600080604083850312156153ea57600080fd5b823560028110614f2257600080fd5b600081518084526020808501945080840160005b8381101561500f57815163ffffffff168752958201959082019060010161540d565b82815260406020820152600061503360408301846153f9565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156154895784518352938301939183019160010161546d565b5090979650505050505050565b6000806000806000608086880312156154ae57600080fd5b85356154b981614eef565b945060208601356154c981614eef565b935060408601359250606086013567ffffffffffffffff808211156154ed57600080fd5b818801915088601f83011261550157600080fd5b81358181111561551057600080fd5b89602082850101111561552257600080fd5b9699959850939650602001949392505050565b63ffffffff81168114614ca557600080fd5b600082601f83011261555857600080fd5b8135602061556861526583615220565b82815260059290921b8401810191818101908684111561558757600080fd5b8286015b848110156152ad57803561559e81615535565b835291830191830161558b565b600082601f8301126155bc57600080fd5b813560206155cc61526583615220565b82815260069290921b840181019181810190868411156155eb57600080fd5b8286015b848110156152ad57604081890312156156085760008081fd5b615610615125565b813561561b81615535565b81526156288286016152b8565b818601528352918301916040016155ef565b60008060008060008060c0878903121561565357600080fd5b863561565e81614eef565b955060208701359450604087013567ffffffffffffffff8082111561568257600080fd5b61568e8a838b01615547565b955060608901359150808211156156a457600080fd5b506156b189828a016155ab565b93505060808701356156c281615535565b8092505060a087013590509295509295509295565b600080600080608085870312156156ed57600080fd5b84356156f881614eef565b935060208501359250604085013567ffffffffffffffff8082111561571c57600080fd5b61572888838901615244565b9350606087013591508082111561573e57600080fd5b5061574b87828801615547565b91505092959194509250565b6000806040838503121561576a57600080fd5b823561577581614eef565b915060208301356153cc81614eef565b602081526001600160601b0382511660208201526001600160a01b03602083015116604082015260408201516060820152600060608301516157cf608084018263ffffffff169052565b50608083015163ffffffff811660a08401525060a083015163ffffffff811660c08401525060c083015161580660e0840182615092565b5060e0830151610100838101526150336101208401826153f9565b6000806000806080858703121561583757600080fd5b843561584281614eef565b935060208501359250604085013561585981614eef565b9150606085013567ffffffffffffffff81111561587557600080fd5b8501601f8101871361588657600080fd5b61574b8782356020840161517f565b600080600080600060a086880312156158ad57600080fd5b85356158b881614eef565b945060208601359350604086013567ffffffffffffffff808211156158dc57600080fd5b6158e889838a01615547565b945060608801359150808211156158fe57600080fd5b5061590b888289016155ab565b925050608086013561591c81615535565b809150509295509295909350565b600181811c9082168061593e57607f821691505b60208210810361595e57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016159a2576159a261597a565b5060010190565b6000602082840312156159bb57600080fd5b8151614e6081614e2d565b600082198211156159d9576159d961597a565b500190565b601f82111561156b57600081815260208120601f850160051c81016020861015615a055750805b601f850160051c820191505b818110156147be57828155600101615a11565b815167ffffffffffffffff811115615a3e57615a3e61510f565b615a5281615a4c845461592a565b846159de565b602080601f831160018114615a875760008415615a6f5750858301515b600019600386901b1c1916600185901b1785556147be565b600085815260208120601f198616915b82811015615ab657888601518255948401946001909101908401615a97565b5085821015615ad45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006001600160601b03808316818516808303821115615b0657615b0661597a565b01949350505050565b60006001600160601b0383811690831681811015615b2f57615b2f61597a565b039392505050565b600063ffffffff83811690831681811015615b2f57615b2f61597a565b60006001600160a01b03808816835280871660208401525084604083015260806060830152826080830152828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b6000808654615bb68161592a565b60018281168015615bce5760018114615be357615c12565b60ff1984168752821515830287019450615c12565b8a60005260208060002060005b85811015615c095781548a820152908401908201615bf0565b50505082870194505b505050508551615c26818360208a01614e67565b019384525050602082015260400192915050565b600063ffffffff808316818103615c5357615c5361597a565b6001019392505050565b606081526000615c706060830186614fd6565b63ffffffff851660208401528281036040840152615c8e8185614e97565b9695505050505050565b600060208284031215615caa57600080fd5b8151614e6081614eef565b60006020808301818452808554615cd0818490815260200190565b60008881526020812094509092505b81600782011015615d5557835463ffffffff808216855281871c811687860152604082811c821690860152606082811c821690860152608082811c82169086015260a082811c82169086015260c082811c9091169085015260e090811c9084015260019093019261010090920191600801615cdf565b92549281811015615d715763ffffffff84168352918401916001015b81811015615d8c5783851c63ffffffff168352918401916001015b81811015615da957604084901c63ffffffff168352918401916001015b81811015615dc657606084901c63ffffffff168352918401916001015b81811015615de357608084901c63ffffffff168352918401916001015b81811015615e005760a084901c63ffffffff168352918401916001015b81811015615e1d5760c084901c63ffffffff168352918401916001015b81811015615e315760e084901c8352918401915b50909695505050505050565b60006020808385031215615e5057600080fd5b825167ffffffffffffffff811115615e6757600080fd5b8301601f81018513615e7857600080fd5b8051615e8661526582615220565b81815260059190911b82018301908381019087831115615ea557600080fd5b928401925b82841015615ecc578351615ebd81615535565b82529284019290840190615eaa565b979650505050505050565b6000816000190483118215151615615ef157615ef161597a565b500290565b600060208284031215615f0857600080fd5b5051919050565b600063ffffffff808316818516808303821115615b0657615b0661597a565b600063ffffffff80831681851681830481118215151615615f5157615f5161597a565b02949350505050565b634e487b7160e01b600052601260045260246000fd5b600082615f7f57615f7f615f5a565b500690565b600082615f9357615f93615f5a565b50049056fea2646970667358221220c6f47c49865f99357fc7f3a83dfde648490b39975e4ec4242e3bcab08caabf3664736f6c634300080f0033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000002f1f7d38e4772884b88f3ecd8b6b9facdc3191120000000000000000000000000000000000000000000000000000000000000010536572766963652052656769737472790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000144155544f4e4f4c41532d534552564943452d5631000000000000000000000000000000000000000000000000000000000000000000000000000000000000002468747470733a2f2f676174657761792e6175746f6e6f6c61732e746563682f697066732f00000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106103605760003560e01c80636f99f15c116101c6578063a5d059ca116100f7578063dff7672411610095578063ef0e239b1161006f578063ef0e239b14610bda578063f908bc7714610c07578063fbdeb3d714610c27578063ffa1ad7414610c4757600080fd5b8063dff7672414610b79578063e23f6fb414610b8c578063e985e9c514610b9f57600080fd5b8063b88d4fde116100d1578063b88d4fde14610af9578063c87b56dd14610b19578063cbf994f814610b39578063ccc9305d14610b5957600080fd5b8063a5d059ca14610a74578063a60e4c3c14610aab578063a6f9dae114610ad957600080fd5b80638a2bd86f1161016457806395d89b411161013e57806395d89b4114610a0a5780639890220b14610a1f578063a22cb46514610a34578063a3fbbaae14610a5457600080fd5b80638a2bd86f146109775780638da5cb5b146109bc57806392080b23146109dc57600080fd5b806373b8b6a2116101a057806373b8b6a2146108e25780637c5e63e01461090257806382694b1d1461093757806386a2bdd41461095757600080fd5b80636f99f15c1461085e57806370a082311461087e578063718934d81461089e57600080fd5b806342144854116102a05780634f6ccce71161023e5780635e4507fa116102185780635e4507fa1461079f5780636352211e146107bf57806363dd7615146107df5780636c0360eb1461084957600080fd5b80634f6ccce71461073857806355f804b31461075857806357838e851461077857600080fd5b8063481c6a751161027a578063481c6a75146106a25780634d486f85146106c25780634eb780da146106e25780634f558e791461071857600080fd5b806342144854146105a55780634236aff8146105f357806342842e0e1461068257600080fd5b806317351f7e1161030d57806321e4f7bb116102e757806321e4f7bb1461050257806323b872dd14610530578063323e010714610550578063406f14ad1461058557600080fd5b806317351f7e1461048057806318160ddd146104b05780631de286ba146104d457600080fd5b8063095ea7b31161033e578063095ea7b31461040a5780630d1cfcae1461042c57806310c6aa191461046057600080fd5b806301ffc9a71461036557806306fdde031461039a578063081812fc146103bc575b600080fd5b34801561037157600080fd5b50610385610380366004614e43565b610c78565b60405190151581526020015b60405180910390f35b3480156103a657600080fd5b506103af610cca565b6040516103919190614ec3565b3480156103c857600080fd5b506103f26103d7366004614ed6565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610391565b34801561041657600080fd5b5061042a610425366004614f04565b610d58565b005b34801561043857600080fd5b506103f27f0000000000000000000000002f1f7d38e4772884b88f3ecd8b6b9facdc31911281565b34801561046c57600080fd5b5061042a61047b366004614f30565b610e3f565b34801561048c57600080fd5b5061038561049b366004614f30565b60146020526000908152604090205460ff1681565b3480156104bc57600080fd5b506104c660095481565b604051908152602001610391565b3480156104e057600080fd5b506104f46104ef366004614ed6565b610ef8565b604051610391929190614f4d565b34801561050e57600080fd5b5061052261051d366004614fb4565b61114e565b60405161039192919061501a565b34801561053c57600080fd5b5061042a61054b36600461503b565b61123c565b34801561055c57600080fd5b5061057061056b366004614fb4565b611416565b60405163ffffffff9091168152602001610391565b34801561059157600080fd5b506105706105a0366004614fb4565b61145f565b3480156105b157600080fd5b506105db6105c0366004614ed6565b6010602052600090815260409020546001600160601b031681565b6040516001600160601b039091168152602001610391565b3480156105ff57600080fd5b5061066f61060e366004614ed6565b6015602052600090815260409020805460018201546002909201546001600160601b03821692600160601b928390046001600160a01b031692909163ffffffff808216926401000000008304821692600160401b8104909216910460ff1687565b60405161039197969594939291906150b4565b34801561068e57600080fd5b5061042a61069d36600461503b565b61147b565b3480156106ae57600080fd5b506007546103f2906001600160a01b031681565b3480156106ce57600080fd5b506105226106dd366004614ed6565b611570565b3480156106ee57600080fd5b506103f26106fd366004614f30565b6011602052600090815260409020546001600160a01b031681565b34801561072457600080fd5b50610385610733366004614ed6565b6116c2565b34801561074457600080fd5b506104c6610753366004614ed6565b6116e4565b34801561076457600080fd5b5061042a6107733660046151d7565b611729565b34801561078457600080fd5b50600b546103f290600160601b90046001600160a01b031681565b3480156107ab57600080fd5b506103f26107ba366004614fb4565b6117d2565b3480156107cb57600080fd5b506103f26107da366004614ed6565b61180a565b3480156107eb57600080fd5b506108256107fa366004614ed6565b600e6020526000908152604090205463ffffffff81169064010000000090046001600160601b031682565b6040805163ffffffff90931683526001600160601b03909116602083015201610391565b34801561085557600080fd5b506103af61186f565b34801561086a57600080fd5b50600b546105db906001600160601b031681565b34801561088a57600080fd5b506104c6610899366004614f30565b61187c565b3480156108aa57600080fd5b506108be6108b9366004614fb4565b6118f0565b604080516001600160a01b03909316835263ffffffff909116602083015201610391565b3480156108ee57600080fd5b506103856108fd3660046152cf565b611936565b34801561090e57600080fd5b506103af6040518060400160405280600981526020016806630313730313232360bc1b81525081565b34801561094357600080fd5b50610385610952366004615399565b611d8b565b34801561096357600080fd5b506104c6610972366004614fb4565b611e24565b34801561098357600080fd5b506104c6610992366004614f04565b60a01b6001600160a01b03909116176000908152601060205260409020546001600160601b031690565b3480156109c857600080fd5b506006546103f2906001600160a01b031681565b3480156109e857600080fd5b506109fc6109f73660046153d7565b611e55565b60405161039192919061542f565b348015610a1657600080fd5b506103af611f90565b348015610a2b57600080fd5b506104c6611f9d565b348015610a4057600080fd5b5061042a610a4f366004615399565b6120fb565b348015610a6057600080fd5b5061042a610a6f366004614f30565b612167565b348015610a8057600080fd5b50610a94610a8f366004614f04565b612218565b604080519215158352602083019190915201610391565b348015610ab757600080fd5b50610acb610ac6366004614ed6565b6126b4565b604051610391929190615448565b348015610ae557600080fd5b5061042a610af4366004614f30565b612718565b348015610b0557600080fd5b5061042a610b14366004615496565b6127c9565b348015610b2557600080fd5b506103af610b34366004614ed6565b6128ae565b348015610b4557600080fd5b50610385610b5436600461563a565b612928565b348015610b6557600080fd5b50610a94610b74366004614f04565b612eb6565b610385610b873660046156d7565b613246565b610385610b9a366004614f04565b613841565b348015610bab57600080fd5b50610385610bba366004615757565b600560209081526000928352604080842090915290825290205460ff1681565b348015610be657600080fd5b50610bfa610bf5366004614ed6565b6139c0565b6040516103919190615785565b348015610c1357600080fd5b506103f2610c22366004615821565b613b40565b348015610c3357600080fd5b506104c6610c42366004615895565b613fe6565b348015610c5357600080fd5b506103af604051806040016040528060058152602001640312e302e360dc1b81525081565b60006301ffc9a760e01b6001600160e01b031983161480610ca957506380ac58cd60e01b6001600160e01b03198316145b80610cc45750635b5e139f60e01b6001600160e01b03198316145b92915050565b60008054610cd79061592a565b80601f0160208091040260200160405190810160405280929190818152602001828054610d039061592a565b8015610d505780601f10610d2557610100808354040283529160200191610d50565b820191906000526020600020905b815481529060010190602001808311610d3357829003601f168201915b505050505081565b6000818152600260205260409020546001600160a01b031633811480610da157506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b610de35760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064015b60405180910390fd5b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6006546001600160a01b03163314610e7f5760065460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6001600160a01b038116610ea65760405163d92e233d60e01b815260040160405180910390fd5b600b80546001600160601b0316600160601b6001600160a01b038416908102919091179091556040517f8d1e8547016120917daad7f81c42b48f7fee379badc48f1889f0f43bb619472590600090a250565b600081815260156020908152604080832081516101008101835281546001600160601b03811682526001600160a01b03600160601b918290041694820194909452600182015492810192909252600281015463ffffffff808216606085810191909152640100000000830482166080860152600160401b830490911660a0850152938593929160c084019160ff9104166005811115610f9957610f9961507c565b6005811115610faa57610faa61507c565b81526020016003820180548060200260200160405190810160405280929190818152602001828054801561102957602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411610fec5790505b50505050508152505090508060e001515192508267ffffffffffffffff8111156110555761105561510f565b60405190808252806020026020018201604052801561109a57816020015b60408051808201909152600080825260208201528152602001906001900390816110735790505b50915060005b8381101561114757600085905060208360e0015183815181106110c5576110c5615964565b60209081029190910181015163ffffffff90811690921b929092176000818152600e845260409081902081518083019092525492831681526401000000009092046001600160601b031692820192909252845185908490811061112a5761112a615964565b6020026020010181905250508061114090615990565b90506110a0565b5050915091565b602081811b83176000818152600f909252604090912054906060908267ffffffffffffffff8111156111825761118261510f565b6040519080825280602002602001820160405280156111ab578160200160208202803683370190505b50915060005b83811015611233576000828152600f602052604090208054829081106111d9576111d9615964565b9060005260206000200160009054906101000a90046001600160a01b031683828151811061120957611209615964565b6001600160a01b03909216602092830291909101909101528061122b81615990565b9150506111b1565b50509250929050565b6000818152600260205260409020546001600160a01b038481169116146112a55760405162461bcd60e51b815260206004820152600a60248201527f57524f4e475f46524f4d000000000000000000000000000000000000000000006044820152606401610dda565b6001600160a01b0382166112ef5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610dda565b336001600160a01b038416148061132957506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b8061134a57506000818152600460205260409020546001600160a01b031633145b6113875760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610dda565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6012602052816000526040600020818154811061143257600080fd5b9060005260206000209060089182820401919006600402915091509054906101000a900463ffffffff1681565b6013602052816000526040600020818154811061143257600080fd5b61148683838361123c565b6001600160a01b0382163b1561156b57604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af11580156114fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152191906159a9565b6001600160e01b0319161461156b5760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610dda565b505050565b600081815260156020908152604080832081516101008101835281546001600160601b03811682526001600160a01b03600160601b918290041694820194909452600182015492810192909252600281015463ffffffff808216606085810191909152640100000000830482166080860152600160401b830490911660a0850152938593929160c084019160ff91041660058111156116115761161161507c565b60058111156116225761162261507c565b8152602001600382018054806020026020016040519081016040528092919081815260200182805480156116a157602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff16815260200190600401906020826003010492830192600103820291508084116116645790505b50505050508152505090506116b681856142de565b91508151925050915091565b60008082118015610cc457506009546116dc9060016159c6565b821092915050565b60006116f18260016159c6565b905060095481111561172457600954604051637ae5968560e01b8152610dda918391600401918252602082015260400190565b919050565b6006546001600160a01b031633146117695760065460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610dda565b805160000361178b57604051637c946ed760e01b815260040160405180910390fd5b60086117978282615a24565b507f5411e8ebf1636d9e83d5fc4900bf80cbac82e8790da2a4c94db4895e889eedf6816040516117c79190614ec3565b60405180910390a150565b600f60205281600052604060002081815481106117ee57600080fd5b6000918252602090912001546001600160a01b03169150829050565b6000818152600260205260409020546001600160a01b0316806117245760405162461bcd60e51b815260206004820152600a60248201527f4e4f545f4d494e544544000000000000000000000000000000000000000000006044820152606401610dda565b60088054610cd79061592a565b60006001600160a01b0382166118d45760405162461bcd60e51b815260206004820152600c60248201527f5a45524f5f4144445245535300000000000000000000000000000000000000006044820152606401610dda565b506001600160a01b031660009081526003602052604090205490565b600d602052816000526040600020818154811061190c57600080fd5b6000918252602090912001546001600160a01b0381169250600160a01b900463ffffffff16905082565b600081815260156020908152604080832081516101008101835281546001600160601b0381168252600160601b908190046001600160a01b031694820194909452600182015492810192909252600281015463ffffffff8082166060850152640100000000820481166080850152600160401b82041660a0840152849360c08401910460ff1660058111156119cd576119cd61507c565b60058111156119de576119de61507c565b815260200160038201805480602002602001604051908101604052809291908181526020018280548015611a5d57602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411611a205790505b505050505081525050905060046005811115611a7b57611a7b61507c565b8160c001516005811115611a9157611a9161507c565b14611ad0578060c001516005811115611aac57611aac61507c565b604051633c053f9d60e21b8152600481019190915260248101849052604401610dda565b8351855114611aff57845184516040516308151c1160e41b815260048101929092526024820152604401610dda565b80602001516001600160a01b0316336001600160a01b031614611b535760208101516040516379f91cd360e01b81523360048201526001600160a01b03909116602482015260448101849052606401610dda565b845160005b81811015611d7e57600060116000898481518110611b7857611b78615964565b6020908102919091018101516001600160a01b03908116835282820193909352604091820160009081205490931660a08a901b81178085526010909252919092205489519193506001600160601b03169081908a9086908110611bdd57611bdd615964565b60200260200101516001611bf19190615ae4565b6001600160601b03161115611c4b57600b8054829190600090611c1e9084906001600160601b0316615ae4565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555060009050611ccf565b888481518110611c5d57611c5d615964565b6020908102919091010151600b8054600090611c839084906001600160601b0316615ae4565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550888481518110611cb957611cb9615964565b602002602001015181611ccc9190615b0f565b90505b600082815260106020526040902080546bffffffffffffffffffffffff19166001600160601b038316179055885188906001600160a01b038516907fa2e524bd0f71903485fbb3d6d50cb305f61005ceea2047c3ac92aa7e0d104306908c9088908110611d3e57611d3e615964565b6020026020010151604051611d6291906001600160601b0391909116815260200190565b60405180910390a350505080611d7790615990565b9050611b58565b5060019695505050505050565b6006546000906001600160a01b03163314611dce5760065460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6001600160a01b038316611df55760405163d92e233d60e01b815260040160405180910390fd5b506001600160a01b03919091166000908152601460205260409020805460ff1916911515919091179055600190565b600c6020528160005260406000208181548110611e4057600080fd5b90600052602060002001600091509150505481565b6000606081846001811115611e6c57611e6c61507c565b03611efd5760008381526012602090815260409182902080548351818402810184019094528084529091830182828015611ef157602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411611eb45790505b50505050509050611f85565b60008381526013602090815260409182902080548351818402810184019094528084529091830182828015611f7d57602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411611f405790505b505050505090505b805191509250929050565b60018054610cd79061592a565b60006001600a541115611fc3576040516345f5ce8b60e11b815260040160405180910390fd5b6002600a55600b54600160601b90046001600160a01b0316331461201557600b5460405163312d21ff60e11b8152336004820152600160601b9091046001600160a01b03166024820152604401610dda565b50600b546001600160601b031680156120f357600b80546bffffffffffffffffffffffff19169055604051600090339083908381818185875af1925050503d806000811461207f576040519150601f19603f3d011682016040523d82523d6000602084013e612084565b606091505b50509050806120bc5760405163cd3f165960e01b81526000600482015230602482015233604482015260648101839052608401610dda565b60405182815233907ff36f4d6622e16a536bbb049064af779cdd483a0b388d347d3752a65f1058bf5b9060200160405180910390a2505b6001600a5590565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6006546001600160a01b031633146121a75760065460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6001600160a01b0381166121ce5760405163d92e233d60e01b815260040160405180910390fd5b600780546001600160a01b0319166001600160a01b0383169081179091556040517f2c1c11af44aa5608f1dca38c00275c30ea091e02417d36e70e9a1538689c433d90600090a250565b6000806001600a54111561223f576040516345f5ce8b60e11b815260040160405180910390fd5b6002600a556007546001600160a01b031633146122845760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6001600160a01b0384166122ab5760405163d92e233d60e01b815260040160405180910390fd5b600083815260156020526040902060056002820154600160601b900460ff1660058111156122db576122db61507c565b14612324576002810154600160601b900460ff1660058111156123005761230061507c565b604051633c053f9d60e21b8152600481019190915260248101859052604401610dda565b60a084901b6001600160a01b038616176000818152600d6020908152604080832080548251818502810185019093528083529192909190849084015b828210156123ac57600084815260209081902060408051808201909152908401546001600160a01b0381168252600160a01b900463ffffffff1681830152825260019092019101612360565b50508251929350505060008190036123e95760405163df2ddd7360e01b81526001600160a01b038916600482015260248101889052604401610dda565b808460020160088282829054906101000a900463ffffffff1661240c9190615b37565b92506101000a81548163ffffffff021916908363ffffffff1602179055508360020160089054906101000a900463ffffffff1663ffffffff166000036124625760028401805460ff60601b1916600160601b1790555b60005b8181101561252a576000889050602084838151811061248657612486615964565b60209081029190910181015181015163ffffffff1690911b919091176000818152600e9092526040909120546124cd9064010000000090046001600160601b0316886159c6565b9650601160008584815181106124e5576124e5615964565b602090810291909101810151516001600160a01b0316825281019190915260400160002080546001600160a01b0319169055508061252281615990565b915050612465565b506000838152600d6020526040812061254291614c87565b6000838152601060205260409020546001600160601b03168086111561256f57806001600160601b031695505b85156126685760008481526010602052604080822080546bffffffffffffffffffffffff19169055516001600160a01b038b169088908381818185875af1925050503d80600081146125dd576040519150601f19603f3d011682016040523d82523d6000602084013e6125e2565b606091505b50509050806126235760405163cd3f165960e01b8152600060048201523060248201526001600160a01b038b16604482015260648101889052608401610dda565b896001600160a01b03167fbb28353e4598c3b9199101a66e0989549b659a59a54d2c27fbb183f1932c8e6d8860405161265e91815260200190565b60405180910390a2505b60405188906001600160a01b038b16907f5ebf7fe30be09f0f03b9195632508d95c8b67bf010c93abda67f70d5d9599d1e90600090a350506001600a8190559793965092945050505050565b6000818152600c60209081526040808320805482518185028101850190935280835260609383018282801561270857602002820191906000526020600020905b8154815260200190600101908083116126f4575b5050505050905080519150915091565b6006546001600160a01b031633146127585760065460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6001600160a01b03811661277f5760405163d92e233d60e01b815260040160405180910390fd5b600680546001600160a01b0319166001600160a01b0383169081179091556040517f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b90600090a250565b6127d485858561123c565b6001600160a01b0384163b156128a757604051630a85bd0160e11b808252906001600160a01b0386169063150b7a029061281a9033908a90899089908990600401615b54565b6020604051808303816000875af1158015612839573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061285d91906159a9565b6001600160e01b031916146128a75760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610dda565b5050505050565b6000818152601560205260408120600101546060915060086040518060400160405280600981526020016806630313730313232360bc1b8152506128f18361442f565b6128fe608085901b61442f565b6040516020016129119493929190615ba8565b604051602081830303815290604052915050919050565b6007546000906001600160a01b0316331461296b5760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b60006129768361180a565b9050876001600160a01b0316816001600160a01b0316146129bd5760405163521eb56d60e11b81526001600160a01b03808a16600483015282166024820152604401610dda565b600083815260156020908152604080832081516101008101835281546001600160601b03811682526001600160a01b03600160601b918290041694820194909452600182015492810192909252600281015463ffffffff8082166060850152640100000000820481166080850152600160401b82041660a08401529192909160c084019160ff9104166005811115612a5757612a5761507c565b6005811115612a6857612a6861507c565b815260200160038201805480602002602001604051908101604052809291908181526020018280548015612ae757602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411612aaa5790505b505050505081525050905060016005811115612b0557612b0561507c565b8160c001516005811115612b1b57612b1b61507c565b14612b36578060c0015160058111156123005761230061507c565b612b418888886145ff565b63ffffffff85166060820152600060808201819052875167ffffffffffffffff811115612b7057612b7061510f565b604051908082528060200260200182016040528015612b99578160200160208202803683370190505b5090506000885167ffffffffffffffff811115612bb857612bb861510f565b604051908082528060200260200182016040528015612bfd57816020015b6040805180820190915260008082526020820152815260200190600190039081612bd65790505b5090506000805b8a51811015612d3257898181518110612c1f57612c1f615964565b60200260200101516000015163ffffffff16600003612c9457600088905060208c8381518110612c5157612c51615964565b60209081029190910181015163ffffffff1690911b919091176000908152600e9091526040902080546fffffffffffffffffffffffffffffffff19169055612d20565b8a8181518110612ca657612ca6615964565b6020026020010151848381518110612cc057612cc0615964565b602002602001019063ffffffff16908163ffffffff1681525050898181518110612cec57612cec615964565b6020026020010151838381518110612d0657612d06615964565b60200260200101819052508180612d1c90615990565b9250505b80612d2a81615990565b915050612c04565b5060408401518b8114612d69576000888152600c602090815260408083208054600181018255908452919092200182905585018c90525b612d76858585858c6147c6565b6000888152601560209081526040918290208751918801516001600160a01b0316600160601b9081026001600160601b03909316929092178155918701516001830155606087015160028301805460808a015160a08b015163ffffffff908116600160401b026bffffffff0000000000000000199282166401000000000267ffffffffffffffff199094169190951617919091179081168317825560c08a01518a9594909360ff60601b19166cffffffffff0000000000000000199092169190911790836005811115612e4b57612e4b61507c565b021790555060e08201518051612e6b916003840191602090910190614ca8565b50506040518d81528991507fff312ce131c4d73ac90ece91266be7090486c5e15f78b7ea2b108c36dfd475299060200160405180910390a25060019c9b505050505050505050505050565b6000806001600a541115612edd576040516345f5ce8b60e11b815260040160405180910390fd5b6002600a556007546001600160a01b03163314612f225760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6000612f2d8461180a565b9050846001600160a01b0316816001600160a01b031614612f745760405163521eb56d60e11b81526001600160a01b03808716600483015282166024820152604401610dda565b600084815260156020526040902060016002820154600160601b900460ff166005811115612fa457612fa461507c565b1480612fcf575060056002820154600160601b900460ff166005811115612fcd57612fcd61507c565b145b15613018576002810154600160601b900460ff166005811115612ff457612ff461507c565b604051633c053f9d60e21b8152600481019190915260248101869052604401610dda565b6002810154600160401b900463ffffffff16156130525760028101805460ff60601b19166c05000000000000000000000000179055613068565b60028101805460ff60601b1916600160601b1790555b600085815260126020526040812061307f91614d57565b600085815260136020526040812061309691614d57565b60005b600382015481101561312357600086905060208360030183815481106130c1576130c1615964565b90600052602060002090600891828204019190066004029054906101000a900463ffffffff1663ffffffff16901b81179050600f600082815260200190815260200160002060006131129190614d7c565b5061311c81615990565b9050613099565b5080546040516001600160601b0390911693506000906001600160a01b0388169085908381818185875af1925050503d806000811461317e576040519150601f19603f3d011682016040523d82523d6000602084013e613183565b606091505b50509050806131c45760405163cd3f165960e01b8152600060048201523060248201526001600160a01b038816604482015260648101859052608401610dda565b866001600160a01b03167fbb28353e4598c3b9199101a66e0989549b659a59a54d2c27fbb183f1932c8e6d856040516131ff91815260200190565b60405180910390a260405186907fe45f5b9540df4f71b7e044809fa318806328c1ea2388a70c7373d97ccf8a0faa90600090a250506001600a819055959194509092505050565b6007546000906001600160a01b031633146132895760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b81518351146132b857825182516040516308151c1160e41b815260048101929092526024820152604401610dda565b6000848152601560205260409020600280820154600160601b900460ff1660058111156132e7576132e761507c565b1461330c576002810154600160601b900460ff166005811115612ff457612ff461507c565b83516000805b82811015613401576000889050602087838151811061333357613333615964565b60209081029190910181015163ffffffff90811690921b929092176000818152600e845260408082208151808301909252549384168082526401000000009094046001600160601b03169481019490945290929190036133d45787838151811061339f5761339f615964565b60200260200101518a6040516332832be560e21b8152600401610dda92919063ffffffff929092168252602082015260400190565b60208101516133ec906001600160601b0316856159c6565b93505050806133fa90615990565b9050613312565b5080341461343257604051637ebbcab960e11b81523460048201526024810182905260448101889052606401610dda565b6001600160a01b03888116600090815260116020526040902054161561346e576040516322ddebd960e21b815260048101889052602401610dda565b60a087901b6001600160a01b0389161760005b8381101561376257600088828151811061349d5761349d615964565b6020026020010151905060008883815181106134bb576134bb615964565b60200260200101519050816001600160a01b03168c6001600160a01b0316036134fa576040516322ddebd960e21b8152600481018c9052602401610dda565b6001600160a01b038281166000908152601160205260409020541615613551576001600160a01b038281166000908152601160205260409081902054905163631695bd60e01b815291166004820152602401610dda565b60008b905060208a858151811061356a5761356a615964565b60209081029190910181015163ffffffff90811690921b929092176000818152600e8452604080822054600f909552902054909290911690036135c3576040516304ad100760e21b8152600481018d9052602401610dda565b6000818152600f602090815260408083208054600181810183559185528385200180546001600160a01b03808a166001600160a01b031990921682179092558a8652600d8552838620845180860190955290845263ffffffff8089168587019081528254948501835591875294909520925192909101805494518416600160a01b0277ffffffffffffffffffffffffffffffffffffffffffffffff19909516929091169190911792909217909155600289018054600160401b900490911690600861368d83615c3a565b91906101000a81548163ffffffff021916908363ffffffff160217905550508c60116000856001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550826001600160a01b03168c8e6001600160a01b03167f6835389a6da5341647f18cbe0a89c56f473f4c17bfaee6e6d07d61f1928e0b7c85604051613746919063ffffffff91909116815260200190565b60405180910390a45050508061375b90615990565b9050613481565b50600284015463ffffffff64010000000082048116600160401b90920416036137a45760028401805460ff60601b19166c030000000000000000000000001790555b600081815260106020526040812080543492906137cb9084906001600160601b0316615ae4565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550886001600160a01b03167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c3460405161382a91815260200190565b60405180910390a250600198975050505050505050565b6007546000906001600160a01b031633146138845760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b600061388f8361180a565b9050836001600160a01b0316816001600160a01b0316146138d65760405163521eb56d60e11b81526001600160a01b03808616600483015282166024820152604401610dda565b600083815260156020526040902060016002820154600160601b900460ff1660058111156139065761390661507c565b1461392757604051635960d22f60e11b815260048101859052602401610dda565b80546001600160601b0316341461396c578054604051631c30abbb60e31b81523460048201526001600160601b03909116602482015260448101859052606401610dda565b60028101805460ff60601b19166c0200000000000000000000000017905560405184907fa48b531f972c0e4aca57afcc5c099c52a7bd21bc5e2a1b733eec3be9e88da97a90600090a2506001949350505050565b613a086040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a081018290529060c08201908152602001606081525090565b60008281526015602090815260409182902082516101008101845281546001600160601b0381168252600160601b908190046001600160a01b031693820193909352600182015493810193909352600281015463ffffffff8082166060860152640100000000820481166080860152600160401b82041660a0850152909160c08401910460ff166005811115613aa057613aa061507c565b6005811115613ab157613ab161507c565b815260200160038201805480602002602001604051908101604052809291908181526020018280548015613b3057602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411613af35790505b5050505050815250509050919050565b60006001600a541115613b66576040516345f5ce8b60e11b815260040160405180910390fd5b6002600a556007546001600160a01b03163314613bab5760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6000613bb68561180a565b9050856001600160a01b0316816001600160a01b031614613bfd5760405163521eb56d60e11b81526001600160a01b03808816600483015282166024820152604401610dda565b6001600160a01b03841660009081526014602052604090205460ff16613c405760405162a2307960e51b81526001600160a01b0385166004820152602401610dda565b600085815260156020526040902060036002820154600160601b900460ff166005811115613c7057613c7061507c565b14613cb9576002810154600160601b900460ff166005811115613c9557613c9561507c565b604051633c053f9d60e21b8152600481019190915260248101879052604401610dda565b604080516101008101825282546001600160601b0381168252600160601b908190046001600160a01b03166020830152600184015492820192909252600283015463ffffffff8082166060840152640100000000820481166080840152600160401b82041660a0830152600092613de69291859160c08401910460ff166005811115613d4757613d4761507c565b6005811115613d5857613d5861507c565b815260200160038201805480602002602001604051908101604052809291908181526020018280548015613dd757602002820191906000526020600020906000905b82829054906101000a900463ffffffff1663ffffffff1681526020019060040190602082600301049283019260010382029150808411613d9a5790505b505050505081525050886142de565b6002830154604051631e731b7560e31b81529192506001600160a01b0388169163f398dba891613e2391859163ffffffff16908a90600401615c5d565b6020604051808303816000875af1158015613e42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e669190615c98565b6000888152601360205260409020600384018054929650613e8692614d9a565b506040516304d9dc3f60e11b81526001600160a01b037f0000000000000000000000002f1f7d38e4772884b88f3ecd8b6b9facdc31911216906309b3b87e90613ed6906003860190600401615cb5565b600060405180830381865afa158015613ef3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613f1b9190810190615e3d565b60008881526012602090815260409091208251613f3e9391929190910190614ca8565b5081546001600160601b0316600160601b6001600160a01b03861690810291909117835560028301805460ff60601b19166c0400000000000000000000000017905560405188907f2d53f895cd5faf3cddba94a25c2ced2105885b5b37450ff430ffa3cbdf332c7490600090a360405187907fa133ed72c03a7d008deaae618a61613c4fd41c67bba1cad1a6bc0a1c5a9c156e90600090a250506001600a5550949350505050565b60006001600a54111561400c576040516345f5ce8b60e11b815260040160405180910390fd5b6002600a556007546001600160a01b031633146140515760075460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610dda565b6001600160a01b0386166140785760405163d92e233d60e01b815260040160405180910390fd5b6140838585856145ff565b60005b8451811015614117578381815181106140a1576140a1615964565b60200260200101516000015163ffffffff16600014806140e757508381815181106140ce576140ce615964565b6020026020010151602001516001600160601b03166000145b1561410557604051637c946ed760e01b815260040160405180910390fd5b8061410f81615990565b915050614086565b50506009548061412681615990565b9150506141716040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a081018290529060c08201908152602001606081525090565b63ffffffff8316606082015260408101869052600160c08201818152505061419d8186868851866147c6565b6000828152601560209081526040918290208351918401516001600160a01b0316600160601b9081026001600160601b039093169290921781559183015160018301556060830151600283018054608086015160a087015163ffffffff908116600160401b026bffffffff0000000000000000199282166401000000000267ffffffffffffffff199094169190951617919091179081168317825560c0860151869594909360ff60601b19166cffffffffff00000000000000001990921691909117908360058111156142725761427261507c565b021790555060e08201518051614292916003840191602090910190614ca8565b50505060098290556142a48783614a7d565b60405182907f9169d45eacd63571e315a0504da919b7c89de505493e7b34051802dd0816a06990600090a2506001600a5595945050505050565b60608260a0015163ffffffff1667ffffffffffffffff8111156143035761430361510f565b60405190808252806020026020018201604052801561432c578160200160208202803683370190505b5090506000805b8460e001515181101561442757600084905060208660e00151838151811061435d5761435d615964565b602002602001015163ffffffff16901b8117905060005b6000828152600f6020526040902054811015614412576000828152600f602052604090208054829081106143aa576143aa615964565b9060005260206000200160009054906101000a90046001600160a01b03168585815181106143da576143da615964565b6001600160a01b0390921660209283029190910190910152836143fc81615990565b945050808061440a90615990565b915050614374565b5050808061441f90615990565b915050614333565b505092915050565b7aff00000000000000ff00000000000000ff00000000000000ff00006bffffffff0000000000000000604083901c9081167bffffffff00000000000000000000000000000000000000000000000084161760201c6fffffffff000000000000000000000000919091166001600160e01b031984161717601081901c9182167eff00000000000000ff00000000000000ff00000000000000ff000000000000821617600890811c7bff00000000000000ff00000000000000ff00000000000000ff000000939093167fff00000000000000ff00000000000000ff00000000000000ff000000000000009290921691909117919091179081901c7e0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f167f0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00600492831c16179061459b827f06060606060606060606060606060606060606060606060606060606060606066159c6565b901c7f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f1660276145cb9190615ed7565b6145f5827f30303030303030303030303030303030303030303030303030303030303030306159c6565b610cc491906159c6565b600083900361462157604051637c946ed760e01b815260040160405180910390fd5b8151158061463157508051825114155b1561465c57815181516040516308151c1160e41b815260048101929092526024820152604401610dda565b60007f0000000000000000000000002f1f7d38e4772884b88f3ecd8b6b9facdc3191126001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156146bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146e09190615ef6565b90506000805b84518110156147be576146fa8260016159c6565b85828151811061470c5761470c615964565b602002602001015163ffffffff16108061474457508285828151811061473457614734615964565b602002602001015163ffffffff16115b156147895784818151811061475b5761475b615964565b6020026020010151604051632ab10b0b60e21b8152600401610dda919063ffffffff91909116815260200190565b84818151811061479b5761479b615964565b602002602001015163ffffffff16915080806147b690615990565b9150506146e6565b505050505050565b60008267ffffffffffffffff8111156147e1576147e161510f565b60405190808252806020026020018201604052801561480a578160200160208202803683370190505b5060e087015260005b8381101561499a5785818151811061482d5761482d615964565b60200260200101518760e00151828151811061484b5761484b615964565b63ffffffff909216602092830291909101820152865184919088908490811061487657614876615964565b602002602001015163ffffffff16901b8117905085828151811061489c5761489c615964565b6020908102919091018101516000838152600e8352604090208151815492909301516001600160601b0316640100000000026fffffffffffffffffffffffffffffffff1990921663ffffffff90931692909217179055855186908390811061490657614906615964565b602002602001015160000151886080018181516149239190615f0f565b63ffffffff1690525085516001600160601b0384169087908490811061494b5761494b615964565b6020026020010151602001516001600160601b031611156149875785828151811061497857614978615964565b60200260200101516020015192505b508061499281615990565b915050614813565b506001600160601b038116865260808601516000906149ba906002615f2e565b6149c5906001615f0f565b63ffffffff1690506149d8600382615f70565b6000036149f1576149ea600382615f84565b9050614a0a565b6149fc600382615f84565b614a079060016159c6565b90505b80876060015163ffffffff161080614a355750866080015163ffffffff16876060015163ffffffff16115b15614a74576060870151608088015160405163eb3a8ba360e01b815263ffffffff92831660048201526024810184905291166044820152606401610dda565b50505050505050565b614a878282614b6d565b6001600160a01b0382163b15614b6957604051630a85bd0160e11b80825233600483015260006024830181905260448301849052608060648401526084830152906001600160a01b0384169063150b7a029060a4016020604051808303816000875af1158015614afb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b1f91906159a9565b6001600160e01b03191614614b695760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606401610dda565b5050565b6001600160a01b038216614bb75760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606401610dda565b6000818152600260205260409020546001600160a01b031615614c1c5760405162461bcd60e51b815260206004820152600e60248201527f414c52454144595f4d494e5445440000000000000000000000000000000000006044820152606401610dda565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b5080546000825590600052602060002090810190614ca59190614de8565b50565b82805482825590600052602060002090600701600890048101928215614d475791602002820160005b83821115614d1557835183826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302614cd1565b8015614d455782816101000a81549063ffffffff0219169055600401602081600301049283019260010302614d15565b505b50614d53929150614e18565b5090565b508054600082556007016008900490600052602060002090810190614ca59190614e18565b5080546000825590600052602060002090810190614ca59190614e18565b82805482825590600052602060002090600701600890048101928215614d47576000526020600020916007016008900482015b82811115614d47578254825591600101919060010190614dcd565b5b80821115614d5357805477ffffffffffffffffffffffffffffffffffffffffffffffff19168155600101614de9565b5b80821115614d535760008155600101614e19565b6001600160e01b031981168114614ca557600080fd5b600060208284031215614e5557600080fd5b8135614e6081614e2d565b9392505050565b60005b83811015614e82578181015183820152602001614e6a565b83811115614e91576000848401525b50505050565b60008151808452614eaf816020860160208601614e67565b601f01601f19169290920160200192915050565b602081526000614e606020830184614e97565b600060208284031215614ee857600080fd5b5035919050565b6001600160a01b0381168114614ca557600080fd5b60008060408385031215614f1757600080fd5b8235614f2281614eef565b946020939093013593505050565b600060208284031215614f4257600080fd5b8135614e6081614eef565b6000604080830185845260208281860152818651808452606087019150828801935060005b81811015614fa6578451805163ffffffff1684528401516001600160601b0316848401529383019391850191600101614f72565b509098975050505050505050565b60008060408385031215614fc757600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b8381101561500f5781516001600160a01b031687529582019590820190600101614fea565b509495945050505050565b8281526040602082015260006150336040830184614fd6565b949350505050565b60008060006060848603121561505057600080fd5b833561505b81614eef565b9250602084013561506b81614eef565b929592945050506040919091013590565b634e487b7160e01b600052602160045260246000fd5b600681106150b057634e487b7160e01b600052602160045260246000fd5b9052565b6001600160601b03881681526001600160a01b03871660208201526040810186905263ffffffff85811660608301528481166080830152831660a082015260e0810161510360c0830184615092565b98975050505050505050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156151485761514861510f565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156151775761517761510f565b604052919050565b600067ffffffffffffffff8311156151995761519961510f565b6151ac601f8401601f191660200161514e565b90508281528383830111156151c057600080fd5b828260208301376000602084830101529392505050565b6000602082840312156151e957600080fd5b813567ffffffffffffffff81111561520057600080fd5b8201601f8101841361521157600080fd5b6150338482356020840161517f565b600067ffffffffffffffff82111561523a5761523a61510f565b5060051b60200190565b600082601f83011261525557600080fd5b8135602061526a61526583615220565b61514e565b82815260059290921b8401810191818101908684111561528957600080fd5b8286015b848110156152ad5780356152a081614eef565b835291830191830161528d565b509695505050505050565b80356001600160601b038116811461172457600080fd5b6000806000606084860312156152e457600080fd5b833567ffffffffffffffff808211156152fc57600080fd5b61530887838801615244565b945060209150818601358181111561531f57600080fd5b86019050601f8101871361533257600080fd5b803561534061526582615220565b81815260059190911b8201830190838101908983111561535f57600080fd5b928401925b8284101561538457615375846152b8565b82529284019290840190615364565b96999698505050506040949094013593505050565b600080604083850312156153ac57600080fd5b82356153b781614eef565b9150602083013580151581146153cc57600080fd5b809150509250929050565b600080604083850312156153ea57600080fd5b823560028110614f2257600080fd5b600081518084526020808501945080840160005b8381101561500f57815163ffffffff168752958201959082019060010161540d565b82815260406020820152600061503360408301846153f9565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156154895784518352938301939183019160010161546d565b5090979650505050505050565b6000806000806000608086880312156154ae57600080fd5b85356154b981614eef565b945060208601356154c981614eef565b935060408601359250606086013567ffffffffffffffff808211156154ed57600080fd5b818801915088601f83011261550157600080fd5b81358181111561551057600080fd5b89602082850101111561552257600080fd5b9699959850939650602001949392505050565b63ffffffff81168114614ca557600080fd5b600082601f83011261555857600080fd5b8135602061556861526583615220565b82815260059290921b8401810191818101908684111561558757600080fd5b8286015b848110156152ad57803561559e81615535565b835291830191830161558b565b600082601f8301126155bc57600080fd5b813560206155cc61526583615220565b82815260069290921b840181019181810190868411156155eb57600080fd5b8286015b848110156152ad57604081890312156156085760008081fd5b615610615125565b813561561b81615535565b81526156288286016152b8565b818601528352918301916040016155ef565b60008060008060008060c0878903121561565357600080fd5b863561565e81614eef565b955060208701359450604087013567ffffffffffffffff8082111561568257600080fd5b61568e8a838b01615547565b955060608901359150808211156156a457600080fd5b506156b189828a016155ab565b93505060808701356156c281615535565b8092505060a087013590509295509295509295565b600080600080608085870312156156ed57600080fd5b84356156f881614eef565b935060208501359250604085013567ffffffffffffffff8082111561571c57600080fd5b61572888838901615244565b9350606087013591508082111561573e57600080fd5b5061574b87828801615547565b91505092959194509250565b6000806040838503121561576a57600080fd5b823561577581614eef565b915060208301356153cc81614eef565b602081526001600160601b0382511660208201526001600160a01b03602083015116604082015260408201516060820152600060608301516157cf608084018263ffffffff169052565b50608083015163ffffffff811660a08401525060a083015163ffffffff811660c08401525060c083015161580660e0840182615092565b5060e0830151610100838101526150336101208401826153f9565b6000806000806080858703121561583757600080fd5b843561584281614eef565b935060208501359250604085013561585981614eef565b9150606085013567ffffffffffffffff81111561587557600080fd5b8501601f8101871361588657600080fd5b61574b8782356020840161517f565b600080600080600060a086880312156158ad57600080fd5b85356158b881614eef565b945060208601359350604086013567ffffffffffffffff808211156158dc57600080fd5b6158e889838a01615547565b945060608801359150808211156158fe57600080fd5b5061590b888289016155ab565b925050608086013561591c81615535565b809150509295509295909350565b600181811c9082168061593e57607f821691505b60208210810361595e57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016159a2576159a261597a565b5060010190565b6000602082840312156159bb57600080fd5b8151614e6081614e2d565b600082198211156159d9576159d961597a565b500190565b601f82111561156b57600081815260208120601f850160051c81016020861015615a055750805b601f850160051c820191505b818110156147be57828155600101615a11565b815167ffffffffffffffff811115615a3e57615a3e61510f565b615a5281615a4c845461592a565b846159de565b602080601f831160018114615a875760008415615a6f5750858301515b600019600386901b1c1916600185901b1785556147be565b600085815260208120601f198616915b82811015615ab657888601518255948401946001909101908401615a97565b5085821015615ad45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006001600160601b03808316818516808303821115615b0657615b0661597a565b01949350505050565b60006001600160601b0383811690831681811015615b2f57615b2f61597a565b039392505050565b600063ffffffff83811690831681811015615b2f57615b2f61597a565b60006001600160a01b03808816835280871660208401525084604083015260806060830152826080830152828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b6000808654615bb68161592a565b60018281168015615bce5760018114615be357615c12565b60ff1984168752821515830287019450615c12565b8a60005260208060002060005b85811015615c095781548a820152908401908201615bf0565b50505082870194505b505050508551615c26818360208a01614e67565b019384525050602082015260400192915050565b600063ffffffff808316818103615c5357615c5361597a565b6001019392505050565b606081526000615c706060830186614fd6565b63ffffffff851660208401528281036040840152615c8e8185614e97565b9695505050505050565b600060208284031215615caa57600080fd5b8151614e6081614eef565b60006020808301818452808554615cd0818490815260200190565b60008881526020812094509092505b81600782011015615d5557835463ffffffff808216855281871c811687860152604082811c821690860152606082811c821690860152608082811c82169086015260a082811c82169086015260c082811c9091169085015260e090811c9084015260019093019261010090920191600801615cdf565b92549281811015615d715763ffffffff84168352918401916001015b81811015615d8c5783851c63ffffffff168352918401916001015b81811015615da957604084901c63ffffffff168352918401916001015b81811015615dc657606084901c63ffffffff168352918401916001015b81811015615de357608084901c63ffffffff168352918401916001015b81811015615e005760a084901c63ffffffff168352918401916001015b81811015615e1d5760c084901c63ffffffff168352918401916001015b81811015615e315760e084901c8352918401915b50909695505050505050565b60006020808385031215615e5057600080fd5b825167ffffffffffffffff811115615e6757600080fd5b8301601f81018513615e7857600080fd5b8051615e8661526582615220565b81815260059190911b82018301908381019087831115615ea557600080fd5b928401925b82841015615ecc578351615ebd81615535565b82529284019290840190615eaa565b979650505050505050565b6000816000190483118215151615615ef157615ef161597a565b500290565b600060208284031215615f0857600080fd5b5051919050565b600063ffffffff808316818516808303821115615b0657615b0661597a565b600063ffffffff80831681851681830481118215151615615f5157615f5161597a565b02949350505050565b634e487b7160e01b600052601260045260246000fd5b600082615f7f57615f7f615f5a565b500690565b600082615f9357615f93615f5a565b50049056fea2646970667358221220c6f47c49865f99357fc7f3a83dfde648490b39975e4ec4242e3bcab08caabf3664736f6c634300080f0033

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

000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000002f1f7d38e4772884b88f3ecd8b6b9facdc3191120000000000000000000000000000000000000000000000000000000000000010536572766963652052656769737472790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000144155544f4e4f4c41532d534552564943452d5631000000000000000000000000000000000000000000000000000000000000000000000000000000000000002468747470733a2f2f676174657761792e6175746f6e6f6c61732e746563682f697066732f00000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): Service Registry
Arg [1] : _symbol (string): AUTONOLAS-SERVICE-V1
Arg [2] : _baseURI (string): https://gateway.autonolas.tech/ipfs/
Arg [3] : _agentRegistry (address): 0x2F1f7D38e4772884b88f3eCd8B6b9faCdC319112

-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [3] : 0000000000000000000000002f1f7d38e4772884b88f3ecd8b6b9facdc319112
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000010
Arg [5] : 5365727669636520526567697374727900000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [7] : 4155544f4e4f4c41532d534552564943452d5631000000000000000000000000
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000024
Arg [9] : 68747470733a2f2f676174657761792e6175746f6e6f6c61732e746563682f69
Arg [10] : 7066732f00000000000000000000000000000000000000000000000000000000


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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