From 28e46c7f5bb17a2a9ba776e216d06aa7dd09e3f2 Mon Sep 17 00:00:00 2001 From: David Vilela Date: Fri, 16 Feb 2024 13:26:01 +0100 Subject: [PATCH 01/10] fix: update contract to latest version --- .../service_staking_token/contract.py | 53 +++++++++++++++++-- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/backend/operate/data/contracts/service_staking_token/contract.py b/backend/operate/data/contracts/service_staking_token/contract.py index e0e91a0b2..e3c29de9e 100644 --- a/backend/operate/data/contracts/service_staking_token/contract.py +++ b/backend/operate/data/contracts/service_staking_token/contract.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2023 Valory AG +# Copyright 2023-2024 Valory AG # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,19 +19,29 @@ """This module contains the class to connect to the `ServiceStakingTokenMechUsage` contract.""" +from enum import Enum + from aea.common import JSONLike from aea.configurations.base import PublicId from aea.contracts.base import Contract from aea.crypto.base import LedgerApi +class StakingState(Enum): + """Staking state enumeration for the staking.""" + + UNSTAKED = 0 + STAKED = 1 + EVICTED = 2 + + class ServiceStakingTokenContract(Contract): """The Service Staking contract.""" contract_id = PublicId.from_str("valory/service_staking_token:0.1.0") @classmethod - def is_service_staked( + def get_service_staking_state( cls, ledger_api: LedgerApi, contract_address: str, @@ -39,8 +49,8 @@ def is_service_staked( ) -> JSONLike: """Check whether the service is staked.""" contract_instance = cls.get_instance(ledger_api, contract_address) - res = contract_instance.functions.isServiceStaked(service_id).call() - return dict(data=res) + res = contract_instance.functions.getServiceStakingState(service_id).call() + return dict(data=StakingState(res)) @classmethod def build_stake_tx( @@ -131,5 +141,38 @@ def get_service_info( ) -> JSONLike: """Retrieve the service info for a service.""" contract = cls.get_instance(ledger_api, contract_address) - info = contract.functions.mapServiceInfo(service_id).call() + info = contract.functions.getServiceInfo(service_id).call() return dict(data=info) + + @classmethod + def max_num_services( + cls, + ledger_api: LedgerApi, + contract_address: str, + ) -> JSONLike: + """Retrieve the max number of services.""" + contract = cls.get_instance(ledger_api, contract_address) + max_num_services = contract.functions.maxNumServices().call() + return dict(data=max_num_services) + + @classmethod + def get_service_ids( + cls, + ledger_api: LedgerApi, + contract_address: str, + ) -> JSONLike: + """Retrieve the service IDs.""" + contract = cls.get_instance(ledger_api, contract_address) + service_ids = contract.functions.getServiceIds().call() + return dict(data=service_ids) + + @classmethod + def get_min_staking_duration( + cls, + ledger_api: LedgerApi, + contract_address: str, + ) -> JSONLike: + """Retrieve the service IDs.""" + contract = cls.get_instance(ledger_api, contract_address) + duration = contract.functions.minStakingDuration().call() + return dict(data=duration) From cee9fda1eb7d5d07db3e9233c84701f0b44fa80c Mon Sep 17 00:00:00 2001 From: David Vilela Date: Fri, 16 Feb 2024 13:26:15 +0100 Subject: [PATCH 02/10] fix: check unstaking availability --- backend/operate/services/protocol.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/backend/operate/services/protocol.py b/backend/operate/services/protocol.py index 62a6325b3..ce1eb0745 100644 --- a/backend/operate/services/protocol.py +++ b/backend/operate/services/protocol.py @@ -29,7 +29,7 @@ from enum import Enum from pathlib import Path from typing import Optional, Union - +import time from aea.configurations.data_types import PackageType from aea.crypto.base import Crypto, LedgerApi from aea.helpers.base import IPFSHash, cd @@ -204,6 +204,11 @@ def slots_available(self, staking_contract: str) -> bool: ) return instance.maxNumServices().call() - len(instance.getServiceIds().call()) + def onchain_info(self, staking_contract: str, service_id: int) -> dict: + """Get the service onchain info""" + return self.staking_ctr.get_service_info(self.ledger_api, staking_contract, service_id) + + def stake( self, service_id: int, @@ -211,14 +216,14 @@ def stake( staking_contract: str, ) -> None: """Stake the service""" - status = self.status(service_id) + status = self.status(service_id, staking_contract) if status == StakingState.STAKED: raise ValueError("Service already stacked") if status == StakingState.EVICTED: raise ValueError("Service is evicted") - if not self.slots_available(): + if not self.slots_available(staking_contract): raise ValueError("No sataking slots available.") tx_settler = TxSettler( @@ -271,9 +276,12 @@ def _build_staking_tx(*args, **kargs) -> t.Dict: def unstake(self, service_id: int, staking_contract: str) -> None: """Unstake the service""" - if self.status(service_id=service_id) != StakingState.STAKED: + if self.status(service_id=service_id, staking_contract=staking_contract) != StakingState.STAKED: raise ValueError("Service not staked.") + if not self.check_unstaking_availability(service_id, staking_contract): + raise ValueError("Service cannot be unstaked yet.") + tx_settler = TxSettler( ledger_api=self.ledger_api, crypto=self.crypto, @@ -283,7 +291,6 @@ def unstake(self, service_id: int, staking_contract: str) -> None: sleep=self.sleep, ) - # TODO: check unstaking availability for EVICTED services def _build_unstaking_tx() -> t.Dict: self.staking_ctr.get_instance( ledger_api=self.ledger_api, contract_address=staking_contract @@ -303,6 +310,14 @@ def _build_unstaking_tx() -> t.Dict: dry_run=False, ) + def check_unstaking_availability(self, service_id: int, staking_contract: str) -> bool: + """Check unstaking availability""" + ts_start = t.cast(int, self.onchain_info(staking_contract, service_id)["data"][3]) + available_rewards = t.cast(int, self.staking_ctr.available_rewards(self.ledger_api, staking_contract)["data"]) + minimum_staking_duration = t.cast(int, self.staking_ctr.get_min_staking_duration(self.ledger_api, staking_contract)["data"]) + if (time.time() - ts_start) < minimum_staking_duration and available_rewards > 0: + return False + return True class OnChainManager: """On chain service management.""" From 24c092569fc18f7c5b5130ea5bc2a6b136e79905 Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Mon, 19 Feb 2024 14:59:34 +0530 Subject: [PATCH 03/10] feat: use one of the hardhat node keys for master keys in the dev mode --- backend/app.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/backend/app.py b/backend/app.py index 768f3bdd5..f05c73a8f 100644 --- a/backend/app.py +++ b/backend/app.py @@ -21,7 +21,7 @@ from pathlib import Path - +import os from aea_ledger_ethereum.ethereum import EthereumCrypto from clea import command, params, run from operate.constants import KEY, KEYS, OPERATE, SERVICES @@ -35,6 +35,10 @@ from typing_extensions import Annotated from uvicorn.main import run as uvicorn +DEFAULT_HARDHAT_KEY = ( + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" +).encode() + class App(Resource): """App resource.""" @@ -63,7 +67,11 @@ def make(self) -> None: self._keys.mkdir(exist_ok=True) if not self._key.exists(): # TODO: Add support for multiple master keys - self._key.write_bytes(EthereumCrypto().private_key.encode()) + self._key.write_bytes( + DEFAULT_HARDHAT_KEY + if os.environ.get("DEV", "false") == "true" + else EthereumCrypto().private_key.encode() + ) @property def json(self) -> None: From 4639b0af1a8919997955934502e83f919c0e2314 Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Mon, 19 Feb 2024 15:03:23 +0530 Subject: [PATCH 04/10] fix: update logic --- backend/operate/services/manage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/operate/services/manage.py b/backend/operate/services/manage.py index fa5fef3fa..8dbb9d836 100644 --- a/backend/operate/services/manage.py +++ b/backend/operate/services/manage.py @@ -286,7 +286,7 @@ def update(self, data: PutServices) -> ServiceType: """Update service using a template.""" # NOTE: This method contains a lot of repetative code rpc = data["new"]["configuration"]["rpc"] - phash = data["new"]["configuration"]["hash"] + phash = data["new"]["hash"] if (self.path / phash).exists(): # For testing only shutil.rmtree(self.path / phash) From a4c74347a4dce921365fc761d184e4ab28c3bdee Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Mon, 19 Feb 2024 15:03:44 +0530 Subject: [PATCH 05/10] fix: use hash from template for e2e testing --- backend/scripts/test_e2e.py | 5 +++-- backend/scripts/test_staking_e2e.py | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/scripts/test_e2e.py b/backend/scripts/test_e2e.py index acc74e60b..9378c5022 100644 --- a/backend/scripts/test_e2e.py +++ b/backend/scripts/test_e2e.py @@ -31,6 +31,7 @@ def test_endpoint_e2e(): with Path("templates/trader.yaml").open("r", encoding="utf-8") as stream: trader_template = yaml_load(stream=stream) + phash = trader_template["hash"] print("Creating service using template") response = requests.post( @@ -42,14 +43,14 @@ def test_endpoint_e2e(): input("> Press enter to start") print( requests.get( - url=f"{BASE_URL}/services/bafybeigiwlvm6ey4dmlztg3z4xyvpol23n444vliivx2ybuki7xo4f3pae/deploy/", + url=f"{BASE_URL}/services/{phash}/deploy/", ).content.decode() ) input("> Press enter to stop") print( requests.get( - url=f"{BASE_URL}/services/bafybeigiwlvm6ey4dmlztg3z4xyvpol23n444vliivx2ybuki7xo4f3pae/stop/", + url=f"{BASE_URL}/services/{phash}/stop/", ).content.decode() ) diff --git a/backend/scripts/test_staking_e2e.py b/backend/scripts/test_staking_e2e.py index 1e3d8d779..d0ca0527a 100644 --- a/backend/scripts/test_staking_e2e.py +++ b/backend/scripts/test_staking_e2e.py @@ -31,6 +31,7 @@ def test_endpoint_e2e(): with Path("templates/trader.yaml").open("r", encoding="utf-8") as stream: trader_template = yaml_load(stream=stream) + phash = trader_template["hash"] trader_template["configuration"]["use_staking"] = True print("Creating service using template") @@ -43,14 +44,14 @@ def test_endpoint_e2e(): input("> Press enter to start") print( requests.get( - url=f"{BASE_URL}/services/bafybeigiwlvm6ey4dmlztg3z4xyvpol23n444vliivx2ybuki7xo4f3pae/deploy/", + url=f"{BASE_URL}/services/{phash}/deploy/", ).content.decode() ) input("> Press enter to stop") print( requests.get( - url=f"{BASE_URL}/services/bafybeigiwlvm6ey4dmlztg3z4xyvpol23n444vliivx2ybuki7xo4f3pae/stop/", + url=f"{BASE_URL}/services/{phash}/stop/", ).content.decode() ) From 55073b0aec5784f1c94f510c24d0ab28dbe14b6f Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Mon, 19 Feb 2024 15:03:57 +0530 Subject: [PATCH 06/10] chore: formatters --- backend/app.py | 3 +- .../service_staking_token/contract.py | 6 +-- backend/operate/services/protocol.py | 40 ++++++++++++++----- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/backend/app.py b/backend/app.py index f05c73a8f..c03a4d58c 100644 --- a/backend/app.py +++ b/backend/app.py @@ -20,8 +20,9 @@ """Operate app entrypoint.""" -from pathlib import Path import os +from pathlib import Path + from aea_ledger_ethereum.ethereum import EthereumCrypto from clea import command, params, run from operate.constants import KEY, KEYS, OPERATE, SERVICES diff --git a/backend/operate/data/contracts/service_staking_token/contract.py b/backend/operate/data/contracts/service_staking_token/contract.py index e3c29de9e..f24a822b0 100644 --- a/backend/operate/data/contracts/service_staking_token/contract.py +++ b/backend/operate/data/contracts/service_staking_token/contract.py @@ -168,9 +168,9 @@ def get_service_ids( @classmethod def get_min_staking_duration( - cls, - ledger_api: LedgerApi, - contract_address: str, + cls, + ledger_api: LedgerApi, + contract_address: str, ) -> JSONLike: """Retrieve the service IDs.""" contract = cls.get_instance(ledger_api, contract_address) diff --git a/backend/operate/services/protocol.py b/backend/operate/services/protocol.py index ce1eb0745..c875383ca 100644 --- a/backend/operate/services/protocol.py +++ b/backend/operate/services/protocol.py @@ -25,11 +25,12 @@ import json import logging import tempfile +import time import typing as t from enum import Enum from pathlib import Path from typing import Optional, Union -import time + from aea.configurations.data_types import PackageType from aea.crypto.base import Crypto, LedgerApi from aea.helpers.base import IPFSHash, cd @@ -206,8 +207,9 @@ def slots_available(self, staking_contract: str) -> bool: def onchain_info(self, staking_contract: str, service_id: int) -> dict: """Get the service onchain info""" - return self.staking_ctr.get_service_info(self.ledger_api, staking_contract, service_id) - + return self.staking_ctr.get_service_info( + self.ledger_api, staking_contract, service_id + ) def stake( self, @@ -276,7 +278,10 @@ def _build_staking_tx(*args, **kargs) -> t.Dict: def unstake(self, service_id: int, staking_contract: str) -> None: """Unstake the service""" - if self.status(service_id=service_id, staking_contract=staking_contract) != StakingState.STAKED: + if ( + self.status(service_id=service_id, staking_contract=staking_contract) + != StakingState.STAKED + ): raise ValueError("Service not staked.") if not self.check_unstaking_availability(service_id, staking_contract): @@ -310,15 +315,32 @@ def _build_unstaking_tx() -> t.Dict: dry_run=False, ) - def check_unstaking_availability(self, service_id: int, staking_contract: str) -> bool: + def check_unstaking_availability( + self, service_id: int, staking_contract: str + ) -> bool: """Check unstaking availability""" - ts_start = t.cast(int, self.onchain_info(staking_contract, service_id)["data"][3]) - available_rewards = t.cast(int, self.staking_ctr.available_rewards(self.ledger_api, staking_contract)["data"]) - minimum_staking_duration = t.cast(int, self.staking_ctr.get_min_staking_duration(self.ledger_api, staking_contract)["data"]) - if (time.time() - ts_start) < minimum_staking_duration and available_rewards > 0: + ts_start = t.cast( + int, self.onchain_info(staking_contract, service_id)["data"][3] + ) + available_rewards = t.cast( + int, + self.staking_ctr.available_rewards(self.ledger_api, staking_contract)[ + "data" + ], + ) + minimum_staking_duration = t.cast( + int, + self.staking_ctr.get_min_staking_duration( + self.ledger_api, staking_contract + )["data"], + ) + if ( + time.time() - ts_start + ) < minimum_staking_duration and available_rewards > 0: return False return True + class OnChainManager: """On chain service management.""" From efa86d7270d75768540b3e927d902a86d058fa51 Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Mon, 19 Feb 2024 15:04:46 +0530 Subject: [PATCH 07/10] fix: remove deprecated argument --- backend/operate/services/manage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/operate/services/manage.py b/backend/operate/services/manage.py index 8dbb9d836..f46eeaaae 100644 --- a/backend/operate/services/manage.py +++ b/backend/operate/services/manage.py @@ -319,7 +319,7 @@ def update(self, data: PutServices) -> ServiceType: ) service = self._create( phash=phash, - rpc=rpc, + configuration=data["new"]["configuration"], instances=instances, reuse_multisig=True, update_token=old.chain_data["token"], From 43bb67ace89a4a6e0eee84d3ee6495088288c528 Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Mon, 19 Feb 2024 17:05:21 +0530 Subject: [PATCH 08/10] fix: staking integration --- .../build/ServiceStakingToken.json | 267 ++++++++++++++++-- .../service_staking_token/contract.yaml | 4 +- backend/operate/ledger/profiles.py | 2 +- backend/operate/services/manage.py | 43 +-- backend/operate/services/protocol.py | 36 ++- backend/pyproject.toml | 2 +- templates/trader.yaml | 5 +- 7 files changed, 296 insertions(+), 63 deletions(-) diff --git a/backend/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json b/backend/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json index 27185c342..e1405c0bf 100644 --- a/backend/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json +++ b/backend/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json @@ -22,6 +22,16 @@ "name": "minStakingDeposit", "type": "uint256" }, + { + "internalType": "uint256", + "name": "minNumStakingPeriods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxNumInactivityPeriods", + "type": "uint256" + }, { "internalType": "uint256", "name": "livenessPeriod", @@ -236,6 +246,27 @@ "name": "NoRewardsAvailable", "type": "error" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tsProvided", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tsExpected", + "type": "uint256" + } + ], + "name": "NotEnoughTimeStaked", + "type": "error" + }, { "inputs": [ { @@ -334,7 +365,7 @@ "type": "uint256" } ], - "name": "ServiceNotStaked", + "name": "ServiceNotUnstaked", "type": "error" }, { @@ -532,16 +563,28 @@ "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "uint256", - "name": "availableRewards", + "name": "epoch", "type": "uint256" }, { "indexed": false, "internalType": "uint256", - "name": "numServices", + "name": "availableRewards", "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "serviceIds", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "rewards", + "type": "uint256[]" } ], "name": "Checkpoint", @@ -581,6 +624,12 @@ { "anonymous": false, "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -612,6 +661,12 @@ { "anonymous": false, "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, { "indexed": true, "internalType": "uint256", @@ -641,15 +696,46 @@ "internalType": "uint256", "name": "reward", "type": "uint256" - }, + } + ], + "name": "ServiceUnstaked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "uint256", - "name": "tsStart", + "name": "epoch", "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "serviceIds", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "owners", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "multisigs", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "serviceInactivity", + "type": "uint256[]" } ], - "name": "ServiceUnstaked", + "name": "ServicesEvicted", "type": "event" }, { @@ -729,6 +815,25 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "calculateServiceStakingLastReward", + "outputs": [ + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -762,11 +867,6 @@ "name": "", "type": "uint256[][]" }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, { "internalType": "uint256[]", "name": "", @@ -778,9 +878,9 @@ "type": "uint256[]" }, { - "internalType": "bool", - "name": "success", - "type": "bool" + "internalType": "uint256[]", + "name": "evictServiceIds", + "type": "uint256[]" } ], "stateMutability": "nonpayable", @@ -812,6 +912,32 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "epochCounter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAgentIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "getNextRewardCheckpointTimestamp", @@ -831,7 +957,7 @@ "outputs": [ { "internalType": "uint256[]", - "name": "serviceIds", + "name": "", "type": "uint256[]" } ], @@ -846,12 +972,63 @@ "type": "uint256" } ], - "name": "isServiceStaked", + "name": "getServiceInfo", "outputs": [ { - "internalType": "bool", - "name": "isStaked", - "type": "bool" + "components": [ + { + "internalType": "address", + "name": "multisig", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "nonces", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "tsStart", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "inactivity", + "type": "uint256" + } + ], + "internalType": "struct ServiceInfo", + "name": "sInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "getServiceStakingState", + "outputs": [ + { + "internalType": "enum ServiceStakingBase.ServiceStakingState", + "name": "stakingState", + "type": "uint8" } ], "stateMutability": "view", @@ -912,6 +1089,37 @@ "internalType": "uint256", "name": "reward", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "inactivity", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxInactivityDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxNumInactivityPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" } ], "stateMutability": "view", @@ -943,6 +1151,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "minStakingDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "numAgentInstances", @@ -1127,8 +1348,8 @@ "type": "function" } ], - "bytecode": "0x6102006040523480156200001257600080fd5b506040516200294c3803806200294c8339810160408190526200003591620003bc565b8484828260000151600014806200004e57506020830151155b806200005c57506060830151155b806200006a57506080830151155b8062000078575060a0830151155b156200009757604051637c946ed760e01b815260040160405180910390fd5b600283604001511015620000d357604080840151905163491a2bb160e01b81526004810191909152600260248201526044015b60405180910390fd5b6001600160a01b038216620000fb5760405163d92e233d60e01b815260040160405180910390fd5b82516080908152602084015160a0908152604085015160c052606085015160e09081529185015161010090815290850151610120526001600160a01b038416610180529084015161014052830151610160526000805b8460c00151518110156200023357818560c001518281518110620001795762000179620004c6565b602002602001015111620001c5578460c001518181518110620001a057620001a0620004c6565b6020026020010151604051632ab10b0b60e21b8152600401620000ca91815260200190565b8460c001518181518110620001de57620001de620004c6565b6020908102919091010151600380546001810182556000919091527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0181905591506200022b81620004dc565b905062000151565b50816200025357604051637c946ed760e01b815260040160405180910390fd5b506101a0525050426002556001600160a01b03821615806200027c57506001600160a01b038316155b156200029b5760405163d92e233d60e01b815260040160405180910390fd5b506001600160a01b039081166101e052166101c05250620005049050565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b0381118282101715620002f557620002f5620002b9565b60405290565b600082601f8301126200030d57600080fd5b815160206001600160401b03808311156200032c576200032c620002b9565b8260051b604051601f19603f83011681018181108482111715620003545762000354620002b9565b6040529384528581018301938381019250878511156200037357600080fd5b83870191505b84821015620003945781518352918301919083019062000379565b979650505050505050565b80516001600160a01b0381168114620003b757600080fd5b919050565b600080600080600060a08688031215620003d557600080fd5b85516001600160401b0380821115620003ed57600080fd5b90870190610120828a0312156200040357600080fd5b6200040d620002cf565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c0830151828111156200045657600080fd5b620004648b828601620002fb565b60c08301525060e08381015190820152610100928301519281019290925250945062000493602087016200039f565b9350620004a3604087016200039f565b9250620004b3606087016200039f565b9150608086015190509295509295909350565b634e487b7160e01b600052603260045260246000fd5b600060018201620004fd57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161231c620006306000396000818161036401528181611030015281816114a50152818161192e015261197201526000818161025801526118b401526000818161039e0152610d3b015260008181610486015281816107cc01528181610af70152610f400152600081816104e201528181610bbf0152610bee0152600081816102b501528181610c350152610c690152600081816103160152610b7d01526000818161033d0152611cb10152600081816102dc015281816114580152611529015260008181610509015281816119a90152611a0001526000818161053001526117da01526000818161022301528181610a7e0152610ab2015261231c6000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c8063a694fc3a116100f9578063e1f1176d11610097578063eb338c9611610071578063eb338c9614610552578063f189e85a14610565578063f4dce7141461057a578063ffa1ad741461058257600080fd5b8063e1f1176d146104dd578063e77cdcc914610504578063eacdaabc1461052b57600080fd5b8063b6b55f25116100d3578063b6b55f2514610454578063c2c4c5c114610467578063cbcf252a14610481578063cd25fe38146104a857600080fd5b8063a694fc3a146103c9578063a74466ad146103dc578063b69ef8a81461044b57600080fd5b806356e760581161016657806372f702f31161014057806372f702f31461035f57806378e0613614610386578063809cee2f14610399578063879d9090146103c057600080fd5b806356e76058146102fe5780635829c5ec14610311578063592cf3fb1461033857600080fd5b80632e17de78116101a25780632e17de78146102925780633e732997146102a757806342cde4e8146102b057806352c824f5146102d757600080fd5b8063150b7a02146101c957806316a751721461021e5780632871405114610253575b600080fd5b6101e86101d7366004611d73565b630a85bd0160e11b95945050505050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020015b60405180910390f35b6102457f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610215565b61027a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610215565b6102a56102a0366004611e12565b6105b3565b005b61024560025481565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b61024561030c366004611e12565b610896565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b61027a7f000000000000000000000000000000000000000000000000000000000000000081565b610245610394366004611e12565b6108b7565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b61024560015481565b6102a56103d7366004611e12565b610a56565b6104206103ea366004611e12565b600460208190526000918252604090912080546001820154600383015492909301546001600160a01b0391821693909116919084565b604080516001600160a01b039586168152949093166020850152918301526060820152608001610215565b61024560005481565b6102a5610462366004611e12565b610ffd565b61046f61109f565b60405161021596959493929190611e66565b61027a7f000000000000000000000000000000000000000000000000000000000000000081565b6104cd6104b6366004611e12565b600090815260046020526040902060030154151590565b6040519015158152602001610215565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b610245610560366004611e12565b61139e565b61056d6113ae565b6040516102159190611f3e565b610245611454565b6105a6604051806040016040528060058152602001640302e312e360dc1b81525081565b6040516102159190611f51565b600081815260046020526040902060018101546001600160a01b0316331461060a57600181015460405163521eb56d60e11b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b60008061061561109f565b95505050505091508061062d5761062a6113ae565b91505b60005b825181101561066a578483828151811061064c5761064c611f9f565b6020026020010151031561066a5761066381611fcb565b9050610630565b600484015460028501805460408051602080840282018101909252828152600093909290918301828280156106be57602002820191906000526020600020905b8154815260200190600101908083116106aa575b5050506003890154895460008c8152600460205260408120805473ffffffffffffffffffffffffffffffffffffffff199081168255600182018054909116905595965091946001600160a01b039091169350915061071f6002830182611cdd565b506000600382018190556004909101556005805461073f90600190611fe4565b8154811061074f5761074f611f9f565b90600052602060002001546005868154811061076d5761076d611f9f565b600091825260209091200155600580548061078a5761078a611ff7565b600082815260208120820160001990810191909155019055604051632142170760e11b8152306004820152336024820152604481018a90526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90606401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b50505050600084111561083b5761083b8185611489565b806001600160a01b0316336001600160a01b03168a7f246ee6115bfd84e00097b16569c2ff2f822026bb9595a82cd2c1e69d4b6ea50c8688876040516108839392919061200d565b60405180910390a4505050505050505050565b600381815481106108a657600080fd5b600091825260209091200154905081565b6000818152600460209081526040808320815160a08101835281546001600160a01b039081168252600183015416818501526002820180548451818702810187018652818152879693958601939092919083018282801561093757602002820191906000526020600020905b815481526020019060010190808311610923575b505050505081526020016003820154815260200160048201548152505090508060800151915080606001516000036109855760405163e0606b6360e01b815260048101849052602401610601565b6000806000806000610995611512565b50509450945094509450945060005b84811015610a4a57888382815181106109bf576109bf611f9f565b602002602001015103610a3a5785841115610a155783868383815181106109e8576109e8611f9f565b60200260200101516109fa9190612032565b610a049190612049565b610a0e908961206b565b9750610a4a565b818181518110610a2757610a27611f9f565b602002602001015188610a0e919061206b565b610a4381611fcb565b90506109a4565b50505050505050919050565b600154600003610a795760405163afb0be3360e01b815260040160405180910390fd5b6005547f00000000000000000000000000000000000000000000000000000000000000008103610ade5760405163fd20861560e01b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610601565b60405163ef0e239b60e01b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef0e239b90602401600060405180830381865afa158015610b46573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b6e91908101906121a4565b9050806080015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014610bbd57604051637ad404bf60e11b815260048101849052602401610601565b7f000000000000000000000000000000000000000000000000000000000000000015801590610c10575080604001517f000000000000000000000000000000000000000000000000000000000000000014155b15610c3157604051637ad404bf60e11b815260048101849052602401610601565b60007f0000000000000000000000000000000000000000000000000000000000000000118015610c8b5750806060015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014155b15610cac57604051637ad404bf60e11b815260048101849052602401610601565b60048160c001516005811115610cc457610cc4612282565b14610d03578060c001516005811115610cdf57610cdf612282565b604051633c053f9d60e21b8152600481019190915260248101849052604401610601565b600081602001516001600160a01b0316803b806020016040519081016040528181526000908060200190933c805190602001209050807f000000000000000000000000000000000000000000000000000000000000000014610d8857602082015160405162a2307960e51b81526001600160a01b039091166004820152602401610601565b6003548015610e595760e083015151818114610dba57604051637ad404bf60e11b815260048101879052602401610601565b60005b81811015610e56578460e001518181518110610ddb57610ddb611f9f565b602002602001015163ffffffff1660038281548110610dfc57610dfc611f9f565b906000526020600020015414610e465760038181548110610e1f57610e1f611f9f565b9060005260206000200154604051632ab10b0b60e21b815260040161060191815260200190565b610e4f81611fcb565b9050610dbd565b50505b610e758584600001516bffffffffffffffffffffffff16611891565b600085815260046020908152604082209085015181546001600160a01b03821673ffffffffffffffffffffffffffffffffffffffff1991821617835560018301805490911633179055909190610eca90611a32565b8051909150610ee29060028401906020840190611cfe565b50426003830155600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db001879055604051632142170760e11b8152336004820152306024820152604481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342842e0e90606401600060405180830381600087803b158015610f8c57600080fd5b505af1158015610fa0573d6000803e3d6000fd5b5050505084602001516001600160a01b0316336001600160a01b0316887f5d43ac9b1b213902df90d405b0006308578486b6c62182c5df202ed572c844e484604051610fec9190611f3e565b60405180910390a450505050505050565b60008160005461100d919061206b565b905060008260015461101f919061206b565b6000839055600181905590506110577f0000000000000000000000000000000000000000000000000000000000000000333086611a43565b604080518481526020810184905290810182905233907f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e9060600160405180910390a2505050565b60608060006060806000806000806000806000806110bb611512565b965096509650965096509650965060008611156112bf5760008786111561122e5760008060015b8981101561118057888b8883815181106110fe576110fe611f9f565b60200260200101516111109190612032565b61111a9190612049565b9250611126838361206b565b915087818151811061113a5761113a611f9f565b602002602001015193508260046000868152602001908152602001600020600401600082825461116a919061206b565b90915550611179905081611fcb565b90506110e2565b50878a8760008151811061119657611196611f9f565b60200260200101516111a89190612032565b6111b29190612049565b91506111be828261206b565b9050866000815181106111d3576111d3611f9f565b60200260200101519250808a11156111fc576111ef818b611fe4565b6111f9908361206b565b91505b6000838152600460208190526040822001805484929061121d90849061206b565b9091555060009a506112b892505050565b60005b878110156112aa5785818151811061124b5761124b611f9f565b6020026020010151915084818151811061126757611267611f9f565b6020026020010151600460008481526020019081526020016000206004016000828254611294919061206b565b909155506112a3905081611fcb565b9050611231565b506112b58689611fe4565b97505b5060018790555b8051156113895760005b82518110156113465760008382815181106112e6576112e6611f9f565b6020026020010151905082828151811061130257611302611f9f565b6020026020010151600460008381526020019081526020016000206002019080519060200190611333929190611cfe565b50508061133f90611fcb565b90506112c9565b50426002556040805188815260208101889052600199507f21d81d5d656869e8ce3ba8d65526a2f0dbbcd3d36f5f9999eb7c84360e45eced910160405180910390a15b909c909b509399509097509550929350915050565b600581815481106108a657600080fd5b6005546060908067ffffffffffffffff8111156113cd576113cd61207e565b6040519080825280602002602001820160405280156113f6578160200160208202803683370190505b50915060005b8181101561144f576005818154811061141757611417611f9f565b906000526020600020015483828151811061143457611434611f9f565b602090810291909101015261144881611fcb565b90506113fc565b505090565b60007f0000000000000000000000000000000000000000000000000000000000000000600254611484919061206b565b905090565b8060008082825461149a9190611fe4565b909155506114cb90507f00000000000000000000000000000000000000000000000000000000000000008383611acd565b816001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243648260405161150691815260200190565b60405180910390a25050565b6002546001549060009081906060908190819081907f00000000000000000000000000000000000000000000000000000000000000006115528242611fe4565b101580156115605750600088115b15611887576005548067ffffffffffffffff8111156115815761158161207e565b6040519080825280602002602001820160405280156115aa578160200160208202803683370190505b5093508067ffffffffffffffff8111156115c6576115c661207e565b6040519080825280602002602001820160405280156115ef578160200160208202803683370190505b5095508067ffffffffffffffff81111561160b5761160b61207e565b604051908082528060200260200182016040528015611634578160200160208202803683370190505b5094508067ffffffffffffffff8111156116505761165061207e565b60405190808252806020026020018201604052801561168357816020015b606081526020019060019003908161166e5790505b50925060005b8181101561188457600581815481106116a4576116a4611f9f565b90600052602060002001548582815181106116c1576116c1611f9f565b6020026020010181815250506000600460008784815181106116e5576116e5611f9f565b60209081029190910181015182528101919091526040016000208054909150611716906001600160a01b0316611a32565b85838151811061172857611728611f9f565b60209081029190910101526003810154849081811115611746578091505b6117508242611fe4565b905060006117ca88868151811061176957611769611f9f565b6020026020010151856002018054806020026020016040519081016040528092919081815260200182805480156117bf57602002820191906000526020600020905b8154815260200190600101908083116117ab575b505050505084611b4a565b9050801561186f5760006117fe837f0000000000000000000000000000000000000000000000000000000000000000612032565b905061180a818e61206b565b9c50808b8f8151811061181f5761181f611f9f565b60200260200101818152505089868151811061183d5761183d611f9f565b60200260200101518c8f8151811061185757611857611f9f565b602090810291909101015261186b8e611fcb565b9d50505b505050508061187d90611fcb565b9050611689565b50505b5090919293949596565b604051633cebfa4f60e01b81526004810183905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633cebfa4f906024016040805180830381865afa1580156118fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191e9190612298565b91509150816001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146119a757604051630b80380d60e31b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015283166024820152604401610601565b7f0000000000000000000000000000000000000000000000000000000000000000816bffffffffffffffffffffffff161015611a2c57604051632b30b24760e21b81526bffffffffffffffffffffffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006024820152604401610601565b50505050565b6060611a3d82611b5f565b92915050565b60006040516323b872dd60e01b6000528460045283602452826044526020600060646000808a5af13d15601f3d1160016000511416171691506000606052806040525080611ac65760405163abae3d6d60e01b81526001600160a01b03808716600483015280861660248301528416604482015260648101839052608401610601565b5050505050565b600060405163a9059cbb60e01b6000528360045282602452602060006044600080895af13d15601f3d1160016000511416171691506000606052806040525080611a2c5760405163abae3d6d60e01b81526001600160a01b0380861660048301523060248301528416604482015260648101839052608401610601565b6000611b57848484611c07565b949350505050565b60408051600180825281830190925260609160208083019080368337019050509050816001600160a01b031663affed0e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be391906122cd565b81600081518110611bf657611bf6611f9f565b602002602001018181525050919050565b60008082118015611c4b575082600081518110611c2657611c26611f9f565b602002602001015184600081518110611c4157611c41611f9f565b6020026020010151115b15611cd65760008284600081518110611c6657611c66611f9f565b602002602001015186600081518110611c8157611c81611f9f565b6020026020010151611c939190611fe4565b611ca590670de0b6b3a7640000612032565b611caf9190612049565b7f000000000000000000000000000000000000000000000000000000000000000011159150505b9392505050565b5080546000825590600052602060002090810190611cfb9190611d49565b50565b828054828255906000526020600020908101928215611d39579160200282015b82811115611d39578251825591602001919060010190611d1e565b50611d45929150611d49565b5090565b5b80821115611d455760008155600101611d4a565b6001600160a01b0381168114611cfb57600080fd5b600080600080600060808688031215611d8b57600080fd5b8535611d9681611d5e565b94506020860135611da681611d5e565b935060408601359250606086013567ffffffffffffffff80821115611dca57600080fd5b818801915088601f830112611dde57600080fd5b813581811115611ded57600080fd5b896020828501011115611dff57600080fd5b9699959850939650602001949392505050565b600060208284031215611e2457600080fd5b5035919050565b600081518084526020808501945080840160005b83811015611e5b57815187529582019590820190600101611e3f565b509495945050505050565b60c081526000611e7960c0830189611e2b565b6020838203818501528189518084528284019150828160051b850101838c016000805b84811015611eef57878403601f19018652825180518086529088019088860190845b81811015611eda5783518352928a0192918a0191600101611ebe565b50509688019694505091860191600101611e9c565b5050508a60408801528681036060880152611f0a818b611e2b565b9450505050508281036080840152611f228186611e2b565b915050611f3360a083018415159052565b979650505050505050565b602081526000611cd66020830184611e2b565b600060208083528351808285015260005b81811015611f7e57858101830151858201604001528201611f62565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611fdd57611fdd611fb5565b5060010190565b81810381811115611a3d57611a3d611fb5565b634e487b7160e01b600052603160045260246000fd5b6060815260006120206060830186611e2b565b60208301949094525060400152919050565b8082028115828204841417611a3d57611a3d611fb5565b60008261206657634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115611a3d57611a3d611fb5565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156120b8576120b861207e565b60405290565b80516bffffffffffffffffffffffff811681146120da57600080fd5b919050565b80516120da81611d5e565b805163ffffffff811681146120da57600080fd5b8051600681106120da57600080fd5b600082601f83011261211e57600080fd5b8151602067ffffffffffffffff8083111561213b5761213b61207e565b8260051b604051601f19603f830116810181811084821117156121605761216061207e565b60405293845285810183019383810192508785111561217e57600080fd5b83870191505b84821015611f3357612195826120ea565b83529183019190830190612184565b6000602082840312156121b657600080fd5b815167ffffffffffffffff808211156121ce57600080fd5b9083019061010082860312156121e357600080fd5b6121eb612094565b6121f4836120be565b8152612202602084016120df565b60208201526040830151604082015261221d606084016120ea565b606082015261222e608084016120ea565b608082015261223f60a084016120ea565b60a082015261225060c084016120fe565b60c082015260e08301518281111561226757600080fd5b6122738782860161210d565b60e08301525095945050505050565b634e487b7160e01b600052602160045260246000fd5b600080604083850312156122ab57600080fd5b82516122b681611d5e565b91506122c4602084016120be565b90509250929050565b6000602082840312156122df57600080fd5b505191905056fea2646970667358221220892b3547cd047374259e7ce0b4c8c70e47fe8f83349b516cd97fa732cc75de9164736f6c63430008150033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101c45760003560e01c8063a694fc3a116100f9578063e1f1176d11610097578063eb338c9611610071578063eb338c9614610552578063f189e85a14610565578063f4dce7141461057a578063ffa1ad741461058257600080fd5b8063e1f1176d146104dd578063e77cdcc914610504578063eacdaabc1461052b57600080fd5b8063b6b55f25116100d3578063b6b55f2514610454578063c2c4c5c114610467578063cbcf252a14610481578063cd25fe38146104a857600080fd5b8063a694fc3a146103c9578063a74466ad146103dc578063b69ef8a81461044b57600080fd5b806356e760581161016657806372f702f31161014057806372f702f31461035f57806378e0613614610386578063809cee2f14610399578063879d9090146103c057600080fd5b806356e76058146102fe5780635829c5ec14610311578063592cf3fb1461033857600080fd5b80632e17de78116101a25780632e17de78146102925780633e732997146102a757806342cde4e8146102b057806352c824f5146102d757600080fd5b8063150b7a02146101c957806316a751721461021e5780632871405114610253575b600080fd5b6101e86101d7366004611d73565b630a85bd0160e11b95945050505050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020015b60405180910390f35b6102457f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610215565b61027a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610215565b6102a56102a0366004611e12565b6105b3565b005b61024560025481565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b61024561030c366004611e12565b610896565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b61027a7f000000000000000000000000000000000000000000000000000000000000000081565b610245610394366004611e12565b6108b7565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b61024560015481565b6102a56103d7366004611e12565b610a56565b6104206103ea366004611e12565b600460208190526000918252604090912080546001820154600383015492909301546001600160a01b0391821693909116919084565b604080516001600160a01b039586168152949093166020850152918301526060820152608001610215565b61024560005481565b6102a5610462366004611e12565b610ffd565b61046f61109f565b60405161021596959493929190611e66565b61027a7f000000000000000000000000000000000000000000000000000000000000000081565b6104cd6104b6366004611e12565b600090815260046020526040902060030154151590565b6040519015158152602001610215565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b610245610560366004611e12565b61139e565b61056d6113ae565b6040516102159190611f3e565b610245611454565b6105a6604051806040016040528060058152602001640302e312e360dc1b81525081565b6040516102159190611f51565b600081815260046020526040902060018101546001600160a01b0316331461060a57600181015460405163521eb56d60e11b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b60008061061561109f565b95505050505091508061062d5761062a6113ae565b91505b60005b825181101561066a578483828151811061064c5761064c611f9f565b6020026020010151031561066a5761066381611fcb565b9050610630565b600484015460028501805460408051602080840282018101909252828152600093909290918301828280156106be57602002820191906000526020600020905b8154815260200190600101908083116106aa575b5050506003890154895460008c8152600460205260408120805473ffffffffffffffffffffffffffffffffffffffff199081168255600182018054909116905595965091946001600160a01b039091169350915061071f6002830182611cdd565b506000600382018190556004909101556005805461073f90600190611fe4565b8154811061074f5761074f611f9f565b90600052602060002001546005868154811061076d5761076d611f9f565b600091825260209091200155600580548061078a5761078a611ff7565b600082815260208120820160001990810191909155019055604051632142170760e11b8152306004820152336024820152604481018a90526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90606401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b50505050600084111561083b5761083b8185611489565b806001600160a01b0316336001600160a01b03168a7f246ee6115bfd84e00097b16569c2ff2f822026bb9595a82cd2c1e69d4b6ea50c8688876040516108839392919061200d565b60405180910390a4505050505050505050565b600381815481106108a657600080fd5b600091825260209091200154905081565b6000818152600460209081526040808320815160a08101835281546001600160a01b039081168252600183015416818501526002820180548451818702810187018652818152879693958601939092919083018282801561093757602002820191906000526020600020905b815481526020019060010190808311610923575b505050505081526020016003820154815260200160048201548152505090508060800151915080606001516000036109855760405163e0606b6360e01b815260048101849052602401610601565b6000806000806000610995611512565b50509450945094509450945060005b84811015610a4a57888382815181106109bf576109bf611f9f565b602002602001015103610a3a5785841115610a155783868383815181106109e8576109e8611f9f565b60200260200101516109fa9190612032565b610a049190612049565b610a0e908961206b565b9750610a4a565b818181518110610a2757610a27611f9f565b602002602001015188610a0e919061206b565b610a4381611fcb565b90506109a4565b50505050505050919050565b600154600003610a795760405163afb0be3360e01b815260040160405180910390fd5b6005547f00000000000000000000000000000000000000000000000000000000000000008103610ade5760405163fd20861560e01b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610601565b60405163ef0e239b60e01b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef0e239b90602401600060405180830381865afa158015610b46573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b6e91908101906121a4565b9050806080015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014610bbd57604051637ad404bf60e11b815260048101849052602401610601565b7f000000000000000000000000000000000000000000000000000000000000000015801590610c10575080604001517f000000000000000000000000000000000000000000000000000000000000000014155b15610c3157604051637ad404bf60e11b815260048101849052602401610601565b60007f0000000000000000000000000000000000000000000000000000000000000000118015610c8b5750806060015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014155b15610cac57604051637ad404bf60e11b815260048101849052602401610601565b60048160c001516005811115610cc457610cc4612282565b14610d03578060c001516005811115610cdf57610cdf612282565b604051633c053f9d60e21b8152600481019190915260248101849052604401610601565b600081602001516001600160a01b0316803b806020016040519081016040528181526000908060200190933c805190602001209050807f000000000000000000000000000000000000000000000000000000000000000014610d8857602082015160405162a2307960e51b81526001600160a01b039091166004820152602401610601565b6003548015610e595760e083015151818114610dba57604051637ad404bf60e11b815260048101879052602401610601565b60005b81811015610e56578460e001518181518110610ddb57610ddb611f9f565b602002602001015163ffffffff1660038281548110610dfc57610dfc611f9f565b906000526020600020015414610e465760038181548110610e1f57610e1f611f9f565b9060005260206000200154604051632ab10b0b60e21b815260040161060191815260200190565b610e4f81611fcb565b9050610dbd565b50505b610e758584600001516bffffffffffffffffffffffff16611891565b600085815260046020908152604082209085015181546001600160a01b03821673ffffffffffffffffffffffffffffffffffffffff1991821617835560018301805490911633179055909190610eca90611a32565b8051909150610ee29060028401906020840190611cfe565b50426003830155600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db001879055604051632142170760e11b8152336004820152306024820152604481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342842e0e90606401600060405180830381600087803b158015610f8c57600080fd5b505af1158015610fa0573d6000803e3d6000fd5b5050505084602001516001600160a01b0316336001600160a01b0316887f5d43ac9b1b213902df90d405b0006308578486b6c62182c5df202ed572c844e484604051610fec9190611f3e565b60405180910390a450505050505050565b60008160005461100d919061206b565b905060008260015461101f919061206b565b6000839055600181905590506110577f0000000000000000000000000000000000000000000000000000000000000000333086611a43565b604080518481526020810184905290810182905233907f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e9060600160405180910390a2505050565b60608060006060806000806000806000806000806110bb611512565b965096509650965096509650965060008611156112bf5760008786111561122e5760008060015b8981101561118057888b8883815181106110fe576110fe611f9f565b60200260200101516111109190612032565b61111a9190612049565b9250611126838361206b565b915087818151811061113a5761113a611f9f565b602002602001015193508260046000868152602001908152602001600020600401600082825461116a919061206b565b90915550611179905081611fcb565b90506110e2565b50878a8760008151811061119657611196611f9f565b60200260200101516111a89190612032565b6111b29190612049565b91506111be828261206b565b9050866000815181106111d3576111d3611f9f565b60200260200101519250808a11156111fc576111ef818b611fe4565b6111f9908361206b565b91505b6000838152600460208190526040822001805484929061121d90849061206b565b9091555060009a506112b892505050565b60005b878110156112aa5785818151811061124b5761124b611f9f565b6020026020010151915084818151811061126757611267611f9f565b6020026020010151600460008481526020019081526020016000206004016000828254611294919061206b565b909155506112a3905081611fcb565b9050611231565b506112b58689611fe4565b97505b5060018790555b8051156113895760005b82518110156113465760008382815181106112e6576112e6611f9f565b6020026020010151905082828151811061130257611302611f9f565b6020026020010151600460008381526020019081526020016000206002019080519060200190611333929190611cfe565b50508061133f90611fcb565b90506112c9565b50426002556040805188815260208101889052600199507f21d81d5d656869e8ce3ba8d65526a2f0dbbcd3d36f5f9999eb7c84360e45eced910160405180910390a15b909c909b509399509097509550929350915050565b600581815481106108a657600080fd5b6005546060908067ffffffffffffffff8111156113cd576113cd61207e565b6040519080825280602002602001820160405280156113f6578160200160208202803683370190505b50915060005b8181101561144f576005818154811061141757611417611f9f565b906000526020600020015483828151811061143457611434611f9f565b602090810291909101015261144881611fcb565b90506113fc565b505090565b60007f0000000000000000000000000000000000000000000000000000000000000000600254611484919061206b565b905090565b8060008082825461149a9190611fe4565b909155506114cb90507f00000000000000000000000000000000000000000000000000000000000000008383611acd565b816001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243648260405161150691815260200190565b60405180910390a25050565b6002546001549060009081906060908190819081907f00000000000000000000000000000000000000000000000000000000000000006115528242611fe4565b101580156115605750600088115b15611887576005548067ffffffffffffffff8111156115815761158161207e565b6040519080825280602002602001820160405280156115aa578160200160208202803683370190505b5093508067ffffffffffffffff8111156115c6576115c661207e565b6040519080825280602002602001820160405280156115ef578160200160208202803683370190505b5095508067ffffffffffffffff81111561160b5761160b61207e565b604051908082528060200260200182016040528015611634578160200160208202803683370190505b5094508067ffffffffffffffff8111156116505761165061207e565b60405190808252806020026020018201604052801561168357816020015b606081526020019060019003908161166e5790505b50925060005b8181101561188457600581815481106116a4576116a4611f9f565b90600052602060002001548582815181106116c1576116c1611f9f565b6020026020010181815250506000600460008784815181106116e5576116e5611f9f565b60209081029190910181015182528101919091526040016000208054909150611716906001600160a01b0316611a32565b85838151811061172857611728611f9f565b60209081029190910101526003810154849081811115611746578091505b6117508242611fe4565b905060006117ca88868151811061176957611769611f9f565b6020026020010151856002018054806020026020016040519081016040528092919081815260200182805480156117bf57602002820191906000526020600020905b8154815260200190600101908083116117ab575b505050505084611b4a565b9050801561186f5760006117fe837f0000000000000000000000000000000000000000000000000000000000000000612032565b905061180a818e61206b565b9c50808b8f8151811061181f5761181f611f9f565b60200260200101818152505089868151811061183d5761183d611f9f565b60200260200101518c8f8151811061185757611857611f9f565b602090810291909101015261186b8e611fcb565b9d50505b505050508061187d90611fcb565b9050611689565b50505b5090919293949596565b604051633cebfa4f60e01b81526004810183905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633cebfa4f906024016040805180830381865afa1580156118fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191e9190612298565b91509150816001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146119a757604051630b80380d60e31b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015283166024820152604401610601565b7f0000000000000000000000000000000000000000000000000000000000000000816bffffffffffffffffffffffff161015611a2c57604051632b30b24760e21b81526bffffffffffffffffffffffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006024820152604401610601565b50505050565b6060611a3d82611b5f565b92915050565b60006040516323b872dd60e01b6000528460045283602452826044526020600060646000808a5af13d15601f3d1160016000511416171691506000606052806040525080611ac65760405163abae3d6d60e01b81526001600160a01b03808716600483015280861660248301528416604482015260648101839052608401610601565b5050505050565b600060405163a9059cbb60e01b6000528360045282602452602060006044600080895af13d15601f3d1160016000511416171691506000606052806040525080611a2c5760405163abae3d6d60e01b81526001600160a01b0380861660048301523060248301528416604482015260648101839052608401610601565b6000611b57848484611c07565b949350505050565b60408051600180825281830190925260609160208083019080368337019050509050816001600160a01b031663affed0e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be391906122cd565b81600081518110611bf657611bf6611f9f565b602002602001018181525050919050565b60008082118015611c4b575082600081518110611c2657611c26611f9f565b602002602001015184600081518110611c4157611c41611f9f565b6020026020010151115b15611cd65760008284600081518110611c6657611c66611f9f565b602002602001015186600081518110611c8157611c81611f9f565b6020026020010151611c939190611fe4565b611ca590670de0b6b3a7640000612032565b611caf9190612049565b7f000000000000000000000000000000000000000000000000000000000000000011159150505b9392505050565b5080546000825590600052602060002090810190611cfb9190611d49565b50565b828054828255906000526020600020908101928215611d39579160200282015b82811115611d39578251825591602001919060010190611d1e565b50611d45929150611d49565b5090565b5b80821115611d455760008155600101611d4a565b6001600160a01b0381168114611cfb57600080fd5b600080600080600060808688031215611d8b57600080fd5b8535611d9681611d5e565b94506020860135611da681611d5e565b935060408601359250606086013567ffffffffffffffff80821115611dca57600080fd5b818801915088601f830112611dde57600080fd5b813581811115611ded57600080fd5b896020828501011115611dff57600080fd5b9699959850939650602001949392505050565b600060208284031215611e2457600080fd5b5035919050565b600081518084526020808501945080840160005b83811015611e5b57815187529582019590820190600101611e3f565b509495945050505050565b60c081526000611e7960c0830189611e2b565b6020838203818501528189518084528284019150828160051b850101838c016000805b84811015611eef57878403601f19018652825180518086529088019088860190845b81811015611eda5783518352928a0192918a0191600101611ebe565b50509688019694505091860191600101611e9c565b5050508a60408801528681036060880152611f0a818b611e2b565b9450505050508281036080840152611f228186611e2b565b915050611f3360a083018415159052565b979650505050505050565b602081526000611cd66020830184611e2b565b600060208083528351808285015260005b81811015611f7e57858101830151858201604001528201611f62565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611fdd57611fdd611fb5565b5060010190565b81810381811115611a3d57611a3d611fb5565b634e487b7160e01b600052603160045260246000fd5b6060815260006120206060830186611e2b565b60208301949094525060400152919050565b8082028115828204841417611a3d57611a3d611fb5565b60008261206657634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115611a3d57611a3d611fb5565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156120b8576120b861207e565b60405290565b80516bffffffffffffffffffffffff811681146120da57600080fd5b919050565b80516120da81611d5e565b805163ffffffff811681146120da57600080fd5b8051600681106120da57600080fd5b600082601f83011261211e57600080fd5b8151602067ffffffffffffffff8083111561213b5761213b61207e565b8260051b604051601f19603f830116810181811084821117156121605761216061207e565b60405293845285810183019383810192508785111561217e57600080fd5b83870191505b84821015611f3357612195826120ea565b83529183019190830190612184565b6000602082840312156121b657600080fd5b815167ffffffffffffffff808211156121ce57600080fd5b9083019061010082860312156121e357600080fd5b6121eb612094565b6121f4836120be565b8152612202602084016120df565b60208201526040830151604082015261221d606084016120ea565b606082015261222e608084016120ea565b608082015261223f60a084016120ea565b60a082015261225060c084016120fe565b60c082015260e08301518281111561226757600080fd5b6122738782860161210d565b60e08301525095945050505050565b634e487b7160e01b600052602160045260246000fd5b600080604083850312156122ab57600080fd5b82516122b681611d5e565b91506122c4602084016120be565b90509250929050565b6000602082840312156122df57600080fd5b505191905056fea2646970667358221220892b3547cd047374259e7ce0b4c8c70e47fe8f83349b516cd97fa732cc75de9164736f6c63430008150033", + "bytecode": "0x6102606040523480156200001257600080fd5b506040516200383a3803806200383a833981016040819052620000359162000453565b8484828260000151600014806200004e57506020830151155b806200005c575060a0830151155b806200006a575060c0830151155b8062000078575060e0830151155b806200008657506060830151155b806200009457506080830151155b15620000b357604051637c946ed760e01b815260040160405180910390fd5b826080015183606001511015620000f5576060830151608084015160405163491a2bb160e01b8152600481019290925260248201526044015b60405180910390fd5b6002836040015110156200012d57604080840151905163491a2bb160e01b8152600481019190915260026024820152604401620000ec565b6001600160a01b038216620001555760405163d92e233d60e01b815260040160405180910390fd5b82516080908152602084015160a0908152604085015160c09081529185015160e0908152908501516101005290840151610120908152908401516101409081526001600160a01b0384166101a0529084015161016052830151610180526000805b846101000151518110156200029257818561010001518281518110620001e057620001e062000576565b6020026020010151116200022d57846101000151818151811062000208576200020862000576565b6020026020010151604051632ab10b0b60e21b8152600401620000ec91815260200190565b846101000151818151811062000247576200024762000576565b602090810291909101015160048054600181810183556000929092527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0182905590925001620001b6565b5081620002b257604051637c946ed760e01b815260040160405180910390fd5b6101c0829052610100516060850151620002cd91906200058c565b6101e052610100516080850151620002e691906200058c565b6102005250504260035550506001600160a01b03821615806200031057506001600160a01b038316155b156200032f5760405163d92e233d60e01b815260040160405180910390fd5b506001600160a01b0390811661024052166102205250620005b89050565b634e487b7160e01b600052604160045260246000fd5b60405161016081016001600160401b03811182821017156200038957620003896200034d565b60405290565b600082601f830112620003a157600080fd5b815160206001600160401b0380831115620003c057620003c06200034d565b8260051b604051601f19603f83011681018181108482111715620003e857620003e86200034d565b60405293845260208187018101949081019250878511156200040957600080fd5b6020870191505b848210156200042b5781518352918301919083019062000410565b979650505050505050565b80516001600160a01b03811681146200044e57600080fd5b919050565b600080600080600060a086880312156200046c57600080fd5b85516001600160401b03808211156200048457600080fd5b90870190610160828a0312156200049a57600080fd5b620004a462000363565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e082015261010080840151838111156200050357600080fd5b620005118c8287016200038f565b918301919091525061012083810151908201526101409283015192810192909252509450620005436020870162000436565b9350620005536040870162000436565b9250620005636060870162000436565b9150608086015190509295509295909350565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417620005b257634e487b7160e01b600052601160045260246000fd5b92915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161311962000721600039600081816104110152818161130901528181611c1401528181611d1e0152611d6201526000818161030501528181611ca40152611e0e01526000818161068e015281816118a50152611b1401526000818161024b0152818161074d015261079f01526000818161044b0152610fca0152600081816105cf01528181610a0101528181610d8601526111bd0152600081816105f601528181610e4e0152610e7d01526000818161036201528181610ec40152610ef80152600081816103c30152610e0c0152600081816103ea015261294a01526000818161038901528181611bc60152611fb80152600061049b01526000818161061d0152611d9901526000818161064401526122ae0152600081816102de01528181610d0d0152610d4101526131196000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c8063a0ed60e011610145578063cbcf252a116100bd578063eb338c961161008c578063f4dce71411610071578063f4dce71414610681578063f86ad2b614610689578063ffa1ad74146106b057600080fd5b8063eb338c9614610666578063f189e85a1461067957600080fd5b8063cbcf252a146105ca578063e1f1176d146105f1578063e77cdcc914610618578063eacdaabc1461063f57600080fd5b8063b69ef8a811610114578063c2c4c5c1116100f9578063c2c4c5c11461057e578063c889921d14610597578063cae2a5f0146105aa57600080fd5b8063b69ef8a814610562578063b6b55f251461056b57600080fd5b8063a0ed60e014610496578063a694fc3a146104bd578063a74466ad146104d0578063b15087601461054d57600080fd5b806352c824f5116101d857806372f702f3116101a7578063809cee2f1161018c578063809cee2f1461044657806382a8ea581461046d578063879d90901461048d57600080fd5b806372f702f31461040c57806378e061361461043357600080fd5b806352c824f51461038457806356e76058146103ab5780635829c5ec146103be578063592cf3fb146103e557600080fd5b8063287140511161021457806328714051146103005780632e17de781461033f5780633e7329971461035457806342cde4e81461035d57600080fd5b806308ae7e541461024657806314b19c5a14610280578063150b7a021461028957806316a75172146102d9575b600080fd5b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61026d60005481565b6102a8610297366004612a0a565b630a85bd0160e11b95945050505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610277565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610277565b61035261034d366004612aa9565b6106e1565b005b61026d60035481565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d6103b9366004612aa9565b610acf565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b61026d610441366004612aa9565b610af0565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61048061047b366004612aa9565b610bba565b6040516102779190612afe565b61026d60025481565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103526104cb366004612aa9565b610cb1565b61051a6104de366004612aa9565b6005602081905260009182526040909120805460018201546003830154600484015493909401546001600160a01b039283169492909116929085565b604080516001600160a01b039687168152959094166020860152928401919091526060830152608082015260a001610277565b61055561127e565b6040516102779190612b65565b61026d60015481565b610352610579366004612aa9565b6112d6565b610586611378565b604051610277959493929190612b78565b61026d6105a5366004612aa9565b6119ad565b6105bd6105b8366004612aa9565b611a69565b6040516102779190612c3d565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d610674366004612aa9565b611b5c565b610555611b6c565b61026d611bc2565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6106d4604051806040016040528060058152602001640302e312e360dc1b81525081565b6040516102779190612c65565b600081815260056020526040902060018101546001600160a01b0316331461073857600181015460405163521eb56d60e11b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b600381015460006107498242612cca565b90507f0000000000000000000000000000000000000000000000000000000000000000811115801561077d57506000600254115b156107cb5760405163ba2bbc6b60e01b815260048101859052602481018290527f0000000000000000000000000000000000000000000000000000000000000000604482015260640161072f565b6000806107d6611378565b945050505091508151600003610837576107ee611b6c565b9150815167ffffffffffffffff81111561080a5761080a612cdd565b604051908082528060200260200182016040528015610833578160200160208202803683370190505b5090505b6000805b8351821015610898578783838151811061085757610857612cf3565b60200260200101510315610898578784838151811061087857610878612cf3565b60200260200101510361088d57506001610898565b81600101915061083b565b600487015460028801805460408051602080840282018101909252828152600093909290918301828280156108ec57602002820191906000526020600020905b8154815260200190600101908083116108d8575b50508c5460008f8152600560205260408120805473ffffffffffffffffffffffffffffffffffffffff19908116825560018201805490911690559596506001600160a01b03909116949350915061094890506002830182612974565b506000600382018190556004820181905560059091015583156109d7576006805461097590600190612cca565b8154811061098557610985612cf3565b9060005260206000200154600686815481106109a3576109a3612cf3565b60009182526020909120015560068054806109c0576109c0612d09565b600190038181906000526020600020016000905590555b604051632142170760e11b8152306004820152336024820152604481018c90526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90606401600060405180830381600087803b158015610a4557600080fd5b505af1158015610a59573d6000803e3d6000fd5b505050506000831115610a7057610a708184611bf7565b806001600160a01b0316336001600160a01b03168c7f950733f4c0bf951b8e770f3cc619a4288e7b59b1236d59aeaf2c238488e8ae816000548688604051610aba93929190612d1f565b60405180910390a45050505050505050505050565b60048181548110610adf57600080fd5b600091825260209091200154905081565b6000818152600560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015610b7057602002820191906000526020600020905b815481526020019060010190808311610b5c575b505050505081526020016003820154815260200160048201548152602001600582015481525050905080608001519150610ba9836119ad565b610bb39083612d48565b9392505050565b610c056040518060c0016040528060006001600160a01b0316815260200160006001600160a01b03168152602001606081526020016000815260200160008152602001600081525090565b600082815260056020908152604091829020825160c08101845281546001600160a01b0390811682526001830154168184015260028201805485518186028101860187528181529295939493860193830182828015610c8357602002820191906000526020600020905b815481526020019060010190808311610c6f575b5050505050815260200160038201548152602001600482015481526020016005820154815250509050919050565b600254600003610cd45760405163afb0be3360e01b815260040160405180910390fd5b6000818152600560205260409020600381015415610d085760405163b4817ce760e01b81526004810183905260240161072f565b6006547f00000000000000000000000000000000000000000000000000000000000000008103610d6d5760405163fd20861560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015260240161072f565b60405163ef0e239b60e01b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef0e239b90602401600060405180830381865afa158015610dd5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dfd9190810190612e79565b9050806080015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014610e4c57604051637ad404bf60e11b81526004810185905260240161072f565b7f000000000000000000000000000000000000000000000000000000000000000015801590610e9f575080604001517f000000000000000000000000000000000000000000000000000000000000000014155b15610ec057604051637ad404bf60e11b81526004810185905260240161072f565b60007f0000000000000000000000000000000000000000000000000000000000000000118015610f1a5750806060015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014155b15610f3b57604051637ad404bf60e11b81526004810185905260240161072f565b60048160c001516005811115610f5357610f53612c27565b14610f92578060c001516005811115610f6e57610f6e612c27565b604051633c053f9d60e21b815260048101919091526024810185905260440161072f565b600081602001516001600160a01b0316803b806020016040519081016040528181526000908060200190933c805190602001209050807f00000000000000000000000000000000000000000000000000000000000000001461101757602082015160405162a2307960e51b81526001600160a01b03909116600482015260240161072f565b60045480156110e05760e08301515181811461104957604051637ad404bf60e11b81526004810188905260240161072f565b60005b818110156110dd578460e00151818151811061106a5761106a612cf3565b602002602001015163ffffffff166004828154811061108b5761108b612cf3565b9060005260206000200154146110d557600481815481106110ae576110ae612cf3565b9060005260206000200154604051632ab10b0b60e21b815260040161072f91815260200190565b60010161104c565b50505b6111018684600001516bffffffffffffffffffffffff168560e00151611c81565b602083015185546001600160a01b03821673ffffffffffffffffffffffffffffffffffffffff199182161787556001870180549091163317905560009061114790611f02565b805190915061115f9060028801906020840190612995565b50426003870155600680546001810182556000919091527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01879055604051632142170760e11b8152336004820152306024820152604481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342842e0e90606401600060405180830381600087803b15801561120957600080fd5b505af115801561121d573d6000803e3d6000fd5b5050505083602001516001600160a01b0316336001600160a01b0316887faa6b005b4958114a0c90492461c24af6525ae0178db7fbf44125ae9217c69ccb6000548560405161126d929190612f57565b60405180910390a450505050505050565b606060048054806020026020016040519081016040528092919081815260200182805480156112cc57602002820191906000526020600020905b8154815260200190600101908083116112b8575b5050505050905090565b6000816001546112e69190612d48565b90506000826002546112f89190612d48565b6001839055600281905590506113307f0000000000000000000000000000000000000000000000000000000000000000333086611f13565b604080518481526020810184905290810182905233907f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e9060600160405180910390a2505050565b6060806060806060600080600080600080600080611394611f9d565b97509750975097509750975097509750606080845167ffffffffffffffff8111156113c1576113c1612cdd565b6040519080825280602002602001820160405280156113ea578160200160208202803683370190505b509a506000891561177d578967ffffffffffffffff81111561140e5761140e612cdd565b604051908082528060200260200182016040528015611437578160200160208202803683370190505b5092508967ffffffffffffffff81111561145357611453612cdd565b60405190808252806020026020018201604052801561147c578160200160208202803683370190505b5091508a8911156116865760008060015b8c811015611579578b8e8b83815181106114a9576114a9612cf3565b60200260200101516114bb9190612f70565b6114c59190612f87565b92506114d18383612d48565b91508a81815181106114e5576114e5612cf3565b602002602001015193508a818151811061150157611501612cf3565b602002602001015186828151811061151b5761151b612cf3565b6020026020010181815250508285828151811061153a5761153a612cf3565b6020026020010181815250508260056000868152602001908152602001600020600401600082825461156c9190612d48565b909155505060010161148d565b508a8d8a60008151811061158f5761158f612cf3565b60200260200101516115a19190612f70565b6115ab9190612f87565b91506115b78282612d48565b9050896000815181106115cc576115cc612cf3565b60200260200101519250896000815181106115e9576115e9612cf3565b60200260200101518560008151811061160457611604612cf3565b602002602001018181525050808d111561162f57611622818e612cca565b61162c9083612d48565b91505b818460008151811061164357611643612cf3565b602002602001018181525050816005600085815260200190815260200160002060040160008282546116759190612d48565b9091555060009d5061177792505050565b60005b8a811015611769578881815181106116a3576116a3612cf3565b602002602001015191508881815181106116bf576116bf612cf3565b60200260200101518482815181106116d9576116d9612cf3565b6020026020010181815250508781815181106116f7576116f7612cf3565b602002602001015183828151811061171157611711612cf3565b60200260200101818152505087818151811061172f5761172f612cf3565b602002602001015160056000848152602001908152602001600020600401600082825461175c9190612d48565b9091555050600101611689565b50611774898c612cca565b9a505b60028b90555b855115611997576000995060005b8651811015611930578681815181106117a6576117a6612cf3565b602002602001015191508581815181106117c2576117c2612cf3565b60200260200101516005600084815260200190815260200160002060020190805190602001906117f3929190612995565b50600085828151811061180857611808612cf3565b602002602001015111156119155784818151811061182857611828612cf3565b602002602001015160056000848152602001908152602001600020600501546118519190612d48565b85828151811061186357611863612cf3565b60200260200101818152505084818151811061188157611881612cf3565b602002602001015160056000848152602001908152602001600020600501819055507f00000000000000000000000000000000000000000000000000000000000000008582815181106118d6576118d6612cf3565b6020026020010151111561191057818d82815181106118f7576118f7612cf3565b60209081029190910101528a61190c81612fa9565b9b50505b611928565b6000828152600560208190526040822001555b60010161178b565b508915611942576119428c858c61239b565b42600355600054611954816001612d48565b60005560405181907f06a98bdd4732811ab3214800ed1ada2dce66a2bce301d250c3ca7d6b461ee6669061198d908f9088908890612fc2565b60405180910390a2505b50939e929d509b50919950969750505050505050565b6000806000806000806119be611f9d565b5050509450945094509450945060005b84811015611a5e57878382815181106119e9576119e9612cf3565b602002602001015103611a565785841115611a35578386838381518110611a1257611a12612cf3565b6020026020010151611a249190612f70565b611a2e9190612f87565b9650611a5e565b818181518110611a4757611a47612cf3565b60200260200101519650611a5e565b6001016119ce565b505050505050919050565b6000818152600560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015611ae957602002820191906000526020600020905b815481526020019060010190808311611ad5575b50505050508152602001600382015481526020016004820154815260200160058201548152505090507f00000000000000000000000000000000000000000000000000000000000000008160a001511115611b475760029150611b56565b606081015115611b5657600191505b50919050565b60068181548110610adf57600080fd5b606060068054806020026020016040519081016040528092919081815260200182805480156112cc57602002820191906000526020600020908154815260200190600101908083116112b8575050505050905090565b60007f0000000000000000000000000000000000000000000000000000000000000000600354611bf29190612d48565b905090565b8060016000828254611c099190612cca565b90915550611c3a90507f00000000000000000000000000000000000000000000000000000000000000008383612760565b816001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436482604051611c7591815260200190565b60405180910390a25050565b604051633cebfa4f60e01b81526004810184905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633cebfa4f906024016040805180830381865afa158015611cea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0e9190612ff7565b91509150816001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614611d9757604051630b80380d60e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301528316602482015260440161072f565b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff8216811115611dfe57604051632b30b24760e21b81526bffffffffffffffffffffffff831660048201526024810182905260440161072f565b60005b8451811015611ef95760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166375c1f93489888581518110611e4e57611e4e612cf3565b60200260200101516040518363ffffffff1660e01b8152600401611e8292919091825263ffffffff16602082015260400190565b602060405180830381865afa158015611e9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec3919061302c565b905082811015611ef057604051632b30b24760e21b8152600481018290526024810184905260440161072f565b50600101611e01565b50505050505050565b6060611f0d826127e3565b92915050565b60006040516323b872dd60e01b6000528460045283602452826044526020600060646000808a5af13d15601f3d1160016000511416171691506000606052806040525080611f965760405163abae3d6d60e01b81526001600160a01b0380871660048301528086166024830152841660448201526064810183905260840161072f565b5050505050565b600080600060608060608060606000600354905060025498507f00000000000000000000000000000000000000000000000000000000000000008142611fe39190612cca565b10158015611ff15750600089115b15612390576006548067ffffffffffffffff81111561201257612012612cdd565b60405190808252806020026020018201604052801561203b578160200160208202803683370190505b5094508067ffffffffffffffff81111561205757612057612cdd565b604051908082528060200260200182016040528015612080578160200160208202803683370190505b5096508067ffffffffffffffff81111561209c5761209c612cdd565b6040519080825280602002602001820160405280156120c5578160200160208202803683370190505b5095508067ffffffffffffffff8111156120e1576120e1612cdd565b60405190808252806020026020018201604052801561211457816020015b60608152602001906001900390816120ff5790505b5093508067ffffffffffffffff81111561213057612130612cdd565b604051908082528060200260200182016040528015612159578160200160208202803683370190505b50925060005b8181101561238d576006818154811061217a5761217a612cf3565b906000526020600020015486828151811061219757612197612cf3565b6020026020010181815250506000600560008884815181106121bb576121bb612cf3565b602090810291909101810151825281019190915260400160002080549091506121ec906001600160a01b0316611f02565b8683815181106121fe576121fe612cf3565b6020908102919091010152600381015484908181111561221c578091505b6122268242612cca565b905060006122a089868151811061223f5761223f612cf3565b60200260200101518560020180548060200260200160405190810160405280929190818152602001828054801561229557602002820191906000526020600020905b815481526020019060010190808311612281575b50505050508461288b565b9050801561235e576122d2827f0000000000000000000000000000000000000000000000000000000000000000612f70565b8b8f815181106122e4576122e4612cf3565b6020026020010181815250508a8e8151811061230257612302612cf3565b60200260200101518d6123159190612d48565b9c5089858151811061232957612329612cf3565b60200260200101518c8f8151811061234357612343612cf3565b60209081029190910101526123578e612fa9565b9d5061237e565b8188868151811061237157612371612cf3565b6020026020010181815250505b5050505080600101905061215f565b50505b509091929394959697565b825160008267ffffffffffffffff8111156123b8576123b8612cdd565b6040519080825280602002602001820160405280156123e1578160200160208202803683370190505b50905060008367ffffffffffffffff8111156123ff576123ff612cdd565b604051908082528060200260200182016040528015612428578160200160208202803683370190505b50905060008467ffffffffffffffff81111561244657612446612cdd565b60405190808252806020026020018201604052801561246f578160200160208202803683370190505b50905060008567ffffffffffffffff81111561248d5761248d612cdd565b6040519080825280602002602001820160405280156124b6578160200160208202803683370190505b50905060008667ffffffffffffffff8111156124d4576124d4612cdd565b6040519080825280602002602001820160405280156124fd578160200160208202803683370190505b50905060008060005b8881101561265d5760008c828151811061252257612522612cf3565b60200260200101511115612655578b818151811061254257612542612cf3565b602002602001015191508188848151811061255f5761255f612cf3565b6020908102919091018101919091526000838152600590915260409020600181015488516001600160a01b03909116908990869081106125a1576125a1612cf3565b6001600160a01b039283166020918202929092010152815488519116908890869081106125d0576125d0612cf3565b60200260200101906001600160a01b031690816001600160a01b0316815250508b828151811061260257612602612cf3565b602002602001015186858151811061261c5761261c612cf3565b6020026020010181815250508185858151811061263b5761263b612cf3565b60209081029190910101528361265081612fa9565b945050505b600101612506565b50885b8015612712578861267081613045565b99506000905084612682600184612cca565b8151811061269257612692612cf3565b6020026020010151905060068a815481106126af576126af612cf3565b9060005260206000200154600682815481106126cd576126cd612cf3565b60009182526020909120015560068054806126ea576126ea612d09565b60019003818190600052602060002001600090559055508061270b90613045565b9050612660565b506000547fd19a3d42ed383465e4058c322d9411aeac76ddb8454d22e139fc99808bd569528888888860405161274b9493929190613096565b60405180910390a25050505050505050505050565b600060405163a9059cbb60e01b6000528360045282602452602060006044600080895af13d15601f3d11600160005114161716915060006060528060405250806127dd5760405163abae3d6d60e01b81526001600160a01b038086166004830152306024830152841660448201526064810183905260840161072f565b50505050565b60408051600180825281830190925260609160208083019080368337019050509050816001600160a01b031663affed0e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612843573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612867919061302c565b8160008151811061287a5761287a612cf3565b602002602001018181525050919050565b60006128988484846128a0565b949350505050565b600080821180156128e45750826000815181106128bf576128bf612cf3565b6020026020010151846000815181106128da576128da612cf3565b6020026020010151115b15610bb357600082846000815181106128ff576128ff612cf3565b60200260200101518660008151811061291a5761291a612cf3565b602002602001015161292c9190612cca565b61293e90670de0b6b3a7640000612f70565b6129489190612f87565b7f0000000000000000000000000000000000000000000000000000000000000000111595945050505050565b508054600082559060005260206000209081019061299291906129e0565b50565b8280548282559060005260206000209081019282156129d0579160200282015b828111156129d05782518255916020019190600101906129b5565b506129dc9291506129e0565b5090565b5b808211156129dc57600081556001016129e1565b6001600160a01b038116811461299257600080fd5b600080600080600060808688031215612a2257600080fd5b8535612a2d816129f5565b94506020860135612a3d816129f5565b935060408601359250606086013567ffffffffffffffff80821115612a6157600080fd5b818801915088601f830112612a7557600080fd5b813581811115612a8457600080fd5b896020828501011115612a9657600080fd5b9699959850939650602001949392505050565b600060208284031215612abb57600080fd5b5035919050565b60008151808452602080850194506020840160005b83811015612af357815187529582019590820190600101612ad7565b509495945050505050565b6020815260006001600160a01b0380845116602084015280602085015116604084015250604083015160c06060840152612b3b60e0840182612ac2565b905060608401516080840152608084015160a084015260a084015160c08401528091505092915050565b602081526000610bb36020830184612ac2565b60a081526000612b8b60a0830188612ac2565b6020838203818501528188518084528284019150828160051b850101838b0160005b83811015612bdb57601f19878403018552612bc9838351612ac2565b94860194925090850190600101612bad565b50508681036040880152612bef818b612ac2565b9450505050508281036060840152612c078186612ac2565b90508281036080840152612c1b8185612ac2565b98975050505050505050565b634e487b7160e01b600052602160045260246000fd5b6020810160038310612c5f57634e487b7160e01b600052602160045260246000fd5b91905290565b60006020808352835180602085015260005b81811015612c9357858101830151858201604001528201612c77565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115611f0d57611f0d612cb4565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b838152606060208201526000612d386060830185612ac2565b9050826040830152949350505050565b80820180821115611f0d57611f0d612cb4565b604051610100810167ffffffffffffffff81118282101715612d7f57612d7f612cdd565b60405290565b80516bffffffffffffffffffffffff81168114612da157600080fd5b919050565b8051612da1816129f5565b805163ffffffff81168114612da157600080fd5b805160068110612da157600080fd5b600082601f830112612de557600080fd5b8151602067ffffffffffffffff80831115612e0257612e02612cdd565b8260051b604051601f19603f83011681018181108482111715612e2757612e27612cdd565b6040529384526020818701810194908101925087851115612e4757600080fd5b6020870191505b84821015612e6e57612e5f82612db1565b83529183019190830190612e4e565b979650505050505050565b600060208284031215612e8b57600080fd5b815167ffffffffffffffff80821115612ea357600080fd5b908301906101008286031215612eb857600080fd5b612ec0612d5b565b612ec983612d85565b8152612ed760208401612da6565b602082015260408301516040820152612ef260608401612db1565b6060820152612f0360808401612db1565b6080820152612f1460a08401612db1565b60a0820152612f2560c08401612dc5565b60c082015260e083015182811115612f3c57600080fd5b612f4887828601612dd4565b60e08301525095945050505050565b8281526040602082015260006128986040830184612ac2565b8082028115828204841417611f0d57611f0d612cb4565b600082612fa457634e487b7160e01b600052601260045260246000fd5b500490565b600060018201612fbb57612fbb612cb4565b5060010190565b838152606060208201526000612fdb6060830185612ac2565b8281036040840152612fed8185612ac2565b9695505050505050565b6000806040838503121561300a57600080fd5b8251613015816129f5565b915061302360208401612d85565b90509250929050565b60006020828403121561303e57600080fd5b5051919050565b60008161305457613054612cb4565b506000190190565b60008151808452602080850194506020840160005b83811015612af35781516001600160a01b031687529582019590820190600101613071565b6080815260006130a96080830187612ac2565b82810360208401526130bb818761305c565b905082810360408401526130cf818661305c565b90508281036060840152612e6e8185612ac256fea26469706673582212201cbb3243bdf2246a74a754c4b24385dc52b256b192f67778a3b3a76648374a5864736f6c63430008170033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102415760003560e01c8063a0ed60e011610145578063cbcf252a116100bd578063eb338c961161008c578063f4dce71411610071578063f4dce71414610681578063f86ad2b614610689578063ffa1ad74146106b057600080fd5b8063eb338c9614610666578063f189e85a1461067957600080fd5b8063cbcf252a146105ca578063e1f1176d146105f1578063e77cdcc914610618578063eacdaabc1461063f57600080fd5b8063b69ef8a811610114578063c2c4c5c1116100f9578063c2c4c5c11461057e578063c889921d14610597578063cae2a5f0146105aa57600080fd5b8063b69ef8a814610562578063b6b55f251461056b57600080fd5b8063a0ed60e014610496578063a694fc3a146104bd578063a74466ad146104d0578063b15087601461054d57600080fd5b806352c824f5116101d857806372f702f3116101a7578063809cee2f1161018c578063809cee2f1461044657806382a8ea581461046d578063879d90901461048d57600080fd5b806372f702f31461040c57806378e061361461043357600080fd5b806352c824f51461038457806356e76058146103ab5780635829c5ec146103be578063592cf3fb146103e557600080fd5b8063287140511161021457806328714051146103005780632e17de781461033f5780633e7329971461035457806342cde4e81461035d57600080fd5b806308ae7e541461024657806314b19c5a14610280578063150b7a021461028957806316a75172146102d9575b600080fd5b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61026d60005481565b6102a8610297366004612a0a565b630a85bd0160e11b95945050505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610277565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610277565b61035261034d366004612aa9565b6106e1565b005b61026d60035481565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d6103b9366004612aa9565b610acf565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b61026d610441366004612aa9565b610af0565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61048061047b366004612aa9565b610bba565b6040516102779190612afe565b61026d60025481565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103526104cb366004612aa9565b610cb1565b61051a6104de366004612aa9565b6005602081905260009182526040909120805460018201546003830154600484015493909401546001600160a01b039283169492909116929085565b604080516001600160a01b039687168152959094166020860152928401919091526060830152608082015260a001610277565b61055561127e565b6040516102779190612b65565b61026d60015481565b610352610579366004612aa9565b6112d6565b610586611378565b604051610277959493929190612b78565b61026d6105a5366004612aa9565b6119ad565b6105bd6105b8366004612aa9565b611a69565b6040516102779190612c3d565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d610674366004612aa9565b611b5c565b610555611b6c565b61026d611bc2565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6106d4604051806040016040528060058152602001640302e312e360dc1b81525081565b6040516102779190612c65565b600081815260056020526040902060018101546001600160a01b0316331461073857600181015460405163521eb56d60e11b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b600381015460006107498242612cca565b90507f0000000000000000000000000000000000000000000000000000000000000000811115801561077d57506000600254115b156107cb5760405163ba2bbc6b60e01b815260048101859052602481018290527f0000000000000000000000000000000000000000000000000000000000000000604482015260640161072f565b6000806107d6611378565b945050505091508151600003610837576107ee611b6c565b9150815167ffffffffffffffff81111561080a5761080a612cdd565b604051908082528060200260200182016040528015610833578160200160208202803683370190505b5090505b6000805b8351821015610898578783838151811061085757610857612cf3565b60200260200101510315610898578784838151811061087857610878612cf3565b60200260200101510361088d57506001610898565b81600101915061083b565b600487015460028801805460408051602080840282018101909252828152600093909290918301828280156108ec57602002820191906000526020600020905b8154815260200190600101908083116108d8575b50508c5460008f8152600560205260408120805473ffffffffffffffffffffffffffffffffffffffff19908116825560018201805490911690559596506001600160a01b03909116949350915061094890506002830182612974565b506000600382018190556004820181905560059091015583156109d7576006805461097590600190612cca565b8154811061098557610985612cf3565b9060005260206000200154600686815481106109a3576109a3612cf3565b60009182526020909120015560068054806109c0576109c0612d09565b600190038181906000526020600020016000905590555b604051632142170760e11b8152306004820152336024820152604481018c90526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90606401600060405180830381600087803b158015610a4557600080fd5b505af1158015610a59573d6000803e3d6000fd5b505050506000831115610a7057610a708184611bf7565b806001600160a01b0316336001600160a01b03168c7f950733f4c0bf951b8e770f3cc619a4288e7b59b1236d59aeaf2c238488e8ae816000548688604051610aba93929190612d1f565b60405180910390a45050505050505050505050565b60048181548110610adf57600080fd5b600091825260209091200154905081565b6000818152600560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015610b7057602002820191906000526020600020905b815481526020019060010190808311610b5c575b505050505081526020016003820154815260200160048201548152602001600582015481525050905080608001519150610ba9836119ad565b610bb39083612d48565b9392505050565b610c056040518060c0016040528060006001600160a01b0316815260200160006001600160a01b03168152602001606081526020016000815260200160008152602001600081525090565b600082815260056020908152604091829020825160c08101845281546001600160a01b0390811682526001830154168184015260028201805485518186028101860187528181529295939493860193830182828015610c8357602002820191906000526020600020905b815481526020019060010190808311610c6f575b5050505050815260200160038201548152602001600482015481526020016005820154815250509050919050565b600254600003610cd45760405163afb0be3360e01b815260040160405180910390fd5b6000818152600560205260409020600381015415610d085760405163b4817ce760e01b81526004810183905260240161072f565b6006547f00000000000000000000000000000000000000000000000000000000000000008103610d6d5760405163fd20861560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015260240161072f565b60405163ef0e239b60e01b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef0e239b90602401600060405180830381865afa158015610dd5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dfd9190810190612e79565b9050806080015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014610e4c57604051637ad404bf60e11b81526004810185905260240161072f565b7f000000000000000000000000000000000000000000000000000000000000000015801590610e9f575080604001517f000000000000000000000000000000000000000000000000000000000000000014155b15610ec057604051637ad404bf60e11b81526004810185905260240161072f565b60007f0000000000000000000000000000000000000000000000000000000000000000118015610f1a5750806060015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014155b15610f3b57604051637ad404bf60e11b81526004810185905260240161072f565b60048160c001516005811115610f5357610f53612c27565b14610f92578060c001516005811115610f6e57610f6e612c27565b604051633c053f9d60e21b815260048101919091526024810185905260440161072f565b600081602001516001600160a01b0316803b806020016040519081016040528181526000908060200190933c805190602001209050807f00000000000000000000000000000000000000000000000000000000000000001461101757602082015160405162a2307960e51b81526001600160a01b03909116600482015260240161072f565b60045480156110e05760e08301515181811461104957604051637ad404bf60e11b81526004810188905260240161072f565b60005b818110156110dd578460e00151818151811061106a5761106a612cf3565b602002602001015163ffffffff166004828154811061108b5761108b612cf3565b9060005260206000200154146110d557600481815481106110ae576110ae612cf3565b9060005260206000200154604051632ab10b0b60e21b815260040161072f91815260200190565b60010161104c565b50505b6111018684600001516bffffffffffffffffffffffff168560e00151611c81565b602083015185546001600160a01b03821673ffffffffffffffffffffffffffffffffffffffff199182161787556001870180549091163317905560009061114790611f02565b805190915061115f9060028801906020840190612995565b50426003870155600680546001810182556000919091527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01879055604051632142170760e11b8152336004820152306024820152604481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342842e0e90606401600060405180830381600087803b15801561120957600080fd5b505af115801561121d573d6000803e3d6000fd5b5050505083602001516001600160a01b0316336001600160a01b0316887faa6b005b4958114a0c90492461c24af6525ae0178db7fbf44125ae9217c69ccb6000548560405161126d929190612f57565b60405180910390a450505050505050565b606060048054806020026020016040519081016040528092919081815260200182805480156112cc57602002820191906000526020600020905b8154815260200190600101908083116112b8575b5050505050905090565b6000816001546112e69190612d48565b90506000826002546112f89190612d48565b6001839055600281905590506113307f0000000000000000000000000000000000000000000000000000000000000000333086611f13565b604080518481526020810184905290810182905233907f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e9060600160405180910390a2505050565b6060806060806060600080600080600080600080611394611f9d565b97509750975097509750975097509750606080845167ffffffffffffffff8111156113c1576113c1612cdd565b6040519080825280602002602001820160405280156113ea578160200160208202803683370190505b509a506000891561177d578967ffffffffffffffff81111561140e5761140e612cdd565b604051908082528060200260200182016040528015611437578160200160208202803683370190505b5092508967ffffffffffffffff81111561145357611453612cdd565b60405190808252806020026020018201604052801561147c578160200160208202803683370190505b5091508a8911156116865760008060015b8c811015611579578b8e8b83815181106114a9576114a9612cf3565b60200260200101516114bb9190612f70565b6114c59190612f87565b92506114d18383612d48565b91508a81815181106114e5576114e5612cf3565b602002602001015193508a818151811061150157611501612cf3565b602002602001015186828151811061151b5761151b612cf3565b6020026020010181815250508285828151811061153a5761153a612cf3565b6020026020010181815250508260056000868152602001908152602001600020600401600082825461156c9190612d48565b909155505060010161148d565b508a8d8a60008151811061158f5761158f612cf3565b60200260200101516115a19190612f70565b6115ab9190612f87565b91506115b78282612d48565b9050896000815181106115cc576115cc612cf3565b60200260200101519250896000815181106115e9576115e9612cf3565b60200260200101518560008151811061160457611604612cf3565b602002602001018181525050808d111561162f57611622818e612cca565b61162c9083612d48565b91505b818460008151811061164357611643612cf3565b602002602001018181525050816005600085815260200190815260200160002060040160008282546116759190612d48565b9091555060009d5061177792505050565b60005b8a811015611769578881815181106116a3576116a3612cf3565b602002602001015191508881815181106116bf576116bf612cf3565b60200260200101518482815181106116d9576116d9612cf3565b6020026020010181815250508781815181106116f7576116f7612cf3565b602002602001015183828151811061171157611711612cf3565b60200260200101818152505087818151811061172f5761172f612cf3565b602002602001015160056000848152602001908152602001600020600401600082825461175c9190612d48565b9091555050600101611689565b50611774898c612cca565b9a505b60028b90555b855115611997576000995060005b8651811015611930578681815181106117a6576117a6612cf3565b602002602001015191508581815181106117c2576117c2612cf3565b60200260200101516005600084815260200190815260200160002060020190805190602001906117f3929190612995565b50600085828151811061180857611808612cf3565b602002602001015111156119155784818151811061182857611828612cf3565b602002602001015160056000848152602001908152602001600020600501546118519190612d48565b85828151811061186357611863612cf3565b60200260200101818152505084818151811061188157611881612cf3565b602002602001015160056000848152602001908152602001600020600501819055507f00000000000000000000000000000000000000000000000000000000000000008582815181106118d6576118d6612cf3565b6020026020010151111561191057818d82815181106118f7576118f7612cf3565b60209081029190910101528a61190c81612fa9565b9b50505b611928565b6000828152600560208190526040822001555b60010161178b565b508915611942576119428c858c61239b565b42600355600054611954816001612d48565b60005560405181907f06a98bdd4732811ab3214800ed1ada2dce66a2bce301d250c3ca7d6b461ee6669061198d908f9088908890612fc2565b60405180910390a2505b50939e929d509b50919950969750505050505050565b6000806000806000806119be611f9d565b5050509450945094509450945060005b84811015611a5e57878382815181106119e9576119e9612cf3565b602002602001015103611a565785841115611a35578386838381518110611a1257611a12612cf3565b6020026020010151611a249190612f70565b611a2e9190612f87565b9650611a5e565b818181518110611a4757611a47612cf3565b60200260200101519650611a5e565b6001016119ce565b505050505050919050565b6000818152600560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015611ae957602002820191906000526020600020905b815481526020019060010190808311611ad5575b50505050508152602001600382015481526020016004820154815260200160058201548152505090507f00000000000000000000000000000000000000000000000000000000000000008160a001511115611b475760029150611b56565b606081015115611b5657600191505b50919050565b60068181548110610adf57600080fd5b606060068054806020026020016040519081016040528092919081815260200182805480156112cc57602002820191906000526020600020908154815260200190600101908083116112b8575050505050905090565b60007f0000000000000000000000000000000000000000000000000000000000000000600354611bf29190612d48565b905090565b8060016000828254611c099190612cca565b90915550611c3a90507f00000000000000000000000000000000000000000000000000000000000000008383612760565b816001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436482604051611c7591815260200190565b60405180910390a25050565b604051633cebfa4f60e01b81526004810184905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633cebfa4f906024016040805180830381865afa158015611cea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0e9190612ff7565b91509150816001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614611d9757604051630b80380d60e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301528316602482015260440161072f565b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff8216811115611dfe57604051632b30b24760e21b81526bffffffffffffffffffffffff831660048201526024810182905260440161072f565b60005b8451811015611ef95760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166375c1f93489888581518110611e4e57611e4e612cf3565b60200260200101516040518363ffffffff1660e01b8152600401611e8292919091825263ffffffff16602082015260400190565b602060405180830381865afa158015611e9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec3919061302c565b905082811015611ef057604051632b30b24760e21b8152600481018290526024810184905260440161072f565b50600101611e01565b50505050505050565b6060611f0d826127e3565b92915050565b60006040516323b872dd60e01b6000528460045283602452826044526020600060646000808a5af13d15601f3d1160016000511416171691506000606052806040525080611f965760405163abae3d6d60e01b81526001600160a01b0380871660048301528086166024830152841660448201526064810183905260840161072f565b5050505050565b600080600060608060608060606000600354905060025498507f00000000000000000000000000000000000000000000000000000000000000008142611fe39190612cca565b10158015611ff15750600089115b15612390576006548067ffffffffffffffff81111561201257612012612cdd565b60405190808252806020026020018201604052801561203b578160200160208202803683370190505b5094508067ffffffffffffffff81111561205757612057612cdd565b604051908082528060200260200182016040528015612080578160200160208202803683370190505b5096508067ffffffffffffffff81111561209c5761209c612cdd565b6040519080825280602002602001820160405280156120c5578160200160208202803683370190505b5095508067ffffffffffffffff8111156120e1576120e1612cdd565b60405190808252806020026020018201604052801561211457816020015b60608152602001906001900390816120ff5790505b5093508067ffffffffffffffff81111561213057612130612cdd565b604051908082528060200260200182016040528015612159578160200160208202803683370190505b50925060005b8181101561238d576006818154811061217a5761217a612cf3565b906000526020600020015486828151811061219757612197612cf3565b6020026020010181815250506000600560008884815181106121bb576121bb612cf3565b602090810291909101810151825281019190915260400160002080549091506121ec906001600160a01b0316611f02565b8683815181106121fe576121fe612cf3565b6020908102919091010152600381015484908181111561221c578091505b6122268242612cca565b905060006122a089868151811061223f5761223f612cf3565b60200260200101518560020180548060200260200160405190810160405280929190818152602001828054801561229557602002820191906000526020600020905b815481526020019060010190808311612281575b50505050508461288b565b9050801561235e576122d2827f0000000000000000000000000000000000000000000000000000000000000000612f70565b8b8f815181106122e4576122e4612cf3565b6020026020010181815250508a8e8151811061230257612302612cf3565b60200260200101518d6123159190612d48565b9c5089858151811061232957612329612cf3565b60200260200101518c8f8151811061234357612343612cf3565b60209081029190910101526123578e612fa9565b9d5061237e565b8188868151811061237157612371612cf3565b6020026020010181815250505b5050505080600101905061215f565b50505b509091929394959697565b825160008267ffffffffffffffff8111156123b8576123b8612cdd565b6040519080825280602002602001820160405280156123e1578160200160208202803683370190505b50905060008367ffffffffffffffff8111156123ff576123ff612cdd565b604051908082528060200260200182016040528015612428578160200160208202803683370190505b50905060008467ffffffffffffffff81111561244657612446612cdd565b60405190808252806020026020018201604052801561246f578160200160208202803683370190505b50905060008567ffffffffffffffff81111561248d5761248d612cdd565b6040519080825280602002602001820160405280156124b6578160200160208202803683370190505b50905060008667ffffffffffffffff8111156124d4576124d4612cdd565b6040519080825280602002602001820160405280156124fd578160200160208202803683370190505b50905060008060005b8881101561265d5760008c828151811061252257612522612cf3565b60200260200101511115612655578b818151811061254257612542612cf3565b602002602001015191508188848151811061255f5761255f612cf3565b6020908102919091018101919091526000838152600590915260409020600181015488516001600160a01b03909116908990869081106125a1576125a1612cf3565b6001600160a01b039283166020918202929092010152815488519116908890869081106125d0576125d0612cf3565b60200260200101906001600160a01b031690816001600160a01b0316815250508b828151811061260257612602612cf3565b602002602001015186858151811061261c5761261c612cf3565b6020026020010181815250508185858151811061263b5761263b612cf3565b60209081029190910101528361265081612fa9565b945050505b600101612506565b50885b8015612712578861267081613045565b99506000905084612682600184612cca565b8151811061269257612692612cf3565b6020026020010151905060068a815481106126af576126af612cf3565b9060005260206000200154600682815481106126cd576126cd612cf3565b60009182526020909120015560068054806126ea576126ea612d09565b60019003818190600052602060002001600090559055508061270b90613045565b9050612660565b506000547fd19a3d42ed383465e4058c322d9411aeac76ddb8454d22e139fc99808bd569528888888860405161274b9493929190613096565b60405180910390a25050505050505050505050565b600060405163a9059cbb60e01b6000528360045282602452602060006044600080895af13d15601f3d11600160005114161716915060006060528060405250806127dd5760405163abae3d6d60e01b81526001600160a01b038086166004830152306024830152841660448201526064810183905260840161072f565b50505050565b60408051600180825281830190925260609160208083019080368337019050509050816001600160a01b031663affed0e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612843573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612867919061302c565b8160008151811061287a5761287a612cf3565b602002602001018181525050919050565b60006128988484846128a0565b949350505050565b600080821180156128e45750826000815181106128bf576128bf612cf3565b6020026020010151846000815181106128da576128da612cf3565b6020026020010151115b15610bb357600082846000815181106128ff576128ff612cf3565b60200260200101518660008151811061291a5761291a612cf3565b602002602001015161292c9190612cca565b61293e90670de0b6b3a7640000612f70565b6129489190612f87565b7f0000000000000000000000000000000000000000000000000000000000000000111595945050505050565b508054600082559060005260206000209081019061299291906129e0565b50565b8280548282559060005260206000209081019282156129d0579160200282015b828111156129d05782518255916020019190600101906129b5565b506129dc9291506129e0565b5090565b5b808211156129dc57600081556001016129e1565b6001600160a01b038116811461299257600080fd5b600080600080600060808688031215612a2257600080fd5b8535612a2d816129f5565b94506020860135612a3d816129f5565b935060408601359250606086013567ffffffffffffffff80821115612a6157600080fd5b818801915088601f830112612a7557600080fd5b813581811115612a8457600080fd5b896020828501011115612a9657600080fd5b9699959850939650602001949392505050565b600060208284031215612abb57600080fd5b5035919050565b60008151808452602080850194506020840160005b83811015612af357815187529582019590820190600101612ad7565b509495945050505050565b6020815260006001600160a01b0380845116602084015280602085015116604084015250604083015160c06060840152612b3b60e0840182612ac2565b905060608401516080840152608084015160a084015260a084015160c08401528091505092915050565b602081526000610bb36020830184612ac2565b60a081526000612b8b60a0830188612ac2565b6020838203818501528188518084528284019150828160051b850101838b0160005b83811015612bdb57601f19878403018552612bc9838351612ac2565b94860194925090850190600101612bad565b50508681036040880152612bef818b612ac2565b9450505050508281036060840152612c078186612ac2565b90508281036080840152612c1b8185612ac2565b98975050505050505050565b634e487b7160e01b600052602160045260246000fd5b6020810160038310612c5f57634e487b7160e01b600052602160045260246000fd5b91905290565b60006020808352835180602085015260005b81811015612c9357858101830151858201604001528201612c77565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115611f0d57611f0d612cb4565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b838152606060208201526000612d386060830185612ac2565b9050826040830152949350505050565b80820180821115611f0d57611f0d612cb4565b604051610100810167ffffffffffffffff81118282101715612d7f57612d7f612cdd565b60405290565b80516bffffffffffffffffffffffff81168114612da157600080fd5b919050565b8051612da1816129f5565b805163ffffffff81168114612da157600080fd5b805160068110612da157600080fd5b600082601f830112612de557600080fd5b8151602067ffffffffffffffff80831115612e0257612e02612cdd565b8260051b604051601f19603f83011681018181108482111715612e2757612e27612cdd565b6040529384526020818701810194908101925087851115612e4757600080fd5b6020870191505b84821015612e6e57612e5f82612db1565b83529183019190830190612e4e565b979650505050505050565b600060208284031215612e8b57600080fd5b815167ffffffffffffffff80821115612ea357600080fd5b908301906101008286031215612eb857600080fd5b612ec0612d5b565b612ec983612d85565b8152612ed760208401612da6565b602082015260408301516040820152612ef260608401612db1565b6060820152612f0360808401612db1565b6080820152612f1460a08401612db1565b60a0820152612f2560c08401612dc5565b60c082015260e083015182811115612f3c57600080fd5b612f4887828601612dd4565b60e08301525095945050505050565b8281526040602082015260006128986040830184612ac2565b8082028115828204841417611f0d57611f0d612cb4565b600082612fa457634e487b7160e01b600052601260045260246000fd5b500490565b600060018201612fbb57612fbb612cb4565b5060010190565b838152606060208201526000612fdb6060830185612ac2565b8281036040840152612fed8185612ac2565b9695505050505050565b6000806040838503121561300a57600080fd5b8251613015816129f5565b915061302360208401612d85565b90509250929050565b60006020828403121561303e57600080fd5b5051919050565b60008161305457613054612cb4565b506000190190565b60008151808452602080850194506020840160005b83811015612af35781516001600160a01b031687529582019590820190600101613071565b6080815260006130a96080830187612ac2565b82810360208401526130bb818761305c565b905082810360408401526130cf818661305c565b90508281036060840152612e6e8185612ac256fea26469706673582212201cbb3243bdf2246a74a754c4b24385dc52b256b192f67778a3b3a76648374a5864736f6c63430008170033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/backend/operate/data/contracts/service_staking_token/contract.yaml b/backend/operate/data/contracts/service_staking_token/contract.yaml index 7a9c886a3..1b1d6b19b 100644 --- a/backend/operate/data/contracts/service_staking_token/contract.yaml +++ b/backend/operate/data/contracts/service_staking_token/contract.yaml @@ -7,8 +7,8 @@ license: Apache-2.0 aea_version: '>=1.0.0, <2.0.0' fingerprint: __init__.py: bafybeid3wfzglolebuo6jrrsopswzu4lk77bm76mvw3euizlsjtnt3wmgu - build/ServiceStakingToken.json: bafybeie2xbccvzmjuptqfqumctv6gtyyeoxe7fkx3t7fgbto7wbdugbqxm - contract.py: bafybeihhdg5mvd3jwc7q445ntdahaiyjpt2ne6ipkiaymycbrw5iwzuble + build/ServiceStakingToken.json: bafybeib6frfpqtr4dfyxuylehqmic2iawofydx7u24t7j5zbrsc4m4ijoi + contract.py: bafybeig26jfncdktpl6d46j7gkjernenw2c4hop7i2guadnsha4hnbhywq fingerprint_ignore_patterns: [] contracts: [] class_name: ServiceStakingTokenContract diff --git a/backend/operate/ledger/profiles.py b/backend/operate/ledger/profiles.py index 3f95407c8..cb24dc76f 100644 --- a/backend/operate/ledger/profiles.py +++ b/backend/operate/ledger/profiles.py @@ -35,7 +35,7 @@ } STAKING = { - ChainType.GNOSIS: "0x2Ef503950Be67a98746F484DA0bBAdA339DF3326", + ChainType.GNOSIS: "0xf8a415d761b1279B0f1ACE68cD85e5ca4346Cc3F", # "0x2Ef503950Be67a98746F484DA0bBAdA339DF3326", } OLAS = { diff --git a/backend/operate/services/manage.py b/backend/operate/services/manage.py index f46eeaaae..f59d6ceb1 100644 --- a/backend/operate/services/manage.py +++ b/backend/operate/services/manage.py @@ -183,10 +183,30 @@ def _create( ) if configuration["use_staking"] and not ocm.staking_slots_available( - staking_address=STAKING[ledger["chain"]], + staking_contract=STAKING[ledger["chain"]] ): raise ValueError("No staking slots available") + if configuration["use_staking"]: + required_olas = ( + configuration["olas_cost_of_bond"] + + configuration["olas_required_to_stake"] + ) + balance = ( + registry_contracts.erc20.get_instance( + ledger_api=ocm.ledger_api, + contract_address=OLAS[ledger["chain"]], + ) + .functions.balanceOf(ocm.crypto.address) + .call() + ) + + if balance < required_olas: + raise BadRequest( + "You don't have enough olas to stake, " + f"required olas: {required_olas}; your balance {balance}" + ) + # Update to user provided RPC ledger["rpc"] = configuration["rpc"] @@ -198,7 +218,7 @@ def _create( agent_id=configuration["agent_id"], number_of_slots=service.helper.config.number_of_agents, cost_of_bond=( - configuration["olas_required_to_bond"] + configuration["olas_cost_of_bond"] if configuration["use_staking"] else configuration["cost_of_bond"] ), @@ -210,25 +230,6 @@ def _create( ) logging.info(f"Activating service {phash}") - if configuration["use_staking"]: - required_olas = ( - configuration["olas_cost_of_bond"] - + configuration["olas_required_to_stake"] - ) - balance = ( - registry_contracts.erc20.get_instance( - ledger_api=ocm.ledger_api, - contract_address=OLAS[ledger["chain"]], - ) - .functions.balanceOf(ocm.crypto.address) - .call() - ) - if balance < required_olas: - raise BadRequest( - "You don't have enough olas to stake, " - f"required olas: {required_olas}; your balance {balance}" - ) - ocm.activate( service_id=service_id, token=OLAS[ledger["chain"]] if configuration["use_staking"] else None, diff --git a/backend/operate/services/protocol.py b/backend/operate/services/protocol.py index c875383ca..c97349e0f 100644 --- a/backend/operate/services/protocol.py +++ b/backend/operate/services/protocol.py @@ -193,7 +193,7 @@ def status(self, service_id: int, staking_contract: str) -> StakingState: ledger_api=self.ledger_api, contract_address=staking_contract, ) - .getServiceStakingState(service_id) + .functions.getServiceStakingState(service_id) .call() ) @@ -203,12 +203,17 @@ def slots_available(self, staking_contract: str) -> bool: ledger_api=self.ledger_api, contract_address=staking_contract, ) - return instance.maxNumServices().call() - len(instance.getServiceIds().call()) + available = instance.functions.maxNumServices().call() - len( + instance.functions.getServiceIds().call() + ) + return available > 0 def onchain_info(self, staking_contract: str, service_id: int) -> dict: """Get the service onchain info""" return self.staking_ctr.get_service_info( - self.ledger_api, staking_contract, service_id + self.ledger_api, + staking_contract, + service_id, ) def stake( @@ -246,6 +251,7 @@ def _build_approval_tx(*args, **kargs) -> t.Dict: ledger_api=self.ledger_api, contract_address=service_registry, spender=staking_contract, + sender=self.crypto.address, amount=service_id, ) @@ -258,15 +264,18 @@ def _build_approval_tx(*args, **kargs) -> t.Dict: ) def _build_staking_tx(*args, **kargs) -> t.Dict: - return { - "data": self.staking_ctr.build_stake_tx( + return self.ledger_api.build_transaction( + contract_instance=self.staking_ctr.get_instance( ledger_api=self.ledger_api, contract_address=staking_contract, - service_id=service_id, - ).pop("data"), - "to": staking_contract, - "value": ZERO_ETH, - } + ), + method_name="stake", + method_args={"serviceId": service_id}, + tx_args={ + "sender_address": self.crypto.address, + }, + raise_on_try=True, + ) setattr(tx_settler, "build", _build_staking_tx) tx_settler.transact( @@ -647,9 +656,10 @@ def unbond(self, service_id: int, token: t.Optional[str] = None) -> None: token=token, ).unbond_service() - def staking_slots_available(self, staking_contract: str) -> None: + def staking_slots_available(self, staking_contract: str) -> bool: """Stake service.""" - StakingManager( + self._patch() + return StakingManager( key=self.key, chain_type=self.chain_type, ).slots_available( @@ -663,6 +673,7 @@ def stake( staking_contract: str, ) -> None: """Stake service.""" + self._patch() StakingManager( key=self.key, chain_type=self.chain_type, @@ -674,6 +685,7 @@ def stake( def unstake(self, service_id: int, staking_contract: str) -> None: """Unstake service.""" + self._patch() StakingManager( key=self.key, chain_type=self.chain_type, diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 237352d0f..5f594ffa9 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -1,5 +1,5 @@ [tool.poetry] -name = "backend" +name = "operate" version = "0.1.0" description = "" authors = ["David Vilela "] diff --git a/templates/trader.yaml b/templates/trader.yaml index 3c255671c..449ed7b92 100644 --- a/templates/trader.yaml +++ b/templates/trader.yaml @@ -9,9 +9,8 @@ configuration: threshold: 1 # TODO: Move to service component use_staking: false # User provided cost_of_bond: 10000000000000000 - olas_cost_of_bond: 10000000000000000000 - olas_required_to_bond: 10000000000000000000 - olas_required_to_stake: 10000000000000000000 + olas_cost_of_bond: 1000000000000000000 + olas_required_to_stake: 1000000000000000000 fund_requirements: agent: 0.1 safe: 0.5 From 84c63f6e752e8b1943956f43fbdcd97682515b80 Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Mon, 19 Feb 2024 20:11:25 +0530 Subject: [PATCH 09/10] chore: revert to defaults --- backend/operate/ledger/profiles.py | 2 +- templates/trader.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/operate/ledger/profiles.py b/backend/operate/ledger/profiles.py index cb24dc76f..3f95407c8 100644 --- a/backend/operate/ledger/profiles.py +++ b/backend/operate/ledger/profiles.py @@ -35,7 +35,7 @@ } STAKING = { - ChainType.GNOSIS: "0xf8a415d761b1279B0f1ACE68cD85e5ca4346Cc3F", # "0x2Ef503950Be67a98746F484DA0bBAdA339DF3326", + ChainType.GNOSIS: "0x2Ef503950Be67a98746F484DA0bBAdA339DF3326", } OLAS = { diff --git a/templates/trader.yaml b/templates/trader.yaml index 449ed7b92..226d4e6f8 100644 --- a/templates/trader.yaml +++ b/templates/trader.yaml @@ -9,8 +9,8 @@ configuration: threshold: 1 # TODO: Move to service component use_staking: false # User provided cost_of_bond: 10000000000000000 - olas_cost_of_bond: 1000000000000000000 - olas_required_to_stake: 1000000000000000000 + olas_cost_of_bond: 10000000000000000000 + olas_required_to_stake: 10000000000000000000 fund_requirements: agent: 0.1 safe: 0.5 From 7e69191b822555381b22292e323b70bc139385f9 Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Tue, 20 Feb 2024 10:02:40 +0530 Subject: [PATCH 10/10] feat: intgrate unstaking --- backend/operate/services/manage.py | 14 ++++- backend/operate/services/protocol.py | 76 ++++++++++++++-------------- backend/operate/types.py | 7 +-- 3 files changed, 56 insertions(+), 41 deletions(-) diff --git a/backend/operate/services/manage.py b/backend/operate/services/manage.py index f59d6ceb1..dca5fe157 100644 --- a/backend/operate/services/manage.py +++ b/backend/operate/services/manage.py @@ -257,9 +257,9 @@ def _create( "token": service_id, "instances": info["instances"], "multisig": info["multisig"], + "staked": False, } ) - service.store() if configuration["use_staking"]: ocm.stake( @@ -267,6 +267,8 @@ def _create( service_registry=CONTRACTS[ledger["chain"]]["service_registry"], staking_contract=STAKING[ledger["chain"]], ) + service.chain_data["staked"] = True + service.store() logging.info(f"Building deployment for service {phash}") deployment = service.deployment() @@ -300,14 +302,24 @@ def update(self, data: PutServices) -> ServiceType: contracts=CONTRACTS[old.ledger["chain"]], ) + if old.chain_data["staked"]: + ocm.unstake( + service_id=old.chain_data["token"], + staking_contract=STAKING[old.ledger["chain"]], + ) + old.chain_data["staked"] = False + old.store() + # Terminate old service ocm.terminate( service_id=old.chain_data["token"], + token=OLAS[old.ledger["chain"]] if old.chain_data["staked"] else None, ) # Unbond old service ocm.unbond( service_id=old.chain_data["token"], + token=OLAS[old.ledger["chain"]] if old.chain_data["staked"] else None, ) # Swap owners on the old safe diff --git a/backend/operate/services/protocol.py b/backend/operate/services/protocol.py index c97349e0f..020106e9b 100644 --- a/backend/operate/services/protocol.py +++ b/backend/operate/services/protocol.py @@ -208,13 +208,13 @@ def slots_available(self, staking_contract: str) -> bool: ) return available > 0 - def onchain_info(self, staking_contract: str, service_id: int) -> dict: + def service_info(self, staking_contract: str, service_id: int) -> dict: """Get the service onchain info""" return self.staking_ctr.get_service_info( self.ledger_api, staking_contract, service_id, - ) + ).get("data") def stake( self, @@ -285,6 +285,30 @@ def _build_staking_tx(*args, **kargs) -> t.Dict: dry_run=False, ) + def _can_unstake_service( + self, + service_id: int, + staking_contract: str, + ) -> bool: + """Check unstaking availability""" + ts_start = t.cast(int, self.service_info(staking_contract, service_id)[3]) + available_rewards = t.cast( + int, + self.staking_ctr.available_rewards(self.ledger_api, staking_contract).get( + "data" + ), + ) + minimum_staking_duration = t.cast( + int, + self.staking_ctr.get_min_staking_duration( + self.ledger_api, staking_contract + ).get("data"), + ) + staked_duration = time.time() - ts_start + if staked_duration < minimum_staking_duration and available_rewards > 0: + return False + return True + def unstake(self, service_id: int, staking_contract: str) -> None: """Unstake the service""" if ( @@ -293,7 +317,7 @@ def unstake(self, service_id: int, staking_contract: str) -> None: ): raise ValueError("Service not staked.") - if not self.check_unstaking_availability(service_id, staking_contract): + if not self._can_unstake_service(service_id, staking_contract): raise ValueError("Service cannot be unstaked yet.") tx_settler = TxSettler( @@ -305,16 +329,19 @@ def unstake(self, service_id: int, staking_contract: str) -> None: sleep=self.sleep, ) - def _build_unstaking_tx() -> t.Dict: - self.staking_ctr.get_instance( - ledger_api=self.ledger_api, contract_address=staking_contract + def _build_unstaking_tx(*args, **kargs) -> t.Dict: + return self.ledger_api.build_transaction( + contract_instance=self.staking_ctr.get_instance( + ledger_api=self.ledger_api, + contract_address=staking_contract, + ), + method_name="unstake", + method_args={"serviceId": service_id}, + tx_args={ + "sender_address": self.crypto.address, + }, + raise_on_try=True, ) - data = self.staking_ctr.encodeABI("unstake", args=[service_id]) - return { - "data": bytes.fromhex(data[2:]), - "to": CONTRACTS[ChainType.GNOSIS]["ServiceStakingToken"], - "value": ZERO_ETH, - } setattr(tx_settler, "build", _build_unstaking_tx) tx_settler.transact( @@ -324,31 +351,6 @@ def _build_unstaking_tx() -> t.Dict: dry_run=False, ) - def check_unstaking_availability( - self, service_id: int, staking_contract: str - ) -> bool: - """Check unstaking availability""" - ts_start = t.cast( - int, self.onchain_info(staking_contract, service_id)["data"][3] - ) - available_rewards = t.cast( - int, - self.staking_ctr.available_rewards(self.ledger_api, staking_contract)[ - "data" - ], - ) - minimum_staking_duration = t.cast( - int, - self.staking_ctr.get_min_staking_duration( - self.ledger_api, staking_contract - )["data"], - ) - if ( - time.time() - ts_start - ) < minimum_staking_duration and available_rewards > 0: - return False - return True - class OnChainManager: """On chain service management.""" diff --git a/backend/operate/types.py b/backend/operate/types.py index 1a8a82c97..d21f043b4 100644 --- a/backend/operate/types.py +++ b/backend/operate/types.py @@ -142,9 +142,10 @@ class ServiceState(enum.IntEnum): class ChainData(TypedDict): """Chain data for service.""" - instances: NotRequired[t.List[str]] # Agent instances registered as safe owners - token: NotRequired[int] - multisig: NotRequired[str] + instances: t.List[str] # Agent instances registered as safe owners + token: int + multisig: str + staked: bool class ChainDeployment(TypedDict):