ETH Price: $3,320.96 (+2.74%)
 

Overview

Max Total Supply

40 AUTONOLAS-SERVICE-V1

Holders

17

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
1 AUTONOLAS-SERVICE-V1
0x0f7ff10364f1c08d52c1cbb3d3cc327cc20aaea6
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

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


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.