ETH Price: $1,935.03 (-2.18%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Create239331072025-12-03 13:06:3588 days ago1764767195IN
0x2EA68212...67F2dB143
0 ETH0.000008160.03280731
Create236674972025-10-27 8:09:11126 days ago1761552551IN
0x2EA68212...67F2dB143
0 ETH0.000613412.60792912
Deploy233975082025-09-19 13:45:11163 days ago1758289511IN
0x2EA68212...67F2dB143
0 ETH0.000216450.4560324
Register Agents233975042025-09-19 13:44:23163 days ago1758289463IN
0x2EA68212...67F2dB143
5 wei0.000094510.45666156
Register Agents233589192025-09-14 4:26:23169 days ago1757823983IN
0x2EA68212...67F2dB143
0.00000001 ETH0.000546792.64194126
Activate Registr...233589042025-09-14 4:23:23169 days ago1757823803IN
0x2EA68212...67F2dB143
0.00000001 ETH0.0001462.66211253
Create233588782025-09-14 4:18:11169 days ago1757823491IN
0x2EA68212...67F2dB143
0 ETH0.000576092.64158944
Update233577492025-09-14 0:31:35169 days ago1757809895IN
0x2EA68212...67F2dB143
0 ETH0.000010040.21384858
Activate Registr...233576792025-09-14 0:17:35169 days ago1757809055IN
0x2EA68212...67F2dB143
5 wei0.000011340.20684251
Activate Registr...233202062025-09-08 18:36:59174 days ago1757356619IN
0x2EA68212...67F2dB143
0.001 ETH0.000171443.12588149
Create233201942025-09-08 18:34:35174 days ago1757356475IN
0x2EA68212...67F2dB143
0 ETH0.000723643.07676481
Create232922402025-09-04 20:49:47178 days ago1757018987IN
0x2EA68212...67F2dB143
0 ETH0.000082760.35197267
Create232919882025-09-04 19:59:11178 days ago1757015951IN
0x2EA68212...67F2dB143
0 ETH0.000021290.464342
Deploy228019102025-06-28 9:01:59247 days ago1751101319IN
0x2EA68212...67F2dB143
0 ETH0.000982692.30224427
Register Agents228019042025-06-28 9:00:47247 days ago1751101247IN
0x2EA68212...67F2dB143
0.00000001 ETH0.000479462.31664218
Register Agents227986342025-06-27 22:04:11247 days ago1751061851IN
0x2EA68212...67F2dB143
0.00000001 ETH0.000179122.65436907
Activate Registr...227986282025-06-27 22:02:47247 days ago1751061767IN
0x2EA68212...67F2dB143
0.00000001 ETH0.000145122.64608725
Create227985382025-06-27 21:44:35247 days ago1751060675IN
0x2EA68212...67F2dB143
0 ETH0.000598252.54373664
Deploy227844882025-06-25 22:38:47249 days ago1750891127IN
0x2EA68212...67F2dB143
0 ETH0.001662633.57337856
Register Agents227844522025-06-25 22:31:35249 days ago1750890695IN
0x2EA68212...67F2dB143
0.00000001 ETH0.000779643.76703231
Activate Registr...227843532025-06-25 22:11:35249 days ago1750889495IN
0x2EA68212...67F2dB143
0.00000001 ETH0.000217773.97061101
Create227843342025-06-25 22:07:47249 days ago1750889267IN
0x2EA68212...67F2dB143
0 ETH0.000912873.8815016
Deploy226173992025-06-02 13:50:47272 days ago1748872247IN
0x2EA68212...67F2dB143
0 ETH0.002584665.5830757
Register Agents226173922025-06-02 13:49:23272 days ago1748872163IN
0x2EA68212...67F2dB143
0.00000001 ETH0.001237585.97967292
Activate Registr...226173882025-06-02 13:48:35272 days ago1748872115IN
0x2EA68212...67F2dB143
0.00000001 ETH0.000289025.26969268
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Method Block
From
To
Register Agents233975042025-09-19 13:44:23163 days ago1758289463
0x2EA68212...67F2dB143
5 wei
Register Agents233589192025-09-14 4:26:23169 days ago1757823983
0x2EA68212...67F2dB143
0.00000001 ETH
Activate Registr...233589042025-09-14 4:23:23169 days ago1757823803
0x2EA68212...67F2dB143
0.00000001 ETH
Activate Registr...233576792025-09-14 0:17:35169 days ago1757809055
0x2EA68212...67F2dB143
5 wei
Activate Registr...233202062025-09-08 18:36:59174 days ago1757356619
0x2EA68212...67F2dB143
0.001 ETH
Register Agents228019042025-06-28 9:00:47247 days ago1751101247
0x2EA68212...67F2dB143
0.00000001 ETH
Register Agents227986342025-06-27 22:04:11247 days ago1751061851
0x2EA68212...67F2dB143
0.00000001 ETH
Activate Registr...227986282025-06-27 22:02:47247 days ago1751061767
0x2EA68212...67F2dB143
0.00000001 ETH
Register Agents227844522025-06-25 22:31:35249 days ago1750890695
0x2EA68212...67F2dB143
0.00000001 ETH
Activate Registr...227843532025-06-25 22:11:35249 days ago1750889495
0x2EA68212...67F2dB143
0.00000001 ETH
Register Agents226173922025-06-02 13:49:23272 days ago1748872163
0x2EA68212...67F2dB143
0.00000001 ETH
Activate Registr...226173882025-06-02 13:48:35272 days ago1748872115
0x2EA68212...67F2dB143
0.00000001 ETH
Register Agents224563652025-05-10 23:52:59295 days ago1746921179
0x2EA68212...67F2dB143
0.005 ETH
Register Agents224559712025-05-10 22:33:23295 days ago1746916403
0x2EA68212...67F2dB143
0.005 ETH
Activate Registr...224559312025-05-10 22:25:11295 days ago1746915911
0x2EA68212...67F2dB143
0.005 ETH
Activate Registr...224551842025-05-10 19:52:47295 days ago1746906767
0x2EA68212...67F2dB143
0.001 ETH
Activate Registr...224538452025-05-10 15:20:35295 days ago1746890435
0x2EA68212...67F2dB143
0.005 ETH
Register Agents219942442025-03-07 9:55:59360 days ago1741341359
0x2EA68212...67F2dB143
1 wei
Activate Registr...219942232025-03-07 9:51:35360 days ago1741341095
0x2EA68212...67F2dB143
1 wei
Register Agents219758802025-03-04 20:20:59362 days ago1741119659
0x2EA68212...67F2dB143
1 wei
Activate Registr...219758722025-03-04 20:19:23362 days ago1741119563
0x2EA68212...67F2dB143
1 wei
Register Agents219529192025-03-01 15:29:47365 days ago1740842987
0x2EA68212...67F2dB143
0 ETH
Activate Registr...219525332025-03-01 14:12:11365 days ago1740838331
0x2EA68212...67F2dB143
0 ETH
Register Agents218825172025-02-19 19:30:59375 days ago1739993459
0x2EA68212...67F2dB143
2 wei
Activate Registr...218824852025-02-19 19:24:35375 days ago1739993075
0x2EA68212...67F2dB143
1 wei
View All Internal Transactions
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

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

Contract Source Code Verified (Exact Match)

Contract Name:
ServiceManagerToken

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 750 runs

Other Settings:
default evmVersion
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {GenericManager} from "./GenericManager.sol";
import {OperatorSignedHashes} from "./utils/OperatorSignedHashes.sol";
import "./interfaces/IService.sol";
import "./interfaces/IServiceTokenUtility.sol";

// Operator whitelist interface
interface IOperatorWhitelist {
    /// @dev Gets operator whitelisting status.
    /// @param serviceId Service Id.
    /// @param operator Operator address.
    /// @return status Whitelisting status.
    function isOperatorWhitelisted(uint256 serviceId, address operator) external view returns (bool status);
}

// Generic token interface
interface IToken {
    /// @dev Gets the owner of the token Id.
    /// @param tokenId Token Id.
    /// @return Token Id owner address.
    function ownerOf(uint256 tokenId) external view returns (address);
}

/// @title Service Manager - Periphery smart contract for managing services with custom ERC20 tokens or ETH
/// @author Aleksandr Kuperman - <aleksandr.kuperman@valory.xyz>
/// @author AL
contract ServiceManagerToken is GenericManager, OperatorSignedHashes {
    event OperatorWhitelistUpdated(address indexed operatorWhitelist);
    event CreateMultisig(address indexed multisig);

    // Service Registry address
    address public immutable serviceRegistry;
    // Service Registry Token Utility address
    address public immutable serviceRegistryTokenUtility;
    // A well-known representation of ETH as an address
    address public constant ETH_TOKEN_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
    // Bond wrapping constant
    uint96 public constant BOND_WRAPPER = 1;
    // Operator whitelist address
    address public operatorWhitelist;

    /// @dev ServiceRegistryTokenUtility constructor.
    /// @param _serviceRegistry Service Registry contract address.
    /// @param _serviceRegistryTokenUtility Service Registry Token Utility contract address.
    constructor(address _serviceRegistry, address _serviceRegistryTokenUtility, address _operatorWhitelist)
        OperatorSignedHashes("Service Manager Token", "1.1.1")
    {
        // Check for the Service Registry related contract zero addresses
        if (_serviceRegistry == address(0) || _serviceRegistryTokenUtility == address(0)) {
            revert ZeroAddress();
        }

        serviceRegistry = _serviceRegistry;
        serviceRegistryTokenUtility = _serviceRegistryTokenUtility;
        operatorWhitelist = _operatorWhitelist;
        owner = msg.sender;
    }

    /// @dev Sets the operator whitelist contract address.
    /// @param newOperatorWhitelist New operator whitelist contract address.
    function setOperatorWhitelist(address newOperatorWhitelist) external {
        // Check for the contract ownership
        if (msg.sender != owner) {
            revert OwnerOnly(msg.sender, owner);
        }

        operatorWhitelist = newOperatorWhitelist;
        emit OperatorWhitelistUpdated(newOperatorWhitelist);
    }

    /// @dev Creates a new service.
    /// @param serviceOwner Individual that creates and controls a service.
    /// @param token ERC20 token address for the security deposit, or ETH.
    /// @param configHash IPFS hash pointing to the config metadata.
    /// @param agentIds Canonical agent Ids.
    /// @param agentParams Number of agent instances and required bond to register an instance in the service.
    /// @param threshold Threshold for a multisig composed by agents.
    /// @return serviceId Created service Id.
    function create(
        address serviceOwner,
        address token,
        bytes32 configHash,
        uint32[] memory agentIds,
        IService.AgentParams[] memory agentParams,
        uint32 threshold
    ) external returns (uint256 serviceId)
    {
        // Check if the minting is paused
        if (paused) {
            revert Paused();
        }

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

        // Check for the custom ERC20 token or ETH based bond
        if (token == ETH_TOKEN_ADDRESS) {
            // Call the original ServiceRegistry contract function
            serviceId = IService(serviceRegistry).create(serviceOwner, configHash, agentIds, agentParams, threshold);
        } else {
            // Wrap agent params with just 1 WEI bond going to the original ServiceRegistry contract,
            // and actual token bonds being recorded with the ServiceRegistryTokenUtility contract
            uint256 numAgents = agentParams.length;
            uint256[] memory bonds = new uint256[](numAgents);
            for (uint256 i = 0; i < numAgents; ++i) {
                // Check for the zero bond value
                if (agentParams[i].bond == 0) {
                    revert ZeroValue();
                }

                // Copy actual bond values for each agent Id
                bonds[i] = agentParams[i].bond;
                // Wrap bonds with the BOND_WRAPPER value for the original ServiceRegistry contract
                agentParams[i].bond = BOND_WRAPPER;
            }

            // Call the original ServiceRegistry contract function
            serviceId = IService(serviceRegistry).create(serviceOwner, configHash, agentIds, agentParams, threshold);
            // Create a token-related record for the service
            IServiceTokenUtility(serviceRegistryTokenUtility).createWithToken(serviceId, token, agentIds, bonds);
        }
    }

    /// @dev Updates a service in a CRUD way.
    /// @param token ERC20 token address for the security deposit, or ETH.
    /// @param configHash IPFS hash pointing to the config metadata.
    /// @param agentIds Canonical agent Ids.
    /// @param agentParams Number of agent instances and required bond to register an instance in the service.
    /// @param threshold Threshold for a multisig composed by agents.
    /// @param serviceId Service Id to be updated.
    /// @return success True, if function executed successfully.
    function update(
        address token,
        bytes32 configHash,
        uint32[] memory agentIds,
        IService.AgentParams[] memory agentParams,
        uint32 threshold,
        uint256 serviceId
    ) external returns (bool success)
    {
        // Check for the zero address
        if (token == address(0)) {
            revert ZeroAddress();
        }

        uint256 numAgents = agentParams.length;
        if (token == ETH_TOKEN_ADDRESS) {
            // If any of the slots is a non-zero, the correspondent bond cannot be zero
            for (uint256 i = 0; i < numAgents; ++i) {
                // Check for the zero bond value
                if (agentParams[i].slots > 0 && agentParams[i].bond == 0) {
                        revert ZeroValue();
                }
            }
            // Call the original ServiceRegistry contract function
            success = IService(serviceRegistry).update(msg.sender, configHash, agentIds, agentParams, threshold, serviceId);
            // Reset the service token-based data
            // This function still needs to be called as the previous token could be a custom ERC20 token
            IServiceTokenUtility(serviceRegistryTokenUtility).resetServiceToken(serviceId);
        } else {
            // Wrap agent params with just 1 WEI bond going to the original ServiceRegistry contract,
            // and actual token bonds being recorded with the ServiceRegistryTokenUtility contract
            uint256[] memory bonds = new uint256[](numAgents);
            for (uint256 i = 0; i < numAgents; ++i) {
                // Copy actual bond values for each agent Id that has at least one slot in the updated service
                if (agentParams[i].slots > 0) {
                    // Check for the zero bond value
                    if (agentParams[i].bond == 0) {
                        revert ZeroValue();
                    }
                    bonds[i] = agentParams[i].bond;
                    // Wrap bonds with the BOND_WRAPPER value for the original ServiceRegistry contract
                    agentParams[i].bond = BOND_WRAPPER;
                }
            }

            // Call the original ServiceRegistry contract function
            success = IService(serviceRegistry).update(msg.sender, configHash, agentIds, agentParams, threshold, serviceId);
            // Update relevant data in the ServiceRegistryTokenUtility contract
            // We follow the optimistic design where existing bonds are just overwritten without a clearing
            // bond values of agent Ids that are not going to be used in the service. This is coming from the fact
            // that all the checks are done on the original ServiceRegistry side
            IServiceTokenUtility(serviceRegistryTokenUtility).createWithToken(serviceId, token, agentIds, bonds);
        }
    }

    /// @dev Activates the service and its sensitive components.
    /// @param serviceId Correspondent service Id.
    /// @return success True, if function executed successfully.
    function activateRegistration(uint256 serviceId) external payable returns (bool success) {
        // Record the actual ERC20 security deposit
        bool isTokenSecured = IServiceTokenUtility(serviceRegistryTokenUtility).activateRegistrationTokenDeposit(serviceId);

        // Activate registration in the original ServiceRegistry contract
        if (isTokenSecured) {
            // If the service Id is based on the ERC20 token, the provided value to the standard registration is 1
            success = IService(serviceRegistry).activateRegistration{value: BOND_WRAPPER}(msg.sender, serviceId);
        } else {
            // Otherwise follow the standard msg.value path
            success = IService(serviceRegistry).activateRegistration{value: msg.value}(msg.sender, serviceId);
        }
    }

    /// @dev Registers agent instances.
    /// @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(
        uint256 serviceId,
        address[] memory agentInstances,
        uint32[] memory agentIds
    ) external payable returns (bool success) {
        if (operatorWhitelist != address(0)) {
            // Check if the operator is whitelisted
            if (!IOperatorWhitelist(operatorWhitelist).isOperatorWhitelisted(serviceId, msg.sender)) {
                revert WrongOperator(serviceId);
            }
        }

        // Record the actual ERC20 bond
        bool isTokenSecured = IServiceTokenUtility(serviceRegistryTokenUtility).registerAgentsTokenDeposit(msg.sender,
            serviceId, agentIds);

        // Register agent instances in a main ServiceRegistry contract
        if (isTokenSecured) {
            // If the service Id is based on the ERC20 token, the provided value to the standard registration is 1
            // multiplied by the number of agent instances
            success = IService(serviceRegistry).registerAgents{value: agentInstances.length * BOND_WRAPPER}(msg.sender,
                serviceId, agentInstances, agentIds);
        } else {
            // Otherwise follow the standard msg.value path
            success = IService(serviceRegistry).registerAgents{value: msg.value}(msg.sender, serviceId, agentInstances, agentIds);
        }
    }

    /// @dev Creates multisig instance controlled by the set of service agent instances and deploys the 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(
        uint256 serviceId,
        address multisigImplementation,
        bytes memory data
    ) external returns (address multisig)
    {
        multisig = IService(serviceRegistry).deploy(msg.sender, serviceId, multisigImplementation, data);
        emit CreateMultisig(multisig);
    }

    /// @dev Terminates the service.
    /// @param serviceId Service Id.
    /// @return success True, if function executed successfully.
    /// @return refund Refund for the service owner.
    function terminate(uint256 serviceId) external returns (bool success, uint256 refund) {
        // Withdraw the ERC20 token if the service is token-based
        uint256 tokenRefund = IServiceTokenUtility(serviceRegistryTokenUtility).terminateTokenRefund(serviceId);

        // Terminate the service with the regular service registry routine
        (success, refund) = IService(serviceRegistry).terminate(msg.sender, serviceId);

        // If the service is token-based, the actual refund is provided via the serviceRegistryTokenUtility contract
        if (tokenRefund > 0) {
            refund = tokenRefund;
        }
    }

    /// @dev Unbonds agent instances of the operator from the service.
    /// @param serviceId Service Id.
    /// @return success True, if function executed successfully.
    /// @return refund The amount of refund returned to the operator.
    function unbond(uint256 serviceId) external returns (bool success, uint256 refund) {
        // Withdraw the ERC20 token if the service is token-based
        uint256 tokenRefund = IServiceTokenUtility(serviceRegistryTokenUtility).unbondTokenRefund(msg.sender, serviceId);

        // Unbond with the regular service registry routine
        (success, refund) = IService(serviceRegistry).unbond(msg.sender, serviceId);

        // If the service is token-based, the actual refund is provided via the serviceRegistryTokenUtility contract
        if (tokenRefund > 0) {
            refund = tokenRefund;
        }
    }

    /// @dev Unbonds agent instances of the operator by the service owner via the operator's pre-signed message hash.
    /// @notice Note that this function accounts for the operator being the EOA, or the contract that has an
    ///         isValidSignature() function that would confirm the message hash was signed by the operator contract.
    ///         Otherwise, if the message hash has been pre-approved, the corresponding map of hashes is going to
    ///         to verify the signed hash, similar to the Safe contract implementation in v1.3.0:
    ///         https://github.com/safe-global/safe-contracts/blob/186a21a74b327f17fc41217a927dea7064f74604/contracts/GnosisSafe.sol#L240-L304
    ///         Also note that only the service owner is able to call this function on behalf of the operator.
    /// @param operator Operator address that signed the unbond message hash.
    /// @param serviceId Service Id.
    /// @param signature Signature byte array associated with operator message hash signature.
    /// @return success True, if the function executed successfully.
    /// @return refund The amount of refund returned to the operator.
    function unbondWithSignature(
        address operator,
        uint256 serviceId,
        bytes memory signature
    ) external returns (bool success, uint256 refund)
    {
        // Check the service owner
        address serviceOwner = IToken(serviceRegistry).ownerOf(serviceId);
        if (msg.sender != serviceOwner) {
            revert OwnerOnly(msg.sender, serviceOwner);
        }

        // Get the (operator | serviceId) nonce for the unbond message
        // Push a pair of key defining variables into one key. Service Id or operator are not enough by themselves
        // as another service might use the operator address at the same time frame
        // operator occupies first 160 bits
        uint256 operatorService = uint256(uint160(operator));
        // serviceId occupies next 32 bits
        operatorService |= serviceId << 160;
        uint256 nonce = mapOperatorUnbondNonces[operatorService];
        // Get the unbond message hash
        bytes32 msgHash = getUnbondHash(operator, serviceOwner, serviceId, nonce);

        // Verify the signed hash against the operator address
        _verifySignedHash(operator, msgHash, signature);

        // Update corresponding nonce value
        nonce++;
        mapOperatorUnbondNonces[operatorService] = nonce;

        // Withdraw the ERC20 token if the service is token-based
        uint256 tokenRefund = IServiceTokenUtility(serviceRegistryTokenUtility).unbondTokenRefund(operator, serviceId);

        // Unbond with the regular service registry routine
        (success, refund) = IService(serviceRegistry).unbond(operator, serviceId);

        // If the service is token-based, the actual refund is provided via the serviceRegistryTokenUtility contract
        if (tokenRefund > 0) {
            refund = tokenRefund;
        }
    }

    /// @dev Registers agent instances of the operator by the service owner via the operator's pre-signed message hash.
    /// @notice Note that this function accounts for the operator being the EOA, or the contract that has an
    ///         isValidSignature() function that would confirm the message hash was signed by the operator contract.
    ///         Otherwise, if the message hash has been pre-approved, the corresponding map of hashes is going to
    ///         to verify the signed hash, similar to the Safe contract implementation in v1.3.0:
    ///         https://github.com/safe-global/safe-contracts/blob/186a21a74b327f17fc41217a927dea7064f74604/contracts/GnosisSafe.sol#L240-L304
    ///         Also note that only the service owner is able to call this function on behalf of the operator.
    /// @param operator Operator address that signed the register agents message hash.
    /// @param serviceId Service Id.
    /// @param agentInstances Agent instance addresses.
    /// @param agentIds Canonical Ids of the agent correspondent to the agent instance.
    /// @param signature Signature byte array associated with operator message hash signature.
    /// @return success True, if the the function executed successfully.
    function registerAgentsWithSignature(
        address operator,
        uint256 serviceId,
        address[] memory agentInstances,
        uint32[] memory agentIds,
        bytes memory signature
    ) external payable returns (bool success) {
        // Check the service owner
        address serviceOwner = IToken(serviceRegistry).ownerOf(serviceId);
        if (msg.sender != serviceOwner) {
            revert OwnerOnly(msg.sender, serviceOwner);
        }

        // Get the (operator | serviceId) nonce for the registerAgents message
        // Push a pair of key defining variables into one key. Service Id or operator are not enough by themselves
        // as another service might use the operator address at the same time frame
        // operator occupies first 160 bits
        uint256 operatorService = uint256(uint160(operator));
        // serviceId occupies next 32 bits as serviceId is limited by the 2^32 - 1 value
        operatorService |= serviceId << 160;
        uint256 nonce = mapOperatorRegisterAgentsNonces[operatorService];
        // Get register agents message hash
        bytes32 msgHash = getRegisterAgentsHash(operator, serviceOwner, serviceId, agentInstances, agentIds, nonce);

        // Verify the signed hash against the operator address
        _verifySignedHash(operator, msgHash, signature);

        // Update corresponding nonce value
        nonce++;
        mapOperatorRegisterAgentsNonces[operatorService] = nonce;

        // Record the actual ERC20 bond
        bool isTokenSecured = IServiceTokenUtility(serviceRegistryTokenUtility).registerAgentsTokenDeposit(operator,
            serviceId, agentIds);

        // Register agent instances in a main ServiceRegistry contract
        if (isTokenSecured) {
            // If the service Id is based on the ERC20 token, the provided value to the standard registration is 1
            // multiplied by the number of agent instances
            success = IService(serviceRegistry).registerAgents{value: agentInstances.length * BOND_WRAPPER}(operator,
                serviceId, agentInstances, agentIds);
        } else {
            // Otherwise follow the standard msg.value path
            success = IService(serviceRegistry).registerAgents{value: msg.value}(operator, serviceId, agentInstances, agentIds);
        }
    }
}

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

import "./interfaces/IErrorsRegistries.sol";

/// @title Generic Manager - Smart contract for generic registry manager template
/// @author Aleksandr Kuperman - <aleksandr.kuperman@valory.xyz>
abstract contract GenericManager is IErrorsRegistries {
    event OwnerUpdated(address indexed owner);
    event Pause(address indexed owner);
    event Unpause(address indexed owner);

    // Owner address
    address public owner;
    // Pause switch
    bool public paused;

    /// @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 Pauses the contract.
    function pause() external virtual {
        // Check for the ownership
        if (msg.sender != owner) {
            revert OwnerOnly(msg.sender, owner);
        }

        paused = true;
        emit Pause(msg.sender);
    }

    /// @dev Unpauses the contract.
    function unpause() external virtual {
        // Check for the ownership
        if (msg.sender != owner) {
            revert OwnerOnly(msg.sender, owner);
        }

        paused = false;
        emit Unpause(msg.sender);
    }
}

File 3 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();
}

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

/// @dev Required interface for the service manipulation.
interface IService{
    struct AgentParams {
        // Number of agent instances
        uint32 slots;
        // Bond per agent instance
        uint96 bond;
    }

    /// @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 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);

    /// @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 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);

    /// @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);

    /// @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);

    /// @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);

    /// @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 serviceOwner.
    function terminate(address serviceOwner, uint256 serviceId) external returns (bool success, uint256 refund);

    /// @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);
}

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

/// @dev Interface for the service registration token utility manipulation.
interface IServiceTokenUtility {
    /// @dev Creates a record with the token-related information for the specified service.
    /// @param serviceId Service Id.
    /// @param token Token address.
    /// @param agentIds Set of agent Ids.
    /// @param bonds Set of correspondent bonds.
    function createWithToken(
        uint256 serviceId,
        address token,
        uint32[] memory agentIds,
        uint256[] memory bonds
    ) external;

    /// @dev Resets a record with token and security deposit data.
    /// @param serviceId Service Id.
    function resetServiceToken(uint256 serviceId) external;

    /// @dev Deposit a token security deposit for the service registration after its activation.
    /// @param serviceId Service Id.
    /// @return isTokenSecured True if the service Id is token secured, false if ETH secured otherwise.
    function activateRegistrationTokenDeposit(uint256 serviceId) external returns (bool isTokenSecured);

    /// @dev Deposits bonded tokens from the operator during the agent instance registration.
    /// @param operator Operator address.
    /// @param serviceId Service Id.
    /// @param agentIds Set of agent Ids for corresponding agent instances opertor is registering.
    /// @return isTokenSecured True if the service Id is token secured, false if ETH secured otherwise.
    function registerAgentsTokenDeposit(
        address operator,
        uint256 serviceId,
        uint32[] memory agentIds
    ) external returns (bool isTokenSecured);

    /// @dev Withdraws a token security deposit to the service owner after the service termination.
    /// @param serviceId Service Id.
    /// @return securityRefund Returned token security deposit, or zero if the service is ETH-secured.
    function terminateTokenRefund(uint256 serviceId) external returns (uint256 securityRefund);

    /// @dev Withdraws bonded tokens to the operator during the unbond phase.
    /// @param operator Operator address.
    /// @param serviceId Service Id.
    /// @return refund Returned bonded token amount, or zero if the service is ETH-secured.
    function unbondTokenRefund(address operator, uint256 serviceId) external returns (uint256 refund);

    /// @dev Gets service token secured status.
    /// @param serviceId Service Id.
    /// @return True if the service Id is token secured.
    function isTokenSecuredService(uint256 serviceId) external view returns (bool);
}

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

interface ISignatureValidator {
    /// @dev Should return whether the signature provided is valid for the provided hash.
    /// @notice MUST return the bytes4 magic value 0x1626ba7e when function passes.
    ///         MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5).
    ///         MUST allow external calls.
    /// @param hash Hash of the data to be signed.
    /// @param signature Signature byte array associated with hash.
    /// @return magicValue bytes4 magic value.
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

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

/// @dev Incorrect signature length provided.
/// @param signature Signature bytes.
/// @param provided Provided signature length.
/// @param expected Expected signature length.
error IncorrectSignatureLength(bytes signature, uint256 provided, uint256 expected);

/// @dev Hash is not validated.
/// @param operator Operator contract address.
/// @param msgHash Message hash.
/// @param signature Signature bytes associated with the message hash.
error HashNotValidated(address operator, bytes32 msgHash, bytes signature);

/// @dev Hash is not approved.
/// @param operator Operator address.
/// @param msgHash Message hash.
/// @param signature Signature bytes associated with the message hash.
error HashNotApproved(address operator, bytes32 msgHash, bytes signature);

/// @dev Obtained wrong operator address.
/// @param provided Provided address.
/// @param expected Expected address.
error WrongOperatorAddress(address provided, address expected);

/// @title OperatorSignedHashes - Smart contract for managing operator signed hashes
/// @author AL
/// @author Aleksandr Kuperman - <aleksandr.kuperman@valory.xyz>
contract OperatorSignedHashes {
    event OperatorHashApproved(address indexed operator, bytes32 hash);

    // Value for the contract signature validation: bytes4(keccak256("isValidSignature(bytes32,bytes)")
    bytes4 constant internal MAGIC_VALUE = 0x1626ba7e;
    // Domain separator type hash
    bytes32 public constant DOMAIN_SEPARATOR_TYPE_HASH =
        keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
    // Unbond type hash
    bytes32 public constant UNBOND_TYPE_HASH =
        keccak256("Unbond(address operator,address serviceOwner,uint256 serviceId,uint256 nonce)");
    // Register agents type hash
    bytes32 public constant REGISTER_AGENTS_TYPE_HASH =
        keccak256("RegisterAgents(address operator,address serviceOwner,uint256 serviceId,bytes32 agentsData,uint256 nonce)");
    // Original domain separator value
    bytes32 public immutable domainSeparator;
    // Original chain Id
    uint256 public immutable chainId;
    // Name hash
    bytes32 public immutable nameHash;
    // Version hash
    bytes32 public immutable versionHash;

    // Name of a signing domain
    string public name;
    // Version of a signing domain
    string public version;

    // Map of operator address and serviceId => unbond nonce
    mapping(uint256 => uint256) public mapOperatorUnbondNonces;
    // Map of operator address and serviceId => register agents nonce
    mapping(uint256 => uint256) public mapOperatorRegisterAgentsNonces;
    // Mapping operator address => approved hashes status
    mapping(address => mapping(bytes32 => bool)) public mapOperatorApprovedHashes;

    /// @dev Contract constructor.
    /// @param _name Name of a signing domain.
    /// @param _version Version of a signing domain.
    constructor(string memory _name, string memory _version) {
        name = _name;
        version = _version;
        nameHash = keccak256(bytes(_name));
        versionHash = keccak256(bytes(_version));
        chainId = block.chainid;
        domainSeparator = _computeDomainSeparator();
    }

    /// @dev Verifies provided message hash against its signature.
    /// @param operator Operator address.
    /// @param msgHash Message hash.
    /// @param signature Signature bytes associated with the signed message hash.
    function _verifySignedHash(address operator, bytes32 msgHash, bytes memory signature) internal view {
        // Check for the operator zero address
        if (operator == address(0)) {
            revert ZeroOperatorAddress();
        }

        // Check for the signature length
        if (signature.length != 65) {
            revert IncorrectSignatureLength(signature, signature.length, 65);
        }

        // Decode the signature
        uint8 v = uint8(signature[64]);
        // For the correct ecrecover() function execution, the v value must be set to {0,1} + 27
        // Although v in a very rare case can be equal to {2,3} (with a probability of 3.73e-37%)
        // If v is set to just 0 or 1 when signing  by the EOA, it is most likely signed by the ledger and must be adjusted
        if (v < 4 && operator.code.length == 0) {
            // In case of a non-contract, adjust v to follow the standard ecrecover case
            v += 27;
        }
        bytes32 r;
        bytes32 s;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            r := mload(add(signature, 32))
            s := mload(add(signature, 64))
        }

        address recOperator;
        // Go through signature cases based on the value of v
        if (v == 4) {
            // Contract signature case, where the address of the contract is encoded into r
            recOperator = address(uint160(uint256(r)));

            // Check for the signature validity in the contract
            if (ISignatureValidator(recOperator).isValidSignature(msgHash, signature) != MAGIC_VALUE) {
                revert HashNotValidated(recOperator, msgHash, signature);
            }
        } else if (v == 5) {
            // Case of an approved hash, where the address of the operator is encoded into r
            recOperator = address(uint160(uint256(r)));

            // Hashes have been pre-approved by the operator via a separate message, see operatorApproveHash() function
            if (!mapOperatorApprovedHashes[recOperator][msgHash]) {
                revert HashNotApproved(recOperator, msgHash, signature);
            }
        } else {
            // Case of ecrecover with the message hash for EOA signatures
            recOperator = ecrecover(msgHash, v, r, s);
        }

        // Final check is for the operator address itself
        if (recOperator != operator) {
            revert WrongOperatorAddress(recOperator, operator);
        }
    }

    /// @dev Approves message hash for the operator address.
    /// @param hash Provided message hash to approve.
    function operatorApproveHash(bytes32 hash) external {
        mapOperatorApprovedHashes[msg.sender][hash] = true;
        emit OperatorHashApproved(msg.sender, hash);
    }

    /// @dev Computes domain separator hash.
    /// @return Hash of the domain separator based on its name, version, chain Id and contract address.
    function _computeDomainSeparator() internal view returns (bytes32) {
        return keccak256(
            abi.encode(
                DOMAIN_SEPARATOR_TYPE_HASH,
                nameHash,
                versionHash,
                block.chainid,
                address(this)
            )
        );
    }

    /// @dev Gets the already computed domain separator of recomputes one if the chain Id is different.
    /// @return Original or recomputed domain separator.
    function getDomainSeparator() public view returns (bytes32) {
        return block.chainid == chainId ? domainSeparator : _computeDomainSeparator();
    }

    /// @dev Gets the unbond message hash for the operator.
    /// @param operator Operator address.
    /// @param serviceOwner Service owner address.
    /// @param serviceId Service Id.
    /// @param nonce Nonce for the unbond message from the pair of (operator | service Id).
    /// @return Computed message hash.
    function getUnbondHash(
        address operator,
        address serviceOwner,
        uint256 serviceId,
        uint256 nonce
    ) public view returns (bytes32)
    {
        return keccak256(
            abi.encodePacked(
                "\x19\x01",
                getDomainSeparator(),
                keccak256(
                    abi.encode(
                        UNBOND_TYPE_HASH,
                        operator,
                        serviceOwner,
                        serviceId,
                        nonce
                    )
                )
            )
        );
    }

    /// @dev Gets the register agents message hash for the operator.
    /// @param operator Operator address.
    /// @param serviceOwner Service owner address.
    /// @param serviceId Service Id.
    /// @param agentInstances Agent instance addresses operator is going to register.
    /// @param agentIds Agent Ids corresponding to each agent instance address.
    /// @param nonce Nonce for the register agents message from the pair of (operator | service Id).
    /// @return Computed message hash.
    function getRegisterAgentsHash(
        address operator,
        address serviceOwner,
        uint256 serviceId,
        address[] memory agentInstances,
        uint32[] memory agentIds,
        uint256 nonce
    ) public view returns (bytes32)
    {
        return keccak256(
            abi.encodePacked(
                "\x19\x01",
                getDomainSeparator(),
                keccak256(
                    abi.encode(
                        REGISTER_AGENTS_TYPE_HASH,
                        operator,
                        serviceOwner,
                        serviceId,
                        keccak256(abi.encode(agentInstances, agentIds)),
                        nonce
                    )
                )
            )
        );
    }

    /// @dev Checks if the hash provided by the operator is approved.
    /// @param operator Operator address.
    /// @param hash Message hash.
    /// @return True, if the hash provided by the operator is approved.
    function isOperatorHashApproved(address operator, bytes32 hash) external view returns (bool) {
        return mapOperatorApprovedHashes[operator][hash];
    }

    /// @dev Gets the (operator | service Id) nonce for the unbond message data.
    /// @param operator Operator address.
    /// @param serviceId Service Id.
    /// @return nonce Obtained nonce.
    function getOperatorUnbondNonce(address operator, uint256 serviceId) external view returns (uint256 nonce) {
        // operator occupies first 160 bits
        uint256 operatorService = uint256(uint160(operator));
        // serviceId occupies next 32 bits as serviceId is limited by the 2^32 - 1 value
        operatorService |= serviceId << 160;
        nonce = mapOperatorUnbondNonces[operatorService];
    }

    /// @dev Gets the (operator | service Id) nonce for the register agents message data.
    /// @param operator Operator address.
    /// @param serviceId Service Id.
    /// @return nonce Obtained nonce.
    function getOperatorRegisterAgentsNonce(address operator, uint256 serviceId) external view returns (uint256 nonce) {
        // operator occupies first 160 bits
        uint256 operatorService = uint256(uint160(operator));
        // serviceId occupies next 32 bits as serviceId is limited by the 2^32 - 1 value
        operatorService |= serviceId << 160;
        nonce = mapOperatorRegisterAgentsNonces[operatorService];
    }
}

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

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_serviceRegistry","type":"address"},{"internalType":"address","name":"_serviceRegistryTokenUtility","type":"address"},{"internalType":"address","name":"_operatorWhitelist","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":"address","name":"operator","type":"address"},{"internalType":"bytes32","name":"msgHash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"HashNotApproved","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes32","name":"msgHash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"HashNotValidated","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":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"provided","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"IncorrectSignatureLength","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":"address","name":"provided","type":"address"},{"internalType":"address","name":"expected","type":"address"}],"name":"WrongOperatorAddress","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":"ZeroOperatorAddress","type":"error"},{"inputs":[],"name":"ZeroValue","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"multisig","type":"address"}],"name":"CreateMultisig","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"OperatorHashApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operatorWhitelist","type":"address"}],"name":"OperatorWhitelistUpdated","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":"owner","type":"address"}],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"Unpause","type":"event"},{"inputs":[],"name":"BOND_WRAPPER","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR_TYPE_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETH_TOKEN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REGISTER_AGENTS_TYPE_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNBOND_TYPE_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"activateRegistration","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"changeOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"serviceOwner","type":"address"},{"internalType":"address","name":"token","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 IService.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":"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":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDomainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"getOperatorRegisterAgentsNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"}],"name":"getOperatorUnbondNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"serviceOwner","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"},{"internalType":"address[]","name":"agentInstances","type":"address[]"},{"internalType":"uint32[]","name":"agentIds","type":"uint32[]"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"getRegisterAgentsHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"serviceOwner","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"getUnbondHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"isOperatorHashApproved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"mapOperatorApprovedHashes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"mapOperatorRegisterAgentsNonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"mapOperatorUnbondNonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nameHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"operatorApproveHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"operatorWhitelist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"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":"operator","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"},{"internalType":"address[]","name":"agentInstances","type":"address[]"},{"internalType":"uint32[]","name":"agentIds","type":"uint32[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"registerAgentsWithSignature","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"serviceRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"serviceRegistryTokenUtility","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOperatorWhitelist","type":"address"}],"name":"setOperatorWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"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":"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":"operator","type":"address"},{"internalType":"uint256","name":"serviceId","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"unbondWithSignature","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"refund","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","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 IService.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"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"versionHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"}]

6101406040523480156200001257600080fd5b506040516200365e3803806200365e8339810160408190526200003591620001cf565b6040518060400160405280601581526020017f53657276696365204d616e6167657220546f6b656e000000000000000000000081525060405180604001604052806005815260200164312e312e3160d81b81525081600190816200009a9190620002be565b506002620000a98282620002be565b50815160208084019190912060c05281519082012060e0524660a0526200013160c0805160e051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201526000910160405160208183030381529060405280519060200120905090565b60805250506001600160a01b03831615806200015457506001600160a01b038216155b15620001735760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b03928316610100529082166101205260068054919092166001600160a01b03199182161790915560008054909116331790556200038a565b80516001600160a01b0381168114620001ca57600080fd5b919050565b600080600060608486031215620001e557600080fd5b620001f084620001b2565b92506200020060208501620001b2565b91506200021060408501620001b2565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200024457607f821691505b6020821081036200026557634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002b957600081815260208120601f850160051c81016020861015620002945750805b601f850160051c820191505b81811015620002b557828155600101620002a0565b5050505b505050565b81516001600160401b03811115620002da57620002da62000219565b620002f281620002eb84546200022f565b846200026b565b602080601f8311600181146200032a5760008415620003115750858301515b600019600386901b1c1916600185901b178555620002b5565b600085815260208120601f198616915b828110156200035b578886015182559484019460019091019084016200033a565b50858210156200037a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161010051610120516131b9620004a56000396000818161042001528181610bc301528181610dcb01528181611030015281816111ec01528181611532015281816119a101528181611c0701528181611d420152612201015260008181610749015281816109c401528181610aa301528181610c4701528181610d0f01528181610e5701528181610ee8015281816110c80152818161127d01528181611318015281816115e00152818161190601528181611b6b01528181611dc801528181611e9001528181611faa015261216701526000818161033c01526122ea01526000818161083901526122c2015260008181610699015261226e0152600081816108a1015261234301526131b96000f3fe6080604052600436106102a05760003560e01c8063757b11561161016e578063cbcf252a116100cb578063e5da07531161007f578063f172a4ce11610064578063f172a4ce14610827578063f5dcb7bb1461085b578063f698da251461088f57600080fd5b8063e5da0753146107f2578063ed24911d1461081257600080fd5b8063d03ca40a116100b0578063d03ca40a1461078b578063dc1d95251461079e578063e42cdd7c146107d257600080fd5b8063cbcf252a14610737578063cbf994f81461076b57600080fd5b80639488791111610122578063a2e2ad7e11610107578063a2e2ad7e146106bb578063a6a7187f146106f7578063a6f9dae11461071757600080fd5b806394887911146106535780639a8a05921461068757600080fd5b80638456cb59116101535780638456cb59146105f15780638a39fa16146106065780638da5cb5b1461063357600080fd5b8063757b1156146105b15780637a828b28146105d157600080fd5b806328f223421161021c5780635405ecb9116101d057806356bda507116101b557806356bda50714610543578063599be46f146105705780635c975abb1461059057600080fd5b80635405ecb9146104f257806354fd4d501461052e57600080fd5b80633f4ba83a116102015780633f4ba83a1461049d57806341b60677146104b25780634d5a5827146104df57600080fd5b806328f22342146104425780633af5d04e1461046257600080fd5b80631878d1f11161027357806321561bfc1161025857806321561bfc146103b757806327de9e32146103d7578063287140511461040e57600080fd5b80631878d1f11461036c5780631ee81fb51461039457600080fd5b806306fdde03146102a557806307a3e0a8146102d05780630d0d57a8146102f2578063152b5c0f1461032a575b600080fd5b3480156102b157600080fd5b506102ba6108c3565b6040516102c79190612620565b60405180910390f35b3480156102dc57600080fd5b506102f06102eb36600461263a565b610951565b005b3480156102fe57600080fd5b5061031261030d36600461274b565b6109aa565b6040516001600160a01b0390911681526020016102c7565b34801561033657600080fd5b5061035e7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016102c7565b34801561037857600080fd5b5061031273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b6103a76103a23660046128ac565b610a80565b60405190151581526020016102c7565b3480156103c357600080fd5b50600654610312906001600160a01b031681565b3480156103e357600080fd5b506103f76103f236600461263a565b610da0565b6040805192151583526020830191909152016102c7565b34801561041a57600080fd5b506103127f000000000000000000000000000000000000000000000000000000000000000081565b34801561044e57600080fd5b506103f761045d366004612951565b610ee1565b34801561046e57600080fd5b506103a761047d366004612994565b600560209081526000928352604080842090915290825290205460ff1681565b3480156104a957600080fd5b506102f0611152565b3480156104be57600080fd5b5061035e6104cd36600461263a565b60046020526000908152604090205481565b6103a76104ed36600461263a565b6111c9565b3480156104fe57600080fd5b5061035e61050d366004612994565b60a01b6001600160a01b039091161760009081526003602052604090205490565b34801561053a57600080fd5b506102ba611398565b34801561054f57600080fd5b50610558600181565b6040516001600160601b0390911681526020016102c7565b34801561057c57600080fd5b506102f061058b3660046129c0565b6113a5565b34801561059c57600080fd5b506000546103a790600160a01b900460ff1681565b3480156105bd57600080fd5b5061035e6105cc3660046129dd565b61143c565b3480156105dd57600080fd5b506103f76105ec36600461263a565b61152b565b3480156105fd57600080fd5b506102f0611617565b34801561061257600080fd5b5061035e61062136600461263a565b60036020526000908152604090205481565b34801561063f57600080fd5b50600054610312906001600160a01b031681565b34801561065f57600080fd5b5061035e7f92b2008d2a99f26809ac9d1989fe92334aa84124767331997ba0eec16050ecf481565b34801561069357600080fd5b5061035e7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106c757600080fd5b5061035e6106d6366004612994565b60a01b6001600160a01b039091161760009081526004602052604090205490565b34801561070357600080fd5b5061035e610712366004612a78565b611694565b34801561072357600080fd5b506102f06107323660046129c0565b611750565b34801561074357600080fd5b506103127f000000000000000000000000000000000000000000000000000000000000000081565b34801561077757600080fd5b506103a7610786366004612b5a565b61180c565b6103a7610799366004612bf3565b611c81565b3480156107aa57600080fd5b5061035e7fde64b4c9fac43e1615e938b03573b078604f57b4d2e78d3a27d7b20ba017e12681565b3480156107de57600080fd5b5061035e6107ed366004612c56565b611f1b565b3480156107fe57600080fd5b506103a761080d366004612994565b61223c565b34801561081e57600080fd5b5061035e61226a565b34801561083357600080fd5b5061035e7f000000000000000000000000000000000000000000000000000000000000000081565b34801561086757600080fd5b5061035e7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b34801561089b57600080fd5b5061035e7f000000000000000000000000000000000000000000000000000000000000000081565b600180546108d090612cf8565b80601f01602080910402602001604051908101604052809291908181526020018280546108fc90612cf8565b80156109495780601f1061091e57610100808354040283529160200191610949565b820191906000526020600020905b81548152906001019060200180831161092c57829003601f168201915b505050505081565b336000818152600560209081526040808320858452825291829020805460ff1916600117905590518381527f85eb1f050732417c0566422b6004a6c5cbded9ded1a406de04060719af52a13a910160405180910390a250565b60405163f908bc7760e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f908bc77906109ff903390889088908890600401612d2c565b6020604051808303816000875af1158015610a1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a429190612d5e565b6040519091506001600160a01b038216907fec97633905b1dbe9773a7536e9a986dcf89803e1193934b7b6d76587c68beb4090600090a29392505050565b6040516331a9108f60e11b81526004810185905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015610aea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0e9190612d5e565b9050336001600160a01b03821614610b4f5760405163521eb56d60e11b81523360048201526001600160a01b03821660248201526044015b60405180910390fd5b60a086901b6001600160a01b0388161760008181526004602052604081205490610b7d8a858b8b8b8761143c565b9050610b8a8a8288612365565b81610b9481612d91565b60008581526004602081905260408083208490555163dc4f8bc560e01b81529295509092506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163dc4f8bc591610bfa918f918f918e9101612deb565b6020604051808303816000875af1158015610c19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3d9190612e2c565b90508015610cf8577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663dff7672460016001600160601b03168b51610c8b9190612e47565b8d8d8d8d6040518663ffffffff1660e01b8152600401610cae9493929190612e97565b60206040518083038185885af1158015610ccc573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610cf19190612e2c565b9550610d92565b6040516337fdd9c960e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063dff76724903490610d4c908f908f908f908f90600401612e97565b60206040518083038185885af1158015610d6a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610d8f9190612e2c565b95505b505050505095945050505050565b60405163161e984960e31b815233600482015260248101829052600090819081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b0f4c248906044016020604051808303816000875af1158015610e14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e389190612edc565b6040516352e82ce560e11b8152336004820152602481018690529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a5d059ca906044015b60408051808303816000875af1158015610ea8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ecc9190612ef5565b90935091508015610edb578091505b50915091565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636352211e866040518263ffffffff1660e01b8152600401610f3491815260200190565b602060405180830381865afa158015610f51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f759190612d5e565b9050336001600160a01b03821614610fb15760405163521eb56d60e11b81523360048201526001600160a01b0382166024820152604401610b46565b60a085901b6001600160a01b0387161760008181526003602052604081205490610fdd89858a85611694565b9050610fea898289612365565b81610ff481612d91565b6000858152600360205260408082208390555163161e984960e31b81526001600160a01b038d81166004830152602482018d90529295509092507f00000000000000000000000000000000000000000000000000000000000000009091169063b0f4c248906044016020604051808303816000875af115801561107b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109f9190612edc565b6040516352e82ce560e11b81526001600160a01b038c81166004830152602482018c90529192507f00000000000000000000000000000000000000000000000000000000000000009091169063a5d059ca9060440160408051808303816000875af1158015611112573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111369190612ef5565b90975095508015611145578095505b5050505050935093915050565b6000546001600160a01b031633146111925760005460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610b46565b6000805460ff60a01b1916815560405133917faeb196d352664784d1900b0e7414a8face7d29f4dae8c4b0cf68ed477423bbf491a2565b60405163542db44960e01b81526004810182905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063542db449906024016020604051808303816000875af1158015611235573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112599190612e2c565b905080156112fc5760405163388fdbed60e21b8152336004820152602481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e23f6fb49060019060440160206040518083038185885af11580156112d0573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906112f59190612e2c565b9150611392565b60405163388fdbed60e21b8152336004820152602481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e23f6fb490349060440160206040518083038185885af115801561136a573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061138f9190612e2c565b91505b50919050565b600280546108d090612cf8565b6000546001600160a01b031633146113e55760005460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610b46565b6006805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517ff8e76e8a7c35558598a944d509f1ed32b104e77b1098ef1dfa5b97b86b09df8f90600090a250565b600061144661226a565b7fde64b4c9fac43e1615e938b03573b078604f57b4d2e78d3a27d7b20ba017e126888888888860405160200161147d929190612f21565b60408051601f198184030181528282528051602091820120908301969096526001600160a01b0394851690820152929091166060830152608082015260a081019190915260c0810184905260e0016040516020818303038152906040528051906020012060405160200161150892919061190160f01b81526002810192909252602282015260420190565b6040516020818303038152906040528051906020012090505b9695505050505050565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166325e1afc3856040518263ffffffff1660e01b815260040161157e91815260200190565b6020604051808303816000875af115801561159d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c19190612edc565b60405163ccc9305d60e01b8152336004820152602481018690529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ccc9305d90604401610e8a565b6000546001600160a01b031633146116575760005460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610b46565b6000805460ff60a01b1916600160a01b17815560405133917f5ee71a369c8672edded508e624ffc9257fa1ae6886ef32905c18e60196bca39991a2565b600061169e61226a565b604080517f92b2008d2a99f26809ac9d1989fe92334aa84124767331997ba0eec16050ecf460208201526001600160a01b038089169282019290925290861660608201526080810185905260a0810184905260c0016040516020818303038152906040528051906020012060405160200161173092919061190160f01b81526002810192909252602282015260420190565b604051602081830303815290604052805190602001209050949350505050565b6000546001600160a01b031633146117905760005460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610b46565b6001600160a01b0381166117b75760405163d92e233d60e01b815260040160405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038316908117825560405190917f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b91a250565b60006001600160a01b0387166118355760405163d92e233d60e01b815260040160405180910390fd5b835173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03891601611a0a5760005b818110156118ee57600086828151811061187b5761187b612f46565b60200260200101516000015163ffffffff161180156118c057508581815181106118a7576118a7612f46565b6020026020010151602001516001600160601b03166000145b156118de57604051637c946ed760e01b815260040160405180910390fd5b6118e781612d91565b905061185f565b5060405163197f329f60e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cbf994f8906119459033908b908b908b908b908b90600401612fa6565b6020604051808303816000875af1158015611964573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119889190612e2c565b604051630be6cc4b60e31b8152600481018590529092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635f36625890602401600060405180830381600087803b1580156119ed57600080fd5b505af1158015611a01573d6000803e3d6000fd5b50505050611c76565b60008167ffffffffffffffff811115611a2557611a2561266b565b604051908082528060200260200182016040528015611a4e578160200160208202803683370190505b50905060005b82811015611b53576000878281518110611a7057611a70612f46565b60200260200101516000015163ffffffff161115611b4357868181518110611a9a57611a9a612f46565b6020026020010151602001516001600160601b0316600003611acf57604051637c946ed760e01b815260040160405180910390fd5b868181518110611ae157611ae1612f46565b6020026020010151602001516001600160601b0316828281518110611b0857611b08612f46565b6020026020010181815250506001878281518110611b2857611b28612f46565b6020908102919091018101516001600160601b039092169101525b611b4c81612d91565b9050611a54565b5060405163197f329f60e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cbf994f890611baa9033908c908c908c908c908c90600401612fa6565b6020604051808303816000875af1158015611bc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bed9190612e2c565b6040516338f3a6a160e21b81529093506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e3ce9a8490611c429087908d908c908790600401612ffc565b600060405180830381600087803b158015611c5c57600080fd5b505af1158015611c70573d6000803e3d6000fd5b50505050505b509695505050505050565b6006546000906001600160a01b031615611d28576006546040516356a7b60760e01b8152600481018690523360248201526001600160a01b03909116906356a7b60790604401602060405180830381865afa158015611ce4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d089190612e2c565b611d28576040516322ddebd960e21b815260048101859052602401610b46565b60405163dc4f8bc560e01b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063dc4f8bc590611d7b90339089908890600401612deb565b6020604051808303816000875af1158015611d9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dbe9190612e2c565b90508015611e79577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663dff7672460016001600160601b03168651611e0c9190612e47565b338888886040518663ffffffff1660e01b8152600401611e2f9493929190612e97565b60206040518083038185885af1158015611e4d573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611e729190612e2c565b9150611f13565b6040516337fdd9c960e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063dff76724903490611ecd9033908a908a908a90600401612e97565b60206040518083038185885af1158015611eeb573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611f109190612e2c565b91505b509392505050565b60008054600160a01b900460ff1615611f47576040516313d0ff5960e31b815260040160405180910390fd5b6001600160a01b038616611f6e5760405163d92e233d60e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038716016120315760405163fbdeb3d760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063fbdeb3d790611fe7908a908990899089908990600401613067565b6020604051808303816000875af1158015612006573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202a9190612edc565b9050611521565b825160008167ffffffffffffffff81111561204e5761204e61266b565b604051908082528060200260200182016040528015612077578160200160208202803683370190505b50905060005b8281101561214f5785818151811061209757612097612f46565b6020026020010151602001516001600160601b03166000036120cc57604051637c946ed760e01b815260040160405180910390fd5b8581815181106120de576120de612f46565b6020026020010151602001516001600160601b031682828151811061210557612105612f46565b602002602001018181525050600186828151811061212557612125612f46565b6020908102919091018101516001600160601b0390921691015261214881612d91565b905061207d565b5060405163fbdeb3d760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063fbdeb3d7906121a4908c908b908b908b908b90600401613067565b6020604051808303816000875af11580156121c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e79190612edc565b6040516338f3a6a160e21b81529093506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e3ce9a8490611c429086908c908b908790600401612ffc565b6001600160a01b038216600090815260056020908152604080832084845290915290205460ff165b92915050565b60007f000000000000000000000000000000000000000000000000000000000000000046146123405761233b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b6001600160a01b03831661238c5760405163e63f571f60e01b815260040160405180910390fd5b80516041146123b5578051604051631d9f5a5f60e01b8152610b469183916041906004016130ba565b6000816040815181106123ca576123ca612f46565b016020015160f81c90506004811080156123ec57506001600160a01b0384163b155b156123ff576123fc601b826130df565b90505b60208201516040830151600060ff84166004036124d45750604051630b135d3f60e11b80825283916001600160a01b03831690631626ba7e90612448908a908a906004016130f8565b602060405180830381865afa158015612465573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124899190613119565b7fffffffff0000000000000000000000000000000000000000000000000000000016146124cf5780868660405163694d54dd60e01b8152600401610b469392919061315b565b61258c565b8360ff1660050361252c57506001600160a01b0382166000908152600560209081526040808320888452909152902054829060ff166124cf578086866040516312cf832560e01b8152600401610b469392919061315b565b60408051600081526020810180835288905260ff861691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa15801561257f573d6000803e3d6000fd5b5050506020604051035190505b866001600160a01b0316816001600160a01b0316146125d15760405163a806216d60e01b81526001600160a01b03808316600483015288166024820152604401610b46565b50505050505050565b6000815180845260005b81811015612600576020818501810151868301820152016125e4565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061263360208301846125da565b9392505050565b60006020828403121561264c57600080fd5b5035919050565b6001600160a01b038116811461266857600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156126a4576126a461266b565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156126d3576126d361266b565b604052919050565b600082601f8301126126ec57600080fd5b813567ffffffffffffffff8111156127065761270661266b565b612719601f8201601f19166020016126aa565b81815284602083860101111561272e57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561276057600080fd5b83359250602084013561277281612653565b9150604084013567ffffffffffffffff81111561278e57600080fd5b61279a868287016126db565b9150509250925092565b600067ffffffffffffffff8211156127be576127be61266b565b5060051b60200190565b600082601f8301126127d957600080fd5b813560206127ee6127e9836127a4565b6126aa565b82815260059290921b8401810191818101908684111561280d57600080fd5b8286015b84811015611c7657803561282481612653565b8352918301918301612811565b803563ffffffff8116811461284557600080fd5b919050565b600082601f83011261285b57600080fd5b8135602061286b6127e9836127a4565b82815260059290921b8401810191818101908684111561288a57600080fd5b8286015b84811015611c765761289f81612831565b835291830191830161288e565b600080600080600060a086880312156128c457600080fd5b85356128cf81612653565b945060208601359350604086013567ffffffffffffffff808211156128f357600080fd5b6128ff89838a016127c8565b9450606088013591508082111561291557600080fd5b61292189838a0161284a565b9350608088013591508082111561293757600080fd5b50612944888289016126db565b9150509295509295909350565b60008060006060848603121561296657600080fd5b833561297181612653565b925060208401359150604084013567ffffffffffffffff81111561278e57600080fd5b600080604083850312156129a757600080fd5b82356129b281612653565b946020939093013593505050565b6000602082840312156129d257600080fd5b813561263381612653565b60008060008060008060c087890312156129f657600080fd5b8635612a0181612653565b95506020870135612a1181612653565b945060408701359350606087013567ffffffffffffffff80821115612a3557600080fd5b612a418a838b016127c8565b94506080890135915080821115612a5757600080fd5b50612a6489828a0161284a565b92505060a087013590509295509295509295565b60008060008060808587031215612a8e57600080fd5b8435612a9981612653565b93506020850135612aa981612653565b93969395505050506040820135916060013590565b600082601f830112612acf57600080fd5b81356020612adf6127e9836127a4565b82815260069290921b84018101918181019086841115612afe57600080fd5b8286015b84811015611c765760408189031215612b1b5760008081fd5b612b23612681565b612b2c82612831565b8152848201356001600160601b0381168114612b485760008081fd5b81860152835291830191604001612b02565b60008060008060008060c08789031215612b7357600080fd5b8635612b7e81612653565b955060208701359450604087013567ffffffffffffffff80821115612ba257600080fd5b612bae8a838b0161284a565b95506060890135915080821115612bc457600080fd5b50612bd189828a01612abe565b935050612be060808801612831565b915060a087013590509295509295509295565b600080600060608486031215612c0857600080fd5b83359250602084013567ffffffffffffffff80821115612c2757600080fd5b612c33878388016127c8565b93506040860135915080821115612c4957600080fd5b5061279a8682870161284a565b60008060008060008060c08789031215612c6f57600080fd5b8635612c7a81612653565b95506020870135612c8a81612653565b945060408701359350606087013567ffffffffffffffff80821115612cae57600080fd5b612cba8a838b0161284a565b94506080890135915080821115612cd057600080fd5b50612cdd89828a01612abe565b925050612cec60a08801612831565b90509295509295509295565b600181811c90821680612d0c57607f821691505b60208210810361139257634e487b7160e01b600052602260045260246000fd5b60006001600160a01b0380871683528560208401528085166040840152506080606083015261152160808301846125da565b600060208284031215612d7057600080fd5b815161263381612653565b634e487b7160e01b600052601160045260246000fd5b600060018201612da357612da3612d7b565b5060010190565b600081518084526020808501945080840160005b83811015612de057815163ffffffff1687529582019590820190600101612dbe565b509495945050505050565b6001600160a01b0384168152826020820152606060408201526000612e136060830184612daa565b95945050505050565b8051801515811461284557600080fd5b600060208284031215612e3e57600080fd5b61263382612e1c565b808202811582820484141761226457612264612d7b565b600081518084526020808501945080840160005b83811015612de05781516001600160a01b031687529582019590820190600101612e72565b6001600160a01b0385168152836020820152608060408201526000612ebf6080830185612e5e565b8281036060840152612ed18185612daa565b979650505050505050565b600060208284031215612eee57600080fd5b5051919050565b60008060408385031215612f0857600080fd5b612f1183612e1c565b9150602083015190509250929050565b604081526000612f346040830185612e5e565b8281036020840152611f108185612daa565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b83811015612de0578151805163ffffffff1688528301516001600160601b03168388015260409096019590820190600101612f70565b6001600160a01b038716815285602082015260c060408201526000612fce60c0830187612daa565b8281036060840152612fe08187612f5c565b63ffffffff959095166080840152505060a00152949350505050565b848152600060206001600160a01b03861681840152608060408401526130256080840186612daa565b838103606085015284518082528286019183019060005b818110156130585783518352928401929184019160010161303c565b50909998505050505050505050565b6001600160a01b038616815284602082015260a06040820152600061308f60a0830186612daa565b82810360608401526130a18186612f5c565b91505063ffffffff831660808301529695505050505050565b6060815260006130cd60608301866125da565b60208301949094525060400152919050565b60ff818116838216019081111561226457612264612d7b565b82815260406020820152600061311160408301846125da565b949350505050565b60006020828403121561312b57600080fd5b81517fffffffff000000000000000000000000000000000000000000000000000000008116811461263357600080fd5b6001600160a01b0384168152826020820152606060408201526000612e1360608301846125da56fea2646970667358221220f2d50ac7cf109448ada9fff306a728e5251fe66a1c6e6ec31ba9ad713c2ad83964736f6c6343000813003300000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca0000000000000000000000003fb926116d454b95c669b6bf2e7c3bad8d19affa00000000000000000000000042042799b0de38add2a70dc996f69f98e1a85260

Deployed Bytecode

0x6080604052600436106102a05760003560e01c8063757b11561161016e578063cbcf252a116100cb578063e5da07531161007f578063f172a4ce11610064578063f172a4ce14610827578063f5dcb7bb1461085b578063f698da251461088f57600080fd5b8063e5da0753146107f2578063ed24911d1461081257600080fd5b8063d03ca40a116100b0578063d03ca40a1461078b578063dc1d95251461079e578063e42cdd7c146107d257600080fd5b8063cbcf252a14610737578063cbf994f81461076b57600080fd5b80639488791111610122578063a2e2ad7e11610107578063a2e2ad7e146106bb578063a6a7187f146106f7578063a6f9dae11461071757600080fd5b806394887911146106535780639a8a05921461068757600080fd5b80638456cb59116101535780638456cb59146105f15780638a39fa16146106065780638da5cb5b1461063357600080fd5b8063757b1156146105b15780637a828b28146105d157600080fd5b806328f223421161021c5780635405ecb9116101d057806356bda507116101b557806356bda50714610543578063599be46f146105705780635c975abb1461059057600080fd5b80635405ecb9146104f257806354fd4d501461052e57600080fd5b80633f4ba83a116102015780633f4ba83a1461049d57806341b60677146104b25780634d5a5827146104df57600080fd5b806328f22342146104425780633af5d04e1461046257600080fd5b80631878d1f11161027357806321561bfc1161025857806321561bfc146103b757806327de9e32146103d7578063287140511461040e57600080fd5b80631878d1f11461036c5780631ee81fb51461039457600080fd5b806306fdde03146102a557806307a3e0a8146102d05780630d0d57a8146102f2578063152b5c0f1461032a575b600080fd5b3480156102b157600080fd5b506102ba6108c3565b6040516102c79190612620565b60405180910390f35b3480156102dc57600080fd5b506102f06102eb36600461263a565b610951565b005b3480156102fe57600080fd5b5061031261030d36600461274b565b6109aa565b6040516001600160a01b0390911681526020016102c7565b34801561033657600080fd5b5061035e7f9dd6d964e72a376a8989d1d2720ab48ff4f2ad77466fb517dabc84f4a79478d481565b6040519081526020016102c7565b34801561037857600080fd5b5061031273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b6103a76103a23660046128ac565b610a80565b60405190151581526020016102c7565b3480156103c357600080fd5b50600654610312906001600160a01b031681565b3480156103e357600080fd5b506103f76103f236600461263a565b610da0565b6040805192151583526020830191909152016102c7565b34801561041a57600080fd5b506103127f0000000000000000000000003fb926116d454b95c669b6bf2e7c3bad8d19affa81565b34801561044e57600080fd5b506103f761045d366004612951565b610ee1565b34801561046e57600080fd5b506103a761047d366004612994565b600560209081526000928352604080842090915290825290205460ff1681565b3480156104a957600080fd5b506102f0611152565b3480156104be57600080fd5b5061035e6104cd36600461263a565b60046020526000908152604090205481565b6103a76104ed36600461263a565b6111c9565b3480156104fe57600080fd5b5061035e61050d366004612994565b60a01b6001600160a01b039091161760009081526003602052604090205490565b34801561053a57600080fd5b506102ba611398565b34801561054f57600080fd5b50610558600181565b6040516001600160601b0390911681526020016102c7565b34801561057c57600080fd5b506102f061058b3660046129c0565b6113a5565b34801561059c57600080fd5b506000546103a790600160a01b900460ff1681565b3480156105bd57600080fd5b5061035e6105cc3660046129dd565b61143c565b3480156105dd57600080fd5b506103f76105ec36600461263a565b61152b565b3480156105fd57600080fd5b506102f0611617565b34801561061257600080fd5b5061035e61062136600461263a565b60036020526000908152604090205481565b34801561063f57600080fd5b50600054610312906001600160a01b031681565b34801561065f57600080fd5b5061035e7f92b2008d2a99f26809ac9d1989fe92334aa84124767331997ba0eec16050ecf481565b34801561069357600080fd5b5061035e7f000000000000000000000000000000000000000000000000000000000000000181565b3480156106c757600080fd5b5061035e6106d6366004612994565b60a01b6001600160a01b039091161760009081526004602052604090205490565b34801561070357600080fd5b5061035e610712366004612a78565b611694565b34801561072357600080fd5b506102f06107323660046129c0565b611750565b34801561074357600080fd5b506103127f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca81565b34801561077757600080fd5b506103a7610786366004612b5a565b61180c565b6103a7610799366004612bf3565b611c81565b3480156107aa57600080fd5b5061035e7fde64b4c9fac43e1615e938b03573b078604f57b4d2e78d3a27d7b20ba017e12681565b3480156107de57600080fd5b5061035e6107ed366004612c56565b611f1b565b3480156107fe57600080fd5b506103a761080d366004612994565b61223c565b34801561081e57600080fd5b5061035e61226a565b34801561083357600080fd5b5061035e7fe7800624217e1c766f5717ba8792e0b2f3e1c1bda11f870b724d9bef903d5b2d81565b34801561086757600080fd5b5061035e7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b34801561089b57600080fd5b5061035e7f27b1db74c9a3fc9e566972b761e2366b72470c34498303516dad89ec572a88e781565b600180546108d090612cf8565b80601f01602080910402602001604051908101604052809291908181526020018280546108fc90612cf8565b80156109495780601f1061091e57610100808354040283529160200191610949565b820191906000526020600020905b81548152906001019060200180831161092c57829003601f168201915b505050505081565b336000818152600560209081526040808320858452825291829020805460ff1916600117905590518381527f85eb1f050732417c0566422b6004a6c5cbded9ded1a406de04060719af52a13a910160405180910390a250565b60405163f908bc7760e01b81526000906001600160a01b037f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca169063f908bc77906109ff903390889088908890600401612d2c565b6020604051808303816000875af1158015610a1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a429190612d5e565b6040519091506001600160a01b038216907fec97633905b1dbe9773a7536e9a986dcf89803e1193934b7b6d76587c68beb4090600090a29392505050565b6040516331a9108f60e11b81526004810185905260009081906001600160a01b037f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca1690636352211e90602401602060405180830381865afa158015610aea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0e9190612d5e565b9050336001600160a01b03821614610b4f5760405163521eb56d60e11b81523360048201526001600160a01b03821660248201526044015b60405180910390fd5b60a086901b6001600160a01b0388161760008181526004602052604081205490610b7d8a858b8b8b8761143c565b9050610b8a8a8288612365565b81610b9481612d91565b60008581526004602081905260408083208490555163dc4f8bc560e01b81529295509092506001600160a01b037f0000000000000000000000003fb926116d454b95c669b6bf2e7c3bad8d19affa169163dc4f8bc591610bfa918f918f918e9101612deb565b6020604051808303816000875af1158015610c19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3d9190612e2c565b90508015610cf8577f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca6001600160a01b031663dff7672460016001600160601b03168b51610c8b9190612e47565b8d8d8d8d6040518663ffffffff1660e01b8152600401610cae9493929190612e97565b60206040518083038185885af1158015610ccc573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610cf19190612e2c565b9550610d92565b6040516337fdd9c960e21b81526001600160a01b037f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca169063dff76724903490610d4c908f908f908f908f90600401612e97565b60206040518083038185885af1158015610d6a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610d8f9190612e2c565b95505b505050505095945050505050565b60405163161e984960e31b815233600482015260248101829052600090819081906001600160a01b037f0000000000000000000000003fb926116d454b95c669b6bf2e7c3bad8d19affa169063b0f4c248906044016020604051808303816000875af1158015610e14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e389190612edc565b6040516352e82ce560e11b8152336004820152602481018690529091507f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca6001600160a01b03169063a5d059ca906044015b60408051808303816000875af1158015610ea8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ecc9190612ef5565b90935091508015610edb578091505b50915091565b60008060007f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca6001600160a01b0316636352211e866040518263ffffffff1660e01b8152600401610f3491815260200190565b602060405180830381865afa158015610f51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f759190612d5e565b9050336001600160a01b03821614610fb15760405163521eb56d60e11b81523360048201526001600160a01b0382166024820152604401610b46565b60a085901b6001600160a01b0387161760008181526003602052604081205490610fdd89858a85611694565b9050610fea898289612365565b81610ff481612d91565b6000858152600360205260408082208390555163161e984960e31b81526001600160a01b038d81166004830152602482018d90529295509092507f0000000000000000000000003fb926116d454b95c669b6bf2e7c3bad8d19affa9091169063b0f4c248906044016020604051808303816000875af115801561107b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109f9190612edc565b6040516352e82ce560e11b81526001600160a01b038c81166004830152602482018c90529192507f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca9091169063a5d059ca9060440160408051808303816000875af1158015611112573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111369190612ef5565b90975095508015611145578095505b5050505050935093915050565b6000546001600160a01b031633146111925760005460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610b46565b6000805460ff60a01b1916815560405133917faeb196d352664784d1900b0e7414a8face7d29f4dae8c4b0cf68ed477423bbf491a2565b60405163542db44960e01b81526004810182905260009081906001600160a01b037f0000000000000000000000003fb926116d454b95c669b6bf2e7c3bad8d19affa169063542db449906024016020604051808303816000875af1158015611235573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112599190612e2c565b905080156112fc5760405163388fdbed60e21b8152336004820152602481018490527f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca6001600160a01b03169063e23f6fb49060019060440160206040518083038185885af11580156112d0573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906112f59190612e2c565b9150611392565b60405163388fdbed60e21b8152336004820152602481018490527f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca6001600160a01b03169063e23f6fb490349060440160206040518083038185885af115801561136a573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061138f9190612e2c565b91505b50919050565b600280546108d090612cf8565b6000546001600160a01b031633146113e55760005460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610b46565b6006805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517ff8e76e8a7c35558598a944d509f1ed32b104e77b1098ef1dfa5b97b86b09df8f90600090a250565b600061144661226a565b7fde64b4c9fac43e1615e938b03573b078604f57b4d2e78d3a27d7b20ba017e126888888888860405160200161147d929190612f21565b60408051601f198184030181528282528051602091820120908301969096526001600160a01b0394851690820152929091166060830152608082015260a081019190915260c0810184905260e0016040516020818303038152906040528051906020012060405160200161150892919061190160f01b81526002810192909252602282015260420190565b6040516020818303038152906040528051906020012090505b9695505050505050565b60008060007f0000000000000000000000003fb926116d454b95c669b6bf2e7c3bad8d19affa6001600160a01b03166325e1afc3856040518263ffffffff1660e01b815260040161157e91815260200190565b6020604051808303816000875af115801561159d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c19190612edc565b60405163ccc9305d60e01b8152336004820152602481018690529091507f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca6001600160a01b03169063ccc9305d90604401610e8a565b6000546001600160a01b031633146116575760005460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610b46565b6000805460ff60a01b1916600160a01b17815560405133917f5ee71a369c8672edded508e624ffc9257fa1ae6886ef32905c18e60196bca39991a2565b600061169e61226a565b604080517f92b2008d2a99f26809ac9d1989fe92334aa84124767331997ba0eec16050ecf460208201526001600160a01b038089169282019290925290861660608201526080810185905260a0810184905260c0016040516020818303038152906040528051906020012060405160200161173092919061190160f01b81526002810192909252602282015260420190565b604051602081830303815290604052805190602001209050949350505050565b6000546001600160a01b031633146117905760005460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610b46565b6001600160a01b0381166117b75760405163d92e233d60e01b815260040160405180910390fd5b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038316908117825560405190917f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b91a250565b60006001600160a01b0387166118355760405163d92e233d60e01b815260040160405180910390fd5b835173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03891601611a0a5760005b818110156118ee57600086828151811061187b5761187b612f46565b60200260200101516000015163ffffffff161180156118c057508581815181106118a7576118a7612f46565b6020026020010151602001516001600160601b03166000145b156118de57604051637c946ed760e01b815260040160405180910390fd5b6118e781612d91565b905061185f565b5060405163197f329f60e31b81526001600160a01b037f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca169063cbf994f8906119459033908b908b908b908b908b90600401612fa6565b6020604051808303816000875af1158015611964573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119889190612e2c565b604051630be6cc4b60e31b8152600481018590529092507f0000000000000000000000003fb926116d454b95c669b6bf2e7c3bad8d19affa6001600160a01b031690635f36625890602401600060405180830381600087803b1580156119ed57600080fd5b505af1158015611a01573d6000803e3d6000fd5b50505050611c76565b60008167ffffffffffffffff811115611a2557611a2561266b565b604051908082528060200260200182016040528015611a4e578160200160208202803683370190505b50905060005b82811015611b53576000878281518110611a7057611a70612f46565b60200260200101516000015163ffffffff161115611b4357868181518110611a9a57611a9a612f46565b6020026020010151602001516001600160601b0316600003611acf57604051637c946ed760e01b815260040160405180910390fd5b868181518110611ae157611ae1612f46565b6020026020010151602001516001600160601b0316828281518110611b0857611b08612f46565b6020026020010181815250506001878281518110611b2857611b28612f46565b6020908102919091018101516001600160601b039092169101525b611b4c81612d91565b9050611a54565b5060405163197f329f60e31b81526001600160a01b037f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca169063cbf994f890611baa9033908c908c908c908c908c90600401612fa6565b6020604051808303816000875af1158015611bc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bed9190612e2c565b6040516338f3a6a160e21b81529093506001600160a01b037f0000000000000000000000003fb926116d454b95c669b6bf2e7c3bad8d19affa169063e3ce9a8490611c429087908d908c908790600401612ffc565b600060405180830381600087803b158015611c5c57600080fd5b505af1158015611c70573d6000803e3d6000fd5b50505050505b509695505050505050565b6006546000906001600160a01b031615611d28576006546040516356a7b60760e01b8152600481018690523360248201526001600160a01b03909116906356a7b60790604401602060405180830381865afa158015611ce4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d089190612e2c565b611d28576040516322ddebd960e21b815260048101859052602401610b46565b60405163dc4f8bc560e01b81526000906001600160a01b037f0000000000000000000000003fb926116d454b95c669b6bf2e7c3bad8d19affa169063dc4f8bc590611d7b90339089908890600401612deb565b6020604051808303816000875af1158015611d9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dbe9190612e2c565b90508015611e79577f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca6001600160a01b031663dff7672460016001600160601b03168651611e0c9190612e47565b338888886040518663ffffffff1660e01b8152600401611e2f9493929190612e97565b60206040518083038185885af1158015611e4d573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611e729190612e2c565b9150611f13565b6040516337fdd9c960e21b81526001600160a01b037f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca169063dff76724903490611ecd9033908a908a908a90600401612e97565b60206040518083038185885af1158015611eeb573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611f109190612e2c565b91505b509392505050565b60008054600160a01b900460ff1615611f47576040516313d0ff5960e31b815260040160405180910390fd5b6001600160a01b038616611f6e5760405163d92e233d60e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038716016120315760405163fbdeb3d760e01b81526001600160a01b037f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca169063fbdeb3d790611fe7908a908990899089908990600401613067565b6020604051808303816000875af1158015612006573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202a9190612edc565b9050611521565b825160008167ffffffffffffffff81111561204e5761204e61266b565b604051908082528060200260200182016040528015612077578160200160208202803683370190505b50905060005b8281101561214f5785818151811061209757612097612f46565b6020026020010151602001516001600160601b03166000036120cc57604051637c946ed760e01b815260040160405180910390fd5b8581815181106120de576120de612f46565b6020026020010151602001516001600160601b031682828151811061210557612105612f46565b602002602001018181525050600186828151811061212557612125612f46565b6020908102919091018101516001600160601b0390921691015261214881612d91565b905061207d565b5060405163fbdeb3d760e01b81526001600160a01b037f00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca169063fbdeb3d7906121a4908c908b908b908b908b90600401613067565b6020604051808303816000875af11580156121c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e79190612edc565b6040516338f3a6a160e21b81529093506001600160a01b037f0000000000000000000000003fb926116d454b95c669b6bf2e7c3bad8d19affa169063e3ce9a8490611c429086908c908b908790600401612ffc565b6001600160a01b038216600090815260056020908152604080832084845290915290205460ff165b92915050565b60007f000000000000000000000000000000000000000000000000000000000000000146146123405761233b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527fe7800624217e1c766f5717ba8792e0b2f3e1c1bda11f870b724d9bef903d5b2d918101919091527f9dd6d964e72a376a8989d1d2720ab48ff4f2ad77466fb517dabc84f4a79478d460608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b905090565b507f27b1db74c9a3fc9e566972b761e2366b72470c34498303516dad89ec572a88e790565b6001600160a01b03831661238c5760405163e63f571f60e01b815260040160405180910390fd5b80516041146123b5578051604051631d9f5a5f60e01b8152610b469183916041906004016130ba565b6000816040815181106123ca576123ca612f46565b016020015160f81c90506004811080156123ec57506001600160a01b0384163b155b156123ff576123fc601b826130df565b90505b60208201516040830151600060ff84166004036124d45750604051630b135d3f60e11b80825283916001600160a01b03831690631626ba7e90612448908a908a906004016130f8565b602060405180830381865afa158015612465573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124899190613119565b7fffffffff0000000000000000000000000000000000000000000000000000000016146124cf5780868660405163694d54dd60e01b8152600401610b469392919061315b565b61258c565b8360ff1660050361252c57506001600160a01b0382166000908152600560209081526040808320888452909152902054829060ff166124cf578086866040516312cf832560e01b8152600401610b469392919061315b565b60408051600081526020810180835288905260ff861691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa15801561257f573d6000803e3d6000fd5b5050506020604051035190505b866001600160a01b0316816001600160a01b0316146125d15760405163a806216d60e01b81526001600160a01b03808316600483015288166024820152604401610b46565b50505050505050565b6000815180845260005b81811015612600576020818501810151868301820152016125e4565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061263360208301846125da565b9392505050565b60006020828403121561264c57600080fd5b5035919050565b6001600160a01b038116811461266857600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156126a4576126a461266b565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156126d3576126d361266b565b604052919050565b600082601f8301126126ec57600080fd5b813567ffffffffffffffff8111156127065761270661266b565b612719601f8201601f19166020016126aa565b81815284602083860101111561272e57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006060848603121561276057600080fd5b83359250602084013561277281612653565b9150604084013567ffffffffffffffff81111561278e57600080fd5b61279a868287016126db565b9150509250925092565b600067ffffffffffffffff8211156127be576127be61266b565b5060051b60200190565b600082601f8301126127d957600080fd5b813560206127ee6127e9836127a4565b6126aa565b82815260059290921b8401810191818101908684111561280d57600080fd5b8286015b84811015611c7657803561282481612653565b8352918301918301612811565b803563ffffffff8116811461284557600080fd5b919050565b600082601f83011261285b57600080fd5b8135602061286b6127e9836127a4565b82815260059290921b8401810191818101908684111561288a57600080fd5b8286015b84811015611c765761289f81612831565b835291830191830161288e565b600080600080600060a086880312156128c457600080fd5b85356128cf81612653565b945060208601359350604086013567ffffffffffffffff808211156128f357600080fd5b6128ff89838a016127c8565b9450606088013591508082111561291557600080fd5b61292189838a0161284a565b9350608088013591508082111561293757600080fd5b50612944888289016126db565b9150509295509295909350565b60008060006060848603121561296657600080fd5b833561297181612653565b925060208401359150604084013567ffffffffffffffff81111561278e57600080fd5b600080604083850312156129a757600080fd5b82356129b281612653565b946020939093013593505050565b6000602082840312156129d257600080fd5b813561263381612653565b60008060008060008060c087890312156129f657600080fd5b8635612a0181612653565b95506020870135612a1181612653565b945060408701359350606087013567ffffffffffffffff80821115612a3557600080fd5b612a418a838b016127c8565b94506080890135915080821115612a5757600080fd5b50612a6489828a0161284a565b92505060a087013590509295509295509295565b60008060008060808587031215612a8e57600080fd5b8435612a9981612653565b93506020850135612aa981612653565b93969395505050506040820135916060013590565b600082601f830112612acf57600080fd5b81356020612adf6127e9836127a4565b82815260069290921b84018101918181019086841115612afe57600080fd5b8286015b84811015611c765760408189031215612b1b5760008081fd5b612b23612681565b612b2c82612831565b8152848201356001600160601b0381168114612b485760008081fd5b81860152835291830191604001612b02565b60008060008060008060c08789031215612b7357600080fd5b8635612b7e81612653565b955060208701359450604087013567ffffffffffffffff80821115612ba257600080fd5b612bae8a838b0161284a565b95506060890135915080821115612bc457600080fd5b50612bd189828a01612abe565b935050612be060808801612831565b915060a087013590509295509295509295565b600080600060608486031215612c0857600080fd5b83359250602084013567ffffffffffffffff80821115612c2757600080fd5b612c33878388016127c8565b93506040860135915080821115612c4957600080fd5b5061279a8682870161284a565b60008060008060008060c08789031215612c6f57600080fd5b8635612c7a81612653565b95506020870135612c8a81612653565b945060408701359350606087013567ffffffffffffffff80821115612cae57600080fd5b612cba8a838b0161284a565b94506080890135915080821115612cd057600080fd5b50612cdd89828a01612abe565b925050612cec60a08801612831565b90509295509295509295565b600181811c90821680612d0c57607f821691505b60208210810361139257634e487b7160e01b600052602260045260246000fd5b60006001600160a01b0380871683528560208401528085166040840152506080606083015261152160808301846125da565b600060208284031215612d7057600080fd5b815161263381612653565b634e487b7160e01b600052601160045260246000fd5b600060018201612da357612da3612d7b565b5060010190565b600081518084526020808501945080840160005b83811015612de057815163ffffffff1687529582019590820190600101612dbe565b509495945050505050565b6001600160a01b0384168152826020820152606060408201526000612e136060830184612daa565b95945050505050565b8051801515811461284557600080fd5b600060208284031215612e3e57600080fd5b61263382612e1c565b808202811582820484141761226457612264612d7b565b600081518084526020808501945080840160005b83811015612de05781516001600160a01b031687529582019590820190600101612e72565b6001600160a01b0385168152836020820152608060408201526000612ebf6080830185612e5e565b8281036060840152612ed18185612daa565b979650505050505050565b600060208284031215612eee57600080fd5b5051919050565b60008060408385031215612f0857600080fd5b612f1183612e1c565b9150602083015190509250929050565b604081526000612f346040830185612e5e565b8281036020840152611f108185612daa565b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501945080840160005b83811015612de0578151805163ffffffff1688528301516001600160601b03168388015260409096019590820190600101612f70565b6001600160a01b038716815285602082015260c060408201526000612fce60c0830187612daa565b8281036060840152612fe08187612f5c565b63ffffffff959095166080840152505060a00152949350505050565b848152600060206001600160a01b03861681840152608060408401526130256080840186612daa565b838103606085015284518082528286019183019060005b818110156130585783518352928401929184019160010161303c565b50909998505050505050505050565b6001600160a01b038616815284602082015260a06040820152600061308f60a0830186612daa565b82810360608401526130a18186612f5c565b91505063ffffffff831660808301529695505050505050565b6060815260006130cd60608301866125da565b60208301949094525060400152919050565b60ff818116838216019081111561226457612264612d7b565b82815260406020820152600061311160408301846125da565b949350505050565b60006020828403121561312b57600080fd5b81517fffffffff000000000000000000000000000000000000000000000000000000008116811461263357600080fd5b6001600160a01b0384168152826020820152606060408201526000612e1360608301846125da56fea2646970667358221220f2d50ac7cf109448ada9fff306a728e5251fe66a1c6e6ec31ba9ad713c2ad83964736f6c63430008130033

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

00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca0000000000000000000000003fb926116d454b95c669b6bf2e7c3bad8d19affa00000000000000000000000042042799b0de38add2a70dc996f69f98e1a85260

-----Decoded View---------------
Arg [0] : _serviceRegistry (address): 0x48b6af7B12C71f09e2fC8aF4855De4Ff54e775cA
Arg [1] : _serviceRegistryTokenUtility (address): 0x3Fb926116D454b95c669B6Bf2E7c3bad8d19affA
Arg [2] : _operatorWhitelist (address): 0x42042799B0DE38AdD2a70dc996f69f98E1a85260

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000048b6af7b12c71f09e2fc8af4855de4ff54e775ca
Arg [1] : 0000000000000000000000003fb926116d454b95c669b6bf2e7c3bad8d19affa
Arg [2] : 00000000000000000000000042042799b0de38add2a70dc996f69f98e1a85260


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

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