From 6834023917760bf7875cc7c107e0c59ad7925ef4 Mon Sep 17 00:00:00 2001 From: David Vilela Date: Wed, 14 Feb 2024 19:31:09 +0100 Subject: [PATCH 1/9] feat: staking support --- backend/operate/ledger/abis/ERC20.json | 288 ++++ .../ledger/abis/ServiceStakingToken.json | 1355 +++++++++++++++++ backend/operate/ledger/ethereum.py | 205 ++- backend/operate/ledger/profiles.py | 2 + 4 files changed, 1847 insertions(+), 3 deletions(-) create mode 100644 backend/operate/ledger/abis/ERC20.json create mode 100644 backend/operate/ledger/abis/ServiceStakingToken.json diff --git a/backend/operate/ledger/abis/ERC20.json b/backend/operate/ledger/abis/ERC20.json new file mode 100644 index 000000000..da6252cad --- /dev/null +++ b/backend/operate/ledger/abis/ERC20.json @@ -0,0 +1,288 @@ +{ + "_format": "", + "contractName": "", + "sourceName": "", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "guy", + "type": "address" + }, + { + "name": "wad", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "src", + "type": "address" + }, + { + "name": "dst", + "type": "address" + }, + { + "name": "wad", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "wad", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "dst", + "type": "address" + }, + { + "name": "wad", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "deposit", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "src", + "type": "address" + }, + { + "indexed": true, + "name": "guy", + "type": "address" + }, + { + "indexed": false, + "name": "wad", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "src", + "type": "address" + }, + { + "indexed": true, + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "name": "wad", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "name": "wad", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "src", + "type": "address" + }, + { + "indexed": false, + "name": "wad", + "type": "uint256" + } + ], + "name": "Withdrawal", + "type": "event" + } + ], + "bytecode": "", + "deployedBytecode": "", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/backend/operate/ledger/abis/ServiceStakingToken.json b/backend/operate/ledger/abis/ServiceStakingToken.json new file mode 100644 index 000000000..e1405c0bf --- /dev/null +++ b/backend/operate/ledger/abis/ServiceStakingToken.json @@ -0,0 +1,1355 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ServiceStakingToken", + "sourceName": "contracts/staking/ServiceStakingToken.sol", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "maxNumServices", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardsPerSecond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minStakingDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minNumStakingPeriods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxNumInactivityPeriods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "livenessPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "livenessRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numAgentInstances", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "agentIds", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "configHash", + "type": "bytes32" + } + ], + "internalType": "struct ServiceStakingBase.StakingParams", + "name": "_stakingParams", + "type": "tuple" + }, + { + "internalType": "address", + "name": "_serviceRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "_serviceRegistryTokenUtility", + "type": "address" + }, + { + "internalType": "address", + "name": "_stakingToken", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_proxyHash", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "AgentInstanceRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "AgentInstancesSlotsFilled", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "agentId", + "type": "uint256" + } + ], + "name": "AgentNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "agentId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "AgentNotInService", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "componentId", + "type": "uint256" + } + ], + "name": "ComponentNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "HashExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "IncorrectAgentBondingValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "IncorrectRegistrationDepositValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "provided", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "LowerThan", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "manager", + "type": "address" + } + ], + "name": "ManagerOnly", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxNumServices", + "type": "uint256" + } + ], + "name": "MaxNumServicesReached", + "type": "error" + }, + { + "inputs": [], + "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": [ + { + "internalType": "address", + "name": "provided", + "type": "address" + }, + { + "internalType": "address", + "name": "expected", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "OnlyOwnServiceMultisig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "OperatorHasNoInstances", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "provided", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "Overflow", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnerOnly", + "type": "error" + }, + { + "inputs": [], + "name": "Paused", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuard", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "ServiceMustBeInactive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "ServiceNotUnstaked", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TokenTransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "multisig", + "type": "address" + } + ], + "name": "UnauthorizedMultisig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "provided", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "ValueLowerThan", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "agentId", + "type": "uint256" + } + ], + "name": "WrongAgentId", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numValues1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numValues2", + "type": "uint256" + } + ], + "name": "WrongArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "WrongOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "WrongServiceConfiguration", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "state", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "WrongServiceState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "expected", + "type": "address" + }, + { + "internalType": "address", + "name": "provided", + "type": "address" + } + ], + "name": "WrongStakingToken", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxThreshold", + "type": "uint256" + } + ], + "name": "WrongThreshold", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValue", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "availableRewards", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "serviceIds", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "rewards", + "type": "uint256[]" + } + ], + "name": "Checkpoint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "availableRewards", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "multisig", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "nonces", + "type": "uint256[]" + } + ], + "name": "ServiceStaked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "multisig", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "nonces", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "ServiceUnstaked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "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": "ServicesEvicted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "agentIds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "availableRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "balance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "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": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "calculateServiceStakingReward", + "outputs": [ + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkpoint", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[][]", + "name": "", + "type": "uint256[][]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "evictServiceIds", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "configHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "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", + "outputs": [ + { + "internalType": "uint256", + "name": "tsNext", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getServiceIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "getServiceInfo", + "outputs": [ + { + "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", + "type": "function" + }, + { + "inputs": [], + "name": "livenessPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "livenessRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "mapServiceInfo", + "outputs": [ + { + "internalType": "address", + "name": "multisig", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tsStart", + "type": "uint256" + }, + { + "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", + "type": "function" + }, + { + "inputs": [], + "name": "maxNumServices", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minStakingDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minStakingDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numAgentInstances", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proxyHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardsPerSecond", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "serviceRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "serviceRegistryTokenUtility", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "setServiceIds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stakingToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "threshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tsCheckpoint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6102606040523480156200001257600080fd5b506040516200383a3803806200383a833981016040819052620000359162000453565b8484828260000151600014806200004e57506020830151155b806200005c575060a0830151155b806200006a575060c0830151155b8062000078575060e0830151155b806200008657506060830151155b806200009457506080830151155b15620000b357604051637c946ed760e01b815260040160405180910390fd5b826080015183606001511015620000f5576060830151608084015160405163491a2bb160e01b8152600481019290925260248201526044015b60405180910390fd5b6002836040015110156200012d57604080840151905163491a2bb160e01b8152600481019190915260026024820152604401620000ec565b6001600160a01b038216620001555760405163d92e233d60e01b815260040160405180910390fd5b82516080908152602084015160a0908152604085015160c09081529185015160e0908152908501516101005290840151610120908152908401516101409081526001600160a01b0384166101a0529084015161016052830151610180526000805b846101000151518110156200029257818561010001518281518110620001e057620001e062000576565b6020026020010151116200022d57846101000151818151811062000208576200020862000576565b6020026020010151604051632ab10b0b60e21b8152600401620000ec91815260200190565b846101000151818151811062000247576200024762000576565b602090810291909101015160048054600181810183556000929092527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0182905590925001620001b6565b5081620002b257604051637c946ed760e01b815260040160405180910390fd5b6101c0829052610100516060850151620002cd91906200058c565b6101e052610100516080850151620002e691906200058c565b6102005250504260035550506001600160a01b03821615806200031057506001600160a01b038316155b156200032f5760405163d92e233d60e01b815260040160405180910390fd5b506001600160a01b0390811661024052166102205250620005b89050565b634e487b7160e01b600052604160045260246000fd5b60405161016081016001600160401b03811182821017156200038957620003896200034d565b60405290565b600082601f830112620003a157600080fd5b815160206001600160401b0380831115620003c057620003c06200034d565b8260051b604051601f19603f83011681018181108482111715620003e857620003e86200034d565b60405293845260208187018101949081019250878511156200040957600080fd5b6020870191505b848210156200042b5781518352918301919083019062000410565b979650505050505050565b80516001600160a01b03811681146200044e57600080fd5b919050565b600080600080600060a086880312156200046c57600080fd5b85516001600160401b03808211156200048457600080fd5b90870190610160828a0312156200049a57600080fd5b620004a462000363565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e082015261010080840151838111156200050357600080fd5b620005118c8287016200038f565b918301919091525061012083810151908201526101409283015192810192909252509450620005436020870162000436565b9350620005536040870162000436565b9250620005636060870162000436565b9150608086015190509295509295909350565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417620005b257634e487b7160e01b600052601160045260246000fd5b92915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161311962000721600039600081816104110152818161130901528181611c1401528181611d1e0152611d6201526000818161030501528181611ca40152611e0e01526000818161068e015281816118a50152611b1401526000818161024b0152818161074d015261079f01526000818161044b0152610fca0152600081816105cf01528181610a0101528181610d8601526111bd0152600081816105f601528181610e4e0152610e7d01526000818161036201528181610ec40152610ef80152600081816103c30152610e0c0152600081816103ea015261294a01526000818161038901528181611bc60152611fb80152600061049b01526000818161061d0152611d9901526000818161064401526122ae0152600081816102de01528181610d0d0152610d4101526131196000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c8063a0ed60e011610145578063cbcf252a116100bd578063eb338c961161008c578063f4dce71411610071578063f4dce71414610681578063f86ad2b614610689578063ffa1ad74146106b057600080fd5b8063eb338c9614610666578063f189e85a1461067957600080fd5b8063cbcf252a146105ca578063e1f1176d146105f1578063e77cdcc914610618578063eacdaabc1461063f57600080fd5b8063b69ef8a811610114578063c2c4c5c1116100f9578063c2c4c5c11461057e578063c889921d14610597578063cae2a5f0146105aa57600080fd5b8063b69ef8a814610562578063b6b55f251461056b57600080fd5b8063a0ed60e014610496578063a694fc3a146104bd578063a74466ad146104d0578063b15087601461054d57600080fd5b806352c824f5116101d857806372f702f3116101a7578063809cee2f1161018c578063809cee2f1461044657806382a8ea581461046d578063879d90901461048d57600080fd5b806372f702f31461040c57806378e061361461043357600080fd5b806352c824f51461038457806356e76058146103ab5780635829c5ec146103be578063592cf3fb146103e557600080fd5b8063287140511161021457806328714051146103005780632e17de781461033f5780633e7329971461035457806342cde4e81461035d57600080fd5b806308ae7e541461024657806314b19c5a14610280578063150b7a021461028957806316a75172146102d9575b600080fd5b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61026d60005481565b6102a8610297366004612a0a565b630a85bd0160e11b95945050505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610277565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610277565b61035261034d366004612aa9565b6106e1565b005b61026d60035481565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d6103b9366004612aa9565b610acf565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b61026d610441366004612aa9565b610af0565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61048061047b366004612aa9565b610bba565b6040516102779190612afe565b61026d60025481565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103526104cb366004612aa9565b610cb1565b61051a6104de366004612aa9565b6005602081905260009182526040909120805460018201546003830154600484015493909401546001600160a01b039283169492909116929085565b604080516001600160a01b039687168152959094166020860152928401919091526060830152608082015260a001610277565b61055561127e565b6040516102779190612b65565b61026d60015481565b610352610579366004612aa9565b6112d6565b610586611378565b604051610277959493929190612b78565b61026d6105a5366004612aa9565b6119ad565b6105bd6105b8366004612aa9565b611a69565b6040516102779190612c3d565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d610674366004612aa9565b611b5c565b610555611b6c565b61026d611bc2565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6106d4604051806040016040528060058152602001640302e312e360dc1b81525081565b6040516102779190612c65565b600081815260056020526040902060018101546001600160a01b0316331461073857600181015460405163521eb56d60e11b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b600381015460006107498242612cca565b90507f0000000000000000000000000000000000000000000000000000000000000000811115801561077d57506000600254115b156107cb5760405163ba2bbc6b60e01b815260048101859052602481018290527f0000000000000000000000000000000000000000000000000000000000000000604482015260640161072f565b6000806107d6611378565b945050505091508151600003610837576107ee611b6c565b9150815167ffffffffffffffff81111561080a5761080a612cdd565b604051908082528060200260200182016040528015610833578160200160208202803683370190505b5090505b6000805b8351821015610898578783838151811061085757610857612cf3565b60200260200101510315610898578784838151811061087857610878612cf3565b60200260200101510361088d57506001610898565b81600101915061083b565b600487015460028801805460408051602080840282018101909252828152600093909290918301828280156108ec57602002820191906000526020600020905b8154815260200190600101908083116108d8575b50508c5460008f8152600560205260408120805473ffffffffffffffffffffffffffffffffffffffff19908116825560018201805490911690559596506001600160a01b03909116949350915061094890506002830182612974565b506000600382018190556004820181905560059091015583156109d7576006805461097590600190612cca565b8154811061098557610985612cf3565b9060005260206000200154600686815481106109a3576109a3612cf3565b60009182526020909120015560068054806109c0576109c0612d09565b600190038181906000526020600020016000905590555b604051632142170760e11b8152306004820152336024820152604481018c90526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90606401600060405180830381600087803b158015610a4557600080fd5b505af1158015610a59573d6000803e3d6000fd5b505050506000831115610a7057610a708184611bf7565b806001600160a01b0316336001600160a01b03168c7f950733f4c0bf951b8e770f3cc619a4288e7b59b1236d59aeaf2c238488e8ae816000548688604051610aba93929190612d1f565b60405180910390a45050505050505050505050565b60048181548110610adf57600080fd5b600091825260209091200154905081565b6000818152600560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015610b7057602002820191906000526020600020905b815481526020019060010190808311610b5c575b505050505081526020016003820154815260200160048201548152602001600582015481525050905080608001519150610ba9836119ad565b610bb39083612d48565b9392505050565b610c056040518060c0016040528060006001600160a01b0316815260200160006001600160a01b03168152602001606081526020016000815260200160008152602001600081525090565b600082815260056020908152604091829020825160c08101845281546001600160a01b0390811682526001830154168184015260028201805485518186028101860187528181529295939493860193830182828015610c8357602002820191906000526020600020905b815481526020019060010190808311610c6f575b5050505050815260200160038201548152602001600482015481526020016005820154815250509050919050565b600254600003610cd45760405163afb0be3360e01b815260040160405180910390fd5b6000818152600560205260409020600381015415610d085760405163b4817ce760e01b81526004810183905260240161072f565b6006547f00000000000000000000000000000000000000000000000000000000000000008103610d6d5760405163fd20861560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015260240161072f565b60405163ef0e239b60e01b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef0e239b90602401600060405180830381865afa158015610dd5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dfd9190810190612e79565b9050806080015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014610e4c57604051637ad404bf60e11b81526004810185905260240161072f565b7f000000000000000000000000000000000000000000000000000000000000000015801590610e9f575080604001517f000000000000000000000000000000000000000000000000000000000000000014155b15610ec057604051637ad404bf60e11b81526004810185905260240161072f565b60007f0000000000000000000000000000000000000000000000000000000000000000118015610f1a5750806060015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014155b15610f3b57604051637ad404bf60e11b81526004810185905260240161072f565b60048160c001516005811115610f5357610f53612c27565b14610f92578060c001516005811115610f6e57610f6e612c27565b604051633c053f9d60e21b815260048101919091526024810185905260440161072f565b600081602001516001600160a01b0316803b806020016040519081016040528181526000908060200190933c805190602001209050807f00000000000000000000000000000000000000000000000000000000000000001461101757602082015160405162a2307960e51b81526001600160a01b03909116600482015260240161072f565b60045480156110e05760e08301515181811461104957604051637ad404bf60e11b81526004810188905260240161072f565b60005b818110156110dd578460e00151818151811061106a5761106a612cf3565b602002602001015163ffffffff166004828154811061108b5761108b612cf3565b9060005260206000200154146110d557600481815481106110ae576110ae612cf3565b9060005260206000200154604051632ab10b0b60e21b815260040161072f91815260200190565b60010161104c565b50505b6111018684600001516bffffffffffffffffffffffff168560e00151611c81565b602083015185546001600160a01b03821673ffffffffffffffffffffffffffffffffffffffff199182161787556001870180549091163317905560009061114790611f02565b805190915061115f9060028801906020840190612995565b50426003870155600680546001810182556000919091527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01879055604051632142170760e11b8152336004820152306024820152604481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342842e0e90606401600060405180830381600087803b15801561120957600080fd5b505af115801561121d573d6000803e3d6000fd5b5050505083602001516001600160a01b0316336001600160a01b0316887faa6b005b4958114a0c90492461c24af6525ae0178db7fbf44125ae9217c69ccb6000548560405161126d929190612f57565b60405180910390a450505050505050565b606060048054806020026020016040519081016040528092919081815260200182805480156112cc57602002820191906000526020600020905b8154815260200190600101908083116112b8575b5050505050905090565b6000816001546112e69190612d48565b90506000826002546112f89190612d48565b6001839055600281905590506113307f0000000000000000000000000000000000000000000000000000000000000000333086611f13565b604080518481526020810184905290810182905233907f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e9060600160405180910390a2505050565b6060806060806060600080600080600080600080611394611f9d565b97509750975097509750975097509750606080845167ffffffffffffffff8111156113c1576113c1612cdd565b6040519080825280602002602001820160405280156113ea578160200160208202803683370190505b509a506000891561177d578967ffffffffffffffff81111561140e5761140e612cdd565b604051908082528060200260200182016040528015611437578160200160208202803683370190505b5092508967ffffffffffffffff81111561145357611453612cdd565b60405190808252806020026020018201604052801561147c578160200160208202803683370190505b5091508a8911156116865760008060015b8c811015611579578b8e8b83815181106114a9576114a9612cf3565b60200260200101516114bb9190612f70565b6114c59190612f87565b92506114d18383612d48565b91508a81815181106114e5576114e5612cf3565b602002602001015193508a818151811061150157611501612cf3565b602002602001015186828151811061151b5761151b612cf3565b6020026020010181815250508285828151811061153a5761153a612cf3565b6020026020010181815250508260056000868152602001908152602001600020600401600082825461156c9190612d48565b909155505060010161148d565b508a8d8a60008151811061158f5761158f612cf3565b60200260200101516115a19190612f70565b6115ab9190612f87565b91506115b78282612d48565b9050896000815181106115cc576115cc612cf3565b60200260200101519250896000815181106115e9576115e9612cf3565b60200260200101518560008151811061160457611604612cf3565b602002602001018181525050808d111561162f57611622818e612cca565b61162c9083612d48565b91505b818460008151811061164357611643612cf3565b602002602001018181525050816005600085815260200190815260200160002060040160008282546116759190612d48565b9091555060009d5061177792505050565b60005b8a811015611769578881815181106116a3576116a3612cf3565b602002602001015191508881815181106116bf576116bf612cf3565b60200260200101518482815181106116d9576116d9612cf3565b6020026020010181815250508781815181106116f7576116f7612cf3565b602002602001015183828151811061171157611711612cf3565b60200260200101818152505087818151811061172f5761172f612cf3565b602002602001015160056000848152602001908152602001600020600401600082825461175c9190612d48565b9091555050600101611689565b50611774898c612cca565b9a505b60028b90555b855115611997576000995060005b8651811015611930578681815181106117a6576117a6612cf3565b602002602001015191508581815181106117c2576117c2612cf3565b60200260200101516005600084815260200190815260200160002060020190805190602001906117f3929190612995565b50600085828151811061180857611808612cf3565b602002602001015111156119155784818151811061182857611828612cf3565b602002602001015160056000848152602001908152602001600020600501546118519190612d48565b85828151811061186357611863612cf3565b60200260200101818152505084818151811061188157611881612cf3565b602002602001015160056000848152602001908152602001600020600501819055507f00000000000000000000000000000000000000000000000000000000000000008582815181106118d6576118d6612cf3565b6020026020010151111561191057818d82815181106118f7576118f7612cf3565b60209081029190910101528a61190c81612fa9565b9b50505b611928565b6000828152600560208190526040822001555b60010161178b565b508915611942576119428c858c61239b565b42600355600054611954816001612d48565b60005560405181907f06a98bdd4732811ab3214800ed1ada2dce66a2bce301d250c3ca7d6b461ee6669061198d908f9088908890612fc2565b60405180910390a2505b50939e929d509b50919950969750505050505050565b6000806000806000806119be611f9d565b5050509450945094509450945060005b84811015611a5e57878382815181106119e9576119e9612cf3565b602002602001015103611a565785841115611a35578386838381518110611a1257611a12612cf3565b6020026020010151611a249190612f70565b611a2e9190612f87565b9650611a5e565b818181518110611a4757611a47612cf3565b60200260200101519650611a5e565b6001016119ce565b505050505050919050565b6000818152600560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015611ae957602002820191906000526020600020905b815481526020019060010190808311611ad5575b50505050508152602001600382015481526020016004820154815260200160058201548152505090507f00000000000000000000000000000000000000000000000000000000000000008160a001511115611b475760029150611b56565b606081015115611b5657600191505b50919050565b60068181548110610adf57600080fd5b606060068054806020026020016040519081016040528092919081815260200182805480156112cc57602002820191906000526020600020908154815260200190600101908083116112b8575050505050905090565b60007f0000000000000000000000000000000000000000000000000000000000000000600354611bf29190612d48565b905090565b8060016000828254611c099190612cca565b90915550611c3a90507f00000000000000000000000000000000000000000000000000000000000000008383612760565b816001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436482604051611c7591815260200190565b60405180910390a25050565b604051633cebfa4f60e01b81526004810184905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633cebfa4f906024016040805180830381865afa158015611cea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0e9190612ff7565b91509150816001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614611d9757604051630b80380d60e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301528316602482015260440161072f565b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff8216811115611dfe57604051632b30b24760e21b81526bffffffffffffffffffffffff831660048201526024810182905260440161072f565b60005b8451811015611ef95760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166375c1f93489888581518110611e4e57611e4e612cf3565b60200260200101516040518363ffffffff1660e01b8152600401611e8292919091825263ffffffff16602082015260400190565b602060405180830381865afa158015611e9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec3919061302c565b905082811015611ef057604051632b30b24760e21b8152600481018290526024810184905260440161072f565b50600101611e01565b50505050505050565b6060611f0d826127e3565b92915050565b60006040516323b872dd60e01b6000528460045283602452826044526020600060646000808a5af13d15601f3d1160016000511416171691506000606052806040525080611f965760405163abae3d6d60e01b81526001600160a01b0380871660048301528086166024830152841660448201526064810183905260840161072f565b5050505050565b600080600060608060608060606000600354905060025498507f00000000000000000000000000000000000000000000000000000000000000008142611fe39190612cca565b10158015611ff15750600089115b15612390576006548067ffffffffffffffff81111561201257612012612cdd565b60405190808252806020026020018201604052801561203b578160200160208202803683370190505b5094508067ffffffffffffffff81111561205757612057612cdd565b604051908082528060200260200182016040528015612080578160200160208202803683370190505b5096508067ffffffffffffffff81111561209c5761209c612cdd565b6040519080825280602002602001820160405280156120c5578160200160208202803683370190505b5095508067ffffffffffffffff8111156120e1576120e1612cdd565b60405190808252806020026020018201604052801561211457816020015b60608152602001906001900390816120ff5790505b5093508067ffffffffffffffff81111561213057612130612cdd565b604051908082528060200260200182016040528015612159578160200160208202803683370190505b50925060005b8181101561238d576006818154811061217a5761217a612cf3565b906000526020600020015486828151811061219757612197612cf3565b6020026020010181815250506000600560008884815181106121bb576121bb612cf3565b602090810291909101810151825281019190915260400160002080549091506121ec906001600160a01b0316611f02565b8683815181106121fe576121fe612cf3565b6020908102919091010152600381015484908181111561221c578091505b6122268242612cca565b905060006122a089868151811061223f5761223f612cf3565b60200260200101518560020180548060200260200160405190810160405280929190818152602001828054801561229557602002820191906000526020600020905b815481526020019060010190808311612281575b50505050508461288b565b9050801561235e576122d2827f0000000000000000000000000000000000000000000000000000000000000000612f70565b8b8f815181106122e4576122e4612cf3565b6020026020010181815250508a8e8151811061230257612302612cf3565b60200260200101518d6123159190612d48565b9c5089858151811061232957612329612cf3565b60200260200101518c8f8151811061234357612343612cf3565b60209081029190910101526123578e612fa9565b9d5061237e565b8188868151811061237157612371612cf3565b6020026020010181815250505b5050505080600101905061215f565b50505b509091929394959697565b825160008267ffffffffffffffff8111156123b8576123b8612cdd565b6040519080825280602002602001820160405280156123e1578160200160208202803683370190505b50905060008367ffffffffffffffff8111156123ff576123ff612cdd565b604051908082528060200260200182016040528015612428578160200160208202803683370190505b50905060008467ffffffffffffffff81111561244657612446612cdd565b60405190808252806020026020018201604052801561246f578160200160208202803683370190505b50905060008567ffffffffffffffff81111561248d5761248d612cdd565b6040519080825280602002602001820160405280156124b6578160200160208202803683370190505b50905060008667ffffffffffffffff8111156124d4576124d4612cdd565b6040519080825280602002602001820160405280156124fd578160200160208202803683370190505b50905060008060005b8881101561265d5760008c828151811061252257612522612cf3565b60200260200101511115612655578b818151811061254257612542612cf3565b602002602001015191508188848151811061255f5761255f612cf3565b6020908102919091018101919091526000838152600590915260409020600181015488516001600160a01b03909116908990869081106125a1576125a1612cf3565b6001600160a01b039283166020918202929092010152815488519116908890869081106125d0576125d0612cf3565b60200260200101906001600160a01b031690816001600160a01b0316815250508b828151811061260257612602612cf3565b602002602001015186858151811061261c5761261c612cf3565b6020026020010181815250508185858151811061263b5761263b612cf3565b60209081029190910101528361265081612fa9565b945050505b600101612506565b50885b8015612712578861267081613045565b99506000905084612682600184612cca565b8151811061269257612692612cf3565b6020026020010151905060068a815481106126af576126af612cf3565b9060005260206000200154600682815481106126cd576126cd612cf3565b60009182526020909120015560068054806126ea576126ea612d09565b60019003818190600052602060002001600090559055508061270b90613045565b9050612660565b506000547fd19a3d42ed383465e4058c322d9411aeac76ddb8454d22e139fc99808bd569528888888860405161274b9493929190613096565b60405180910390a25050505050505050505050565b600060405163a9059cbb60e01b6000528360045282602452602060006044600080895af13d15601f3d11600160005114161716915060006060528060405250806127dd5760405163abae3d6d60e01b81526001600160a01b038086166004830152306024830152841660448201526064810183905260840161072f565b50505050565b60408051600180825281830190925260609160208083019080368337019050509050816001600160a01b031663affed0e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612843573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612867919061302c565b8160008151811061287a5761287a612cf3565b602002602001018181525050919050565b60006128988484846128a0565b949350505050565b600080821180156128e45750826000815181106128bf576128bf612cf3565b6020026020010151846000815181106128da576128da612cf3565b6020026020010151115b15610bb357600082846000815181106128ff576128ff612cf3565b60200260200101518660008151811061291a5761291a612cf3565b602002602001015161292c9190612cca565b61293e90670de0b6b3a7640000612f70565b6129489190612f87565b7f0000000000000000000000000000000000000000000000000000000000000000111595945050505050565b508054600082559060005260206000209081019061299291906129e0565b50565b8280548282559060005260206000209081019282156129d0579160200282015b828111156129d05782518255916020019190600101906129b5565b506129dc9291506129e0565b5090565b5b808211156129dc57600081556001016129e1565b6001600160a01b038116811461299257600080fd5b600080600080600060808688031215612a2257600080fd5b8535612a2d816129f5565b94506020860135612a3d816129f5565b935060408601359250606086013567ffffffffffffffff80821115612a6157600080fd5b818801915088601f830112612a7557600080fd5b813581811115612a8457600080fd5b896020828501011115612a9657600080fd5b9699959850939650602001949392505050565b600060208284031215612abb57600080fd5b5035919050565b60008151808452602080850194506020840160005b83811015612af357815187529582019590820190600101612ad7565b509495945050505050565b6020815260006001600160a01b0380845116602084015280602085015116604084015250604083015160c06060840152612b3b60e0840182612ac2565b905060608401516080840152608084015160a084015260a084015160c08401528091505092915050565b602081526000610bb36020830184612ac2565b60a081526000612b8b60a0830188612ac2565b6020838203818501528188518084528284019150828160051b850101838b0160005b83811015612bdb57601f19878403018552612bc9838351612ac2565b94860194925090850190600101612bad565b50508681036040880152612bef818b612ac2565b9450505050508281036060840152612c078186612ac2565b90508281036080840152612c1b8185612ac2565b98975050505050505050565b634e487b7160e01b600052602160045260246000fd5b6020810160038310612c5f57634e487b7160e01b600052602160045260246000fd5b91905290565b60006020808352835180602085015260005b81811015612c9357858101830151858201604001528201612c77565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115611f0d57611f0d612cb4565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b838152606060208201526000612d386060830185612ac2565b9050826040830152949350505050565b80820180821115611f0d57611f0d612cb4565b604051610100810167ffffffffffffffff81118282101715612d7f57612d7f612cdd565b60405290565b80516bffffffffffffffffffffffff81168114612da157600080fd5b919050565b8051612da1816129f5565b805163ffffffff81168114612da157600080fd5b805160068110612da157600080fd5b600082601f830112612de557600080fd5b8151602067ffffffffffffffff80831115612e0257612e02612cdd565b8260051b604051601f19603f83011681018181108482111715612e2757612e27612cdd565b6040529384526020818701810194908101925087851115612e4757600080fd5b6020870191505b84821015612e6e57612e5f82612db1565b83529183019190830190612e4e565b979650505050505050565b600060208284031215612e8b57600080fd5b815167ffffffffffffffff80821115612ea357600080fd5b908301906101008286031215612eb857600080fd5b612ec0612d5b565b612ec983612d85565b8152612ed760208401612da6565b602082015260408301516040820152612ef260608401612db1565b6060820152612f0360808401612db1565b6080820152612f1460a08401612db1565b60a0820152612f2560c08401612dc5565b60c082015260e083015182811115612f3c57600080fd5b612f4887828601612dd4565b60e08301525095945050505050565b8281526040602082015260006128986040830184612ac2565b8082028115828204841417611f0d57611f0d612cb4565b600082612fa457634e487b7160e01b600052601260045260246000fd5b500490565b600060018201612fbb57612fbb612cb4565b5060010190565b838152606060208201526000612fdb6060830185612ac2565b8281036040840152612fed8185612ac2565b9695505050505050565b6000806040838503121561300a57600080fd5b8251613015816129f5565b915061302360208401612d85565b90509250929050565b60006020828403121561303e57600080fd5b5051919050565b60008161305457613054612cb4565b506000190190565b60008151808452602080850194506020840160005b83811015612af35781516001600160a01b031687529582019590820190600101613071565b6080815260006130a96080830187612ac2565b82810360208401526130bb818761305c565b905082810360408401526130cf818661305c565b90508281036060840152612e6e8185612ac256fea26469706673582212201cbb3243bdf2246a74a754c4b24385dc52b256b192f67778a3b3a76648374a5864736f6c63430008170033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102415760003560e01c8063a0ed60e011610145578063cbcf252a116100bd578063eb338c961161008c578063f4dce71411610071578063f4dce71414610681578063f86ad2b614610689578063ffa1ad74146106b057600080fd5b8063eb338c9614610666578063f189e85a1461067957600080fd5b8063cbcf252a146105ca578063e1f1176d146105f1578063e77cdcc914610618578063eacdaabc1461063f57600080fd5b8063b69ef8a811610114578063c2c4c5c1116100f9578063c2c4c5c11461057e578063c889921d14610597578063cae2a5f0146105aa57600080fd5b8063b69ef8a814610562578063b6b55f251461056b57600080fd5b8063a0ed60e014610496578063a694fc3a146104bd578063a74466ad146104d0578063b15087601461054d57600080fd5b806352c824f5116101d857806372f702f3116101a7578063809cee2f1161018c578063809cee2f1461044657806382a8ea581461046d578063879d90901461048d57600080fd5b806372f702f31461040c57806378e061361461043357600080fd5b806352c824f51461038457806356e76058146103ab5780635829c5ec146103be578063592cf3fb146103e557600080fd5b8063287140511161021457806328714051146103005780632e17de781461033f5780633e7329971461035457806342cde4e81461035d57600080fd5b806308ae7e541461024657806314b19c5a14610280578063150b7a021461028957806316a75172146102d9575b600080fd5b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61026d60005481565b6102a8610297366004612a0a565b630a85bd0160e11b95945050505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610277565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610277565b61035261034d366004612aa9565b6106e1565b005b61026d60035481565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d6103b9366004612aa9565b610acf565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b61026d610441366004612aa9565b610af0565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61048061047b366004612aa9565b610bba565b6040516102779190612afe565b61026d60025481565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103526104cb366004612aa9565b610cb1565b61051a6104de366004612aa9565b6005602081905260009182526040909120805460018201546003830154600484015493909401546001600160a01b039283169492909116929085565b604080516001600160a01b039687168152959094166020860152928401919091526060830152608082015260a001610277565b61055561127e565b6040516102779190612b65565b61026d60015481565b610352610579366004612aa9565b6112d6565b610586611378565b604051610277959493929190612b78565b61026d6105a5366004612aa9565b6119ad565b6105bd6105b8366004612aa9565b611a69565b6040516102779190612c3d565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d610674366004612aa9565b611b5c565b610555611b6c565b61026d611bc2565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6106d4604051806040016040528060058152602001640302e312e360dc1b81525081565b6040516102779190612c65565b600081815260056020526040902060018101546001600160a01b0316331461073857600181015460405163521eb56d60e11b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b600381015460006107498242612cca565b90507f0000000000000000000000000000000000000000000000000000000000000000811115801561077d57506000600254115b156107cb5760405163ba2bbc6b60e01b815260048101859052602481018290527f0000000000000000000000000000000000000000000000000000000000000000604482015260640161072f565b6000806107d6611378565b945050505091508151600003610837576107ee611b6c565b9150815167ffffffffffffffff81111561080a5761080a612cdd565b604051908082528060200260200182016040528015610833578160200160208202803683370190505b5090505b6000805b8351821015610898578783838151811061085757610857612cf3565b60200260200101510315610898578784838151811061087857610878612cf3565b60200260200101510361088d57506001610898565b81600101915061083b565b600487015460028801805460408051602080840282018101909252828152600093909290918301828280156108ec57602002820191906000526020600020905b8154815260200190600101908083116108d8575b50508c5460008f8152600560205260408120805473ffffffffffffffffffffffffffffffffffffffff19908116825560018201805490911690559596506001600160a01b03909116949350915061094890506002830182612974565b506000600382018190556004820181905560059091015583156109d7576006805461097590600190612cca565b8154811061098557610985612cf3565b9060005260206000200154600686815481106109a3576109a3612cf3565b60009182526020909120015560068054806109c0576109c0612d09565b600190038181906000526020600020016000905590555b604051632142170760e11b8152306004820152336024820152604481018c90526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90606401600060405180830381600087803b158015610a4557600080fd5b505af1158015610a59573d6000803e3d6000fd5b505050506000831115610a7057610a708184611bf7565b806001600160a01b0316336001600160a01b03168c7f950733f4c0bf951b8e770f3cc619a4288e7b59b1236d59aeaf2c238488e8ae816000548688604051610aba93929190612d1f565b60405180910390a45050505050505050505050565b60048181548110610adf57600080fd5b600091825260209091200154905081565b6000818152600560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015610b7057602002820191906000526020600020905b815481526020019060010190808311610b5c575b505050505081526020016003820154815260200160048201548152602001600582015481525050905080608001519150610ba9836119ad565b610bb39083612d48565b9392505050565b610c056040518060c0016040528060006001600160a01b0316815260200160006001600160a01b03168152602001606081526020016000815260200160008152602001600081525090565b600082815260056020908152604091829020825160c08101845281546001600160a01b0390811682526001830154168184015260028201805485518186028101860187528181529295939493860193830182828015610c8357602002820191906000526020600020905b815481526020019060010190808311610c6f575b5050505050815260200160038201548152602001600482015481526020016005820154815250509050919050565b600254600003610cd45760405163afb0be3360e01b815260040160405180910390fd5b6000818152600560205260409020600381015415610d085760405163b4817ce760e01b81526004810183905260240161072f565b6006547f00000000000000000000000000000000000000000000000000000000000000008103610d6d5760405163fd20861560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015260240161072f565b60405163ef0e239b60e01b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef0e239b90602401600060405180830381865afa158015610dd5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dfd9190810190612e79565b9050806080015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014610e4c57604051637ad404bf60e11b81526004810185905260240161072f565b7f000000000000000000000000000000000000000000000000000000000000000015801590610e9f575080604001517f000000000000000000000000000000000000000000000000000000000000000014155b15610ec057604051637ad404bf60e11b81526004810185905260240161072f565b60007f0000000000000000000000000000000000000000000000000000000000000000118015610f1a5750806060015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014155b15610f3b57604051637ad404bf60e11b81526004810185905260240161072f565b60048160c001516005811115610f5357610f53612c27565b14610f92578060c001516005811115610f6e57610f6e612c27565b604051633c053f9d60e21b815260048101919091526024810185905260440161072f565b600081602001516001600160a01b0316803b806020016040519081016040528181526000908060200190933c805190602001209050807f00000000000000000000000000000000000000000000000000000000000000001461101757602082015160405162a2307960e51b81526001600160a01b03909116600482015260240161072f565b60045480156110e05760e08301515181811461104957604051637ad404bf60e11b81526004810188905260240161072f565b60005b818110156110dd578460e00151818151811061106a5761106a612cf3565b602002602001015163ffffffff166004828154811061108b5761108b612cf3565b9060005260206000200154146110d557600481815481106110ae576110ae612cf3565b9060005260206000200154604051632ab10b0b60e21b815260040161072f91815260200190565b60010161104c565b50505b6111018684600001516bffffffffffffffffffffffff168560e00151611c81565b602083015185546001600160a01b03821673ffffffffffffffffffffffffffffffffffffffff199182161787556001870180549091163317905560009061114790611f02565b805190915061115f9060028801906020840190612995565b50426003870155600680546001810182556000919091527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01879055604051632142170760e11b8152336004820152306024820152604481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342842e0e90606401600060405180830381600087803b15801561120957600080fd5b505af115801561121d573d6000803e3d6000fd5b5050505083602001516001600160a01b0316336001600160a01b0316887faa6b005b4958114a0c90492461c24af6525ae0178db7fbf44125ae9217c69ccb6000548560405161126d929190612f57565b60405180910390a450505050505050565b606060048054806020026020016040519081016040528092919081815260200182805480156112cc57602002820191906000526020600020905b8154815260200190600101908083116112b8575b5050505050905090565b6000816001546112e69190612d48565b90506000826002546112f89190612d48565b6001839055600281905590506113307f0000000000000000000000000000000000000000000000000000000000000000333086611f13565b604080518481526020810184905290810182905233907f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e9060600160405180910390a2505050565b6060806060806060600080600080600080600080611394611f9d565b97509750975097509750975097509750606080845167ffffffffffffffff8111156113c1576113c1612cdd565b6040519080825280602002602001820160405280156113ea578160200160208202803683370190505b509a506000891561177d578967ffffffffffffffff81111561140e5761140e612cdd565b604051908082528060200260200182016040528015611437578160200160208202803683370190505b5092508967ffffffffffffffff81111561145357611453612cdd565b60405190808252806020026020018201604052801561147c578160200160208202803683370190505b5091508a8911156116865760008060015b8c811015611579578b8e8b83815181106114a9576114a9612cf3565b60200260200101516114bb9190612f70565b6114c59190612f87565b92506114d18383612d48565b91508a81815181106114e5576114e5612cf3565b602002602001015193508a818151811061150157611501612cf3565b602002602001015186828151811061151b5761151b612cf3565b6020026020010181815250508285828151811061153a5761153a612cf3565b6020026020010181815250508260056000868152602001908152602001600020600401600082825461156c9190612d48565b909155505060010161148d565b508a8d8a60008151811061158f5761158f612cf3565b60200260200101516115a19190612f70565b6115ab9190612f87565b91506115b78282612d48565b9050896000815181106115cc576115cc612cf3565b60200260200101519250896000815181106115e9576115e9612cf3565b60200260200101518560008151811061160457611604612cf3565b602002602001018181525050808d111561162f57611622818e612cca565b61162c9083612d48565b91505b818460008151811061164357611643612cf3565b602002602001018181525050816005600085815260200190815260200160002060040160008282546116759190612d48565b9091555060009d5061177792505050565b60005b8a811015611769578881815181106116a3576116a3612cf3565b602002602001015191508881815181106116bf576116bf612cf3565b60200260200101518482815181106116d9576116d9612cf3565b6020026020010181815250508781815181106116f7576116f7612cf3565b602002602001015183828151811061171157611711612cf3565b60200260200101818152505087818151811061172f5761172f612cf3565b602002602001015160056000848152602001908152602001600020600401600082825461175c9190612d48565b9091555050600101611689565b50611774898c612cca565b9a505b60028b90555b855115611997576000995060005b8651811015611930578681815181106117a6576117a6612cf3565b602002602001015191508581815181106117c2576117c2612cf3565b60200260200101516005600084815260200190815260200160002060020190805190602001906117f3929190612995565b50600085828151811061180857611808612cf3565b602002602001015111156119155784818151811061182857611828612cf3565b602002602001015160056000848152602001908152602001600020600501546118519190612d48565b85828151811061186357611863612cf3565b60200260200101818152505084818151811061188157611881612cf3565b602002602001015160056000848152602001908152602001600020600501819055507f00000000000000000000000000000000000000000000000000000000000000008582815181106118d6576118d6612cf3565b6020026020010151111561191057818d82815181106118f7576118f7612cf3565b60209081029190910101528a61190c81612fa9565b9b50505b611928565b6000828152600560208190526040822001555b60010161178b565b508915611942576119428c858c61239b565b42600355600054611954816001612d48565b60005560405181907f06a98bdd4732811ab3214800ed1ada2dce66a2bce301d250c3ca7d6b461ee6669061198d908f9088908890612fc2565b60405180910390a2505b50939e929d509b50919950969750505050505050565b6000806000806000806119be611f9d565b5050509450945094509450945060005b84811015611a5e57878382815181106119e9576119e9612cf3565b602002602001015103611a565785841115611a35578386838381518110611a1257611a12612cf3565b6020026020010151611a249190612f70565b611a2e9190612f87565b9650611a5e565b818181518110611a4757611a47612cf3565b60200260200101519650611a5e565b6001016119ce565b505050505050919050565b6000818152600560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015611ae957602002820191906000526020600020905b815481526020019060010190808311611ad5575b50505050508152602001600382015481526020016004820154815260200160058201548152505090507f00000000000000000000000000000000000000000000000000000000000000008160a001511115611b475760029150611b56565b606081015115611b5657600191505b50919050565b60068181548110610adf57600080fd5b606060068054806020026020016040519081016040528092919081815260200182805480156112cc57602002820191906000526020600020908154815260200190600101908083116112b8575050505050905090565b60007f0000000000000000000000000000000000000000000000000000000000000000600354611bf29190612d48565b905090565b8060016000828254611c099190612cca565b90915550611c3a90507f00000000000000000000000000000000000000000000000000000000000000008383612760565b816001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436482604051611c7591815260200190565b60405180910390a25050565b604051633cebfa4f60e01b81526004810184905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633cebfa4f906024016040805180830381865afa158015611cea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0e9190612ff7565b91509150816001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614611d9757604051630b80380d60e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301528316602482015260440161072f565b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff8216811115611dfe57604051632b30b24760e21b81526bffffffffffffffffffffffff831660048201526024810182905260440161072f565b60005b8451811015611ef95760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166375c1f93489888581518110611e4e57611e4e612cf3565b60200260200101516040518363ffffffff1660e01b8152600401611e8292919091825263ffffffff16602082015260400190565b602060405180830381865afa158015611e9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec3919061302c565b905082811015611ef057604051632b30b24760e21b8152600481018290526024810184905260440161072f565b50600101611e01565b50505050505050565b6060611f0d826127e3565b92915050565b60006040516323b872dd60e01b6000528460045283602452826044526020600060646000808a5af13d15601f3d1160016000511416171691506000606052806040525080611f965760405163abae3d6d60e01b81526001600160a01b0380871660048301528086166024830152841660448201526064810183905260840161072f565b5050505050565b600080600060608060608060606000600354905060025498507f00000000000000000000000000000000000000000000000000000000000000008142611fe39190612cca565b10158015611ff15750600089115b15612390576006548067ffffffffffffffff81111561201257612012612cdd565b60405190808252806020026020018201604052801561203b578160200160208202803683370190505b5094508067ffffffffffffffff81111561205757612057612cdd565b604051908082528060200260200182016040528015612080578160200160208202803683370190505b5096508067ffffffffffffffff81111561209c5761209c612cdd565b6040519080825280602002602001820160405280156120c5578160200160208202803683370190505b5095508067ffffffffffffffff8111156120e1576120e1612cdd565b60405190808252806020026020018201604052801561211457816020015b60608152602001906001900390816120ff5790505b5093508067ffffffffffffffff81111561213057612130612cdd565b604051908082528060200260200182016040528015612159578160200160208202803683370190505b50925060005b8181101561238d576006818154811061217a5761217a612cf3565b906000526020600020015486828151811061219757612197612cf3565b6020026020010181815250506000600560008884815181106121bb576121bb612cf3565b602090810291909101810151825281019190915260400160002080549091506121ec906001600160a01b0316611f02565b8683815181106121fe576121fe612cf3565b6020908102919091010152600381015484908181111561221c578091505b6122268242612cca565b905060006122a089868151811061223f5761223f612cf3565b60200260200101518560020180548060200260200160405190810160405280929190818152602001828054801561229557602002820191906000526020600020905b815481526020019060010190808311612281575b50505050508461288b565b9050801561235e576122d2827f0000000000000000000000000000000000000000000000000000000000000000612f70565b8b8f815181106122e4576122e4612cf3565b6020026020010181815250508a8e8151811061230257612302612cf3565b60200260200101518d6123159190612d48565b9c5089858151811061232957612329612cf3565b60200260200101518c8f8151811061234357612343612cf3565b60209081029190910101526123578e612fa9565b9d5061237e565b8188868151811061237157612371612cf3565b6020026020010181815250505b5050505080600101905061215f565b50505b509091929394959697565b825160008267ffffffffffffffff8111156123b8576123b8612cdd565b6040519080825280602002602001820160405280156123e1578160200160208202803683370190505b50905060008367ffffffffffffffff8111156123ff576123ff612cdd565b604051908082528060200260200182016040528015612428578160200160208202803683370190505b50905060008467ffffffffffffffff81111561244657612446612cdd565b60405190808252806020026020018201604052801561246f578160200160208202803683370190505b50905060008567ffffffffffffffff81111561248d5761248d612cdd565b6040519080825280602002602001820160405280156124b6578160200160208202803683370190505b50905060008667ffffffffffffffff8111156124d4576124d4612cdd565b6040519080825280602002602001820160405280156124fd578160200160208202803683370190505b50905060008060005b8881101561265d5760008c828151811061252257612522612cf3565b60200260200101511115612655578b818151811061254257612542612cf3565b602002602001015191508188848151811061255f5761255f612cf3565b6020908102919091018101919091526000838152600590915260409020600181015488516001600160a01b03909116908990869081106125a1576125a1612cf3565b6001600160a01b039283166020918202929092010152815488519116908890869081106125d0576125d0612cf3565b60200260200101906001600160a01b031690816001600160a01b0316815250508b828151811061260257612602612cf3565b602002602001015186858151811061261c5761261c612cf3565b6020026020010181815250508185858151811061263b5761263b612cf3565b60209081029190910101528361265081612fa9565b945050505b600101612506565b50885b8015612712578861267081613045565b99506000905084612682600184612cca565b8151811061269257612692612cf3565b6020026020010151905060068a815481106126af576126af612cf3565b9060005260206000200154600682815481106126cd576126cd612cf3565b60009182526020909120015560068054806126ea576126ea612d09565b60019003818190600052602060002001600090559055508061270b90613045565b9050612660565b506000547fd19a3d42ed383465e4058c322d9411aeac76ddb8454d22e139fc99808bd569528888888860405161274b9493929190613096565b60405180910390a25050505050505050505050565b600060405163a9059cbb60e01b6000528360045282602452602060006044600080895af13d15601f3d11600160005114161716915060006060528060405250806127dd5760405163abae3d6d60e01b81526001600160a01b038086166004830152306024830152841660448201526064810183905260840161072f565b50505050565b60408051600180825281830190925260609160208083019080368337019050509050816001600160a01b031663affed0e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612843573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612867919061302c565b8160008151811061287a5761287a612cf3565b602002602001018181525050919050565b60006128988484846128a0565b949350505050565b600080821180156128e45750826000815181106128bf576128bf612cf3565b6020026020010151846000815181106128da576128da612cf3565b6020026020010151115b15610bb357600082846000815181106128ff576128ff612cf3565b60200260200101518660008151811061291a5761291a612cf3565b602002602001015161292c9190612cca565b61293e90670de0b6b3a7640000612f70565b6129489190612f87565b7f0000000000000000000000000000000000000000000000000000000000000000111595945050505050565b508054600082559060005260206000209081019061299291906129e0565b50565b8280548282559060005260206000209081019282156129d0579160200282015b828111156129d05782518255916020019190600101906129b5565b506129dc9291506129e0565b5090565b5b808211156129dc57600081556001016129e1565b6001600160a01b038116811461299257600080fd5b600080600080600060808688031215612a2257600080fd5b8535612a2d816129f5565b94506020860135612a3d816129f5565b935060408601359250606086013567ffffffffffffffff80821115612a6157600080fd5b818801915088601f830112612a7557600080fd5b813581811115612a8457600080fd5b896020828501011115612a9657600080fd5b9699959850939650602001949392505050565b600060208284031215612abb57600080fd5b5035919050565b60008151808452602080850194506020840160005b83811015612af357815187529582019590820190600101612ad7565b509495945050505050565b6020815260006001600160a01b0380845116602084015280602085015116604084015250604083015160c06060840152612b3b60e0840182612ac2565b905060608401516080840152608084015160a084015260a084015160c08401528091505092915050565b602081526000610bb36020830184612ac2565b60a081526000612b8b60a0830188612ac2565b6020838203818501528188518084528284019150828160051b850101838b0160005b83811015612bdb57601f19878403018552612bc9838351612ac2565b94860194925090850190600101612bad565b50508681036040880152612bef818b612ac2565b9450505050508281036060840152612c078186612ac2565b90508281036080840152612c1b8185612ac2565b98975050505050505050565b634e487b7160e01b600052602160045260246000fd5b6020810160038310612c5f57634e487b7160e01b600052602160045260246000fd5b91905290565b60006020808352835180602085015260005b81811015612c9357858101830151858201604001528201612c77565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115611f0d57611f0d612cb4565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b838152606060208201526000612d386060830185612ac2565b9050826040830152949350505050565b80820180821115611f0d57611f0d612cb4565b604051610100810167ffffffffffffffff81118282101715612d7f57612d7f612cdd565b60405290565b80516bffffffffffffffffffffffff81168114612da157600080fd5b919050565b8051612da1816129f5565b805163ffffffff81168114612da157600080fd5b805160068110612da157600080fd5b600082601f830112612de557600080fd5b8151602067ffffffffffffffff80831115612e0257612e02612cdd565b8260051b604051601f19603f83011681018181108482111715612e2757612e27612cdd565b6040529384526020818701810194908101925087851115612e4757600080fd5b6020870191505b84821015612e6e57612e5f82612db1565b83529183019190830190612e4e565b979650505050505050565b600060208284031215612e8b57600080fd5b815167ffffffffffffffff80821115612ea357600080fd5b908301906101008286031215612eb857600080fd5b612ec0612d5b565b612ec983612d85565b8152612ed760208401612da6565b602082015260408301516040820152612ef260608401612db1565b6060820152612f0360808401612db1565b6080820152612f1460a08401612db1565b60a0820152612f2560c08401612dc5565b60c082015260e083015182811115612f3c57600080fd5b612f4887828601612dd4565b60e08301525095945050505050565b8281526040602082015260006128986040830184612ac2565b8082028115828204841417611f0d57611f0d612cb4565b600082612fa457634e487b7160e01b600052601260045260246000fd5b500490565b600060018201612fbb57612fbb612cb4565b5060010190565b838152606060208201526000612fdb6060830185612ac2565b8281036040840152612fed8185612ac2565b9695505050505050565b6000806040838503121561300a57600080fd5b8251613015816129f5565b915061302360208401612d85565b90509250929050565b60006020828403121561303e57600080fd5b5051919050565b60008161305457613054612cb4565b506000190190565b60008151808452602080850194506020840160005b83811015612af35781516001600160a01b031687529582019590820190600101613071565b6080815260006130a96080830187612ac2565b82810360208401526130bb818761305c565b905082810360408401526130cf818661305c565b90508281036060840152612e6e8185612ac256fea26469706673582212201cbb3243bdf2246a74a754c4b24385dc52b256b192f67778a3b3a76648374a5864736f6c63430008170033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/backend/operate/ledger/ethereum.py b/backend/operate/ledger/ethereum.py index 50d67a1b2..417c764d9 100644 --- a/backend/operate/ledger/ethereum.py +++ b/backend/operate/ledger/ethereum.py @@ -20,11 +20,50 @@ """Ethereum ledger helpers.""" import typing as t - -from aea_ledger_ethereum import EthereumCrypto +from datetime import datetime +from aea_ledger_ethereum import EthereumCrypto, EthereumApi from operate.ledger.base import LedgerHelper from operate.types import LedgerType from web3 import HTTPProvider, Web3 +from operate.ledger.profiles import CONTRACTS +from operate.types import ChainType +import json +from pathlib import Path +from requests.exceptions import ConnectionError as RequestsConnectionError +from autonomy.chain.exceptions import ( + ChainInteractionError, + ChainTimeoutError, + RPCError, +) +from eth_typing import HexStr +from autonomy.chain.tx import ( + TxSettler, + should_retry, + should_reprice, +) +import time +from enum import Enum + + +DEFAULT_ON_CHAIN_INTERACT_TIMEOUT = 120.0 +DEFAULT_ON_CHAIN_INTERACT_RETRIES = 10 +DEFAULT_ON_CHAIN_INTERACT_SLEEP = 6.0 +ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" +ZERO_ETH = 0 + +GAS_PARAMS = { + "maxFeePerGas": 30_000_000_000, + "maxPriorityFeePerGas": 3_000_000_000, + "gas": 500_000, +} + + +class StakingState(Enum): + """Staking state enumeration for the staking.""" + + UNSTAKED = 0 + STAKED = 1 + EVICTED = 2 class Ethereum(LedgerHelper): @@ -34,7 +73,10 @@ class Ethereum(LedgerHelper): def __init__(self, rpc: str) -> None: super().__init__(rpc) - self.api = Web3(provider=HTTPProvider(self.rpc)) + self.ledger_api = EthereumApi(address=self.rpc) + self.api = self.ledger_api.api + self.contracts = {chain_type: {} for chain_type in ChainType} + self.load_contracts() def create_key(self) -> t.Dict: """Create key.""" @@ -45,3 +87,160 @@ def create_key(self) -> t.Dict: "encrypted": False, "ledger": LedgerType.ETHEREUM, } + + def load_contracts(self) -> None: + """Load all contracts""" + + for abi_path in Path("operate", "ledger", "abis").iterdir(): + for chain_type in ChainType: + if chain_type not in CONTRACTS: + continue + if abi_path.stem not in CONTRACTS[chain_type]: + continue + with open(abi_path, "r") as abi_file: + abi = json.load(abi_file)["abi"] + self.contracts[chain_type][abi_path.stem] = self.api.eth.contract( + address=CONTRACTS[chain_type][abi_path.stem], + abi=abi + ) + + + def get_staking_status(self, service_id) -> StakingState: + """Is the service staked?""" + staking_contract = self.contracts[ChainType.GNOSIS]["ServiceStakingToken"] + a = staking_contract.functions.getServiceStakingState(service_id).call() + return StakingState(a) + + + def is_available_slots(self) -> bool: + """Check if there are available slots on the staking contract""" + staking_contract = self.contracts[ChainType.GNOSIS]["ServiceStakingToken"] + max_num_services = staking_contract.functions.maxNumServices().call() + service_ids = staking_contract.functions.getServiceIds().call() + return max_num_services - len(service_ids) + + + def stake(self, service_id, crypto) -> bool: + """Stake the service""" + + if self.get_staking_status(service_id) != StakingState.UNSTAKED: + return False + + staking_contract = self.contracts[ChainType.GNOSIS]["ServiceStakingToken"] + erc20_contract = self.contracts[ChainType.GNOSIS]["ERC20"] + + # Approval tx: approve the service token to be spent + # We make use of the ERC20 contract to build the approval transaction + # since it has the same interface as ERC721 + # We use the ZERO_ADDRESS as the contract address since we don't do any contract interaction here, + # we are simply encoding + spender = staking_contract.address + amount = service_id + data = erc20_contract.encodeABI("approve", args=(spender, amount)) + + approval_tx = { + "data": bytes.fromhex(data[2:]), + "to": CONTRACTS[ChainType.GNOSIS]["service_registry"], + "value": ZERO_ETH, + } + + # Stake tx + stake_tx = staking_contract.encodeABI("stake", args=[service_id]) + + # Send txs + for tx in (approval_tx, stake_tx): + self.send_tx_and_wait_for_receipt(crypto, tx) + + return True + + + def unstake(self, service_id, crypto) -> bool: + """Unstake the service""" + + if self.get_staking_status(service_id) != StakingState.STAKED: + return False + + # TODO: check unstaking availability for EVICTED services + + staking_contract = self.contracts[ChainType.GNOSIS]["ServiceStakingToken"] + data = staking_contract.encodeABI("unstake", args=[service_id]) + + unstake_tx = { + "data": bytes.fromhex(data[2:]), + "to": CONTRACTS[ChainType.GNOSIS]["ServiceStakingToken"], + "value": ZERO_ETH, + } + + self.send_tx_and_wait_for_receipt(crypto, unstake_tx) + + return True + + + def send_tx_and_wait_for_receipt( + self, + crypto: EthereumCrypto, + raw_tx: t.Dict[str, t.Any], + ) -> t.Dict[str, t.Any]: + """Send transaction and wait for receipt.""" + receipt = HexStr(self.send_tx(crypto, raw_tx)) + if receipt["status"] != 1: + raise ValueError("Transaction failed. Receipt:", receipt) + return receipt + + + def send_tx( + self, + crypto: EthereumCrypto, + raw_tx: t.Dict[str, t.Any], + timeout: float = DEFAULT_ON_CHAIN_INTERACT_TIMEOUT, + max_retries: int = DEFAULT_ON_CHAIN_INTERACT_RETRIES, + sleep: float = DEFAULT_ON_CHAIN_INTERACT_SLEEP, + ) -> str: + """Send transaction.""" + tx_dict = { + **raw_tx, + **GAS_PARAMS, + "from": crypto.address, + "nonce": self.api.eth.get_transaction_count(crypto.address), + "chainId": self.api.eth.chain_id, + } + gas_params = self.ledger_api.try_get_gas_pricing() + if gas_params is not None: + tx_dict.update(gas_params) + + tx_settler = TxSettler(self.api, crypto, ChainType.CUSTOM) + retries = 0 + tx_digest = None + already_known = False + deadline = datetime.now().timestamp() + timeout + while retries < max_retries and deadline >= datetime.now().timestamp(): + retries += 1 + try: + if not already_known: + tx_signed = crypto.sign_transaction(transaction=tx_dict) + tx_digest = self.ledger_api.send_signed_transaction( + tx_signed=tx_signed, + raise_on_try=True, + ) + tx_receipt = self.api.eth.get_transaction_receipt( + t.cast(str, tx_digest) + ) + if tx_receipt is not None: + return tx_receipt + except RequestsConnectionError as e: + raise RPCError("Cannot connect to the given RPC") from e + except Exception as e: # pylint: disable=broad-except + error = str(e) + if tx_settler._already_known(error): + already_known = True + continue # pragma: nocover + if not should_retry(error): + raise ChainInteractionError(error) from e + if should_reprice(error): + print("Repricing the transaction...") + tx_dict = tx_settler._repice(t.cast(t.Dict, tx_dict)) + continue + print(f"Error occurred when interacting with chain: {e}; ") + print(f"will retry in {sleep}...") + time.sleep(sleep) + raise ChainTimeoutError("Timed out when waiting for transaction to go through") \ No newline at end of file diff --git a/backend/operate/ledger/profiles.py b/backend/operate/ledger/profiles.py index 43e5bff84..468c5cbb1 100644 --- a/backend/operate/ledger/profiles.py +++ b/backend/operate/ledger/profiles.py @@ -29,5 +29,7 @@ "gnosis_safe_proxy_factory": "0x3C1fF68f5aa342D296d4DEe4Bb1cACCA912D95fE", "gnosis_safe_same_address_multisig": "0x6e7f594f680f7aBad18b7a63de50F0FeE47dfD06", "multisend": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", + "ServiceStakingToken": "0x2Ef503950Be67a98746F484DA0bBAdA339DF3326", + "ERC20": "0x0000000000000000000000000000000000000000", # just for encoding } } From c0899447416f737f914059772e11d161fdca0a88 Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Thu, 15 Feb 2024 16:14:47 +0530 Subject: [PATCH 2/9] chore: fix gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 21aab4fdf..61a193911 100644 --- a/.gitignore +++ b/.gitignore @@ -37,7 +37,6 @@ yarn-error.log* next-env.d.ts # python -data backend/__pycache__/ backend/scripts/__pycache__/ .operate/ From 5cab8794b2f9547e4bc4fd4e87b3174a9f69a980 Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Thu, 15 Feb 2024 16:15:33 +0530 Subject: [PATCH 3/9] chore: move abis to data folder --- backend/operate/data/__init__.py | 24 +++++++++++++++++++ .../operate/{ledger => data}/abis/ERC20.json | 0 .../abis/ServiceStakingToken.json | 0 3 files changed, 24 insertions(+) create mode 100644 backend/operate/data/__init__.py rename backend/operate/{ledger => data}/abis/ERC20.json (100%) rename backend/operate/{ledger => data}/abis/ServiceStakingToken.json (100%) diff --git a/backend/operate/data/__init__.py b/backend/operate/data/__init__.py new file mode 100644 index 000000000..14575eed2 --- /dev/null +++ b/backend/operate/data/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 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. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ + +"""Data module.""" + +from pathlib import Path + +DATA_DIR = Path(__file__).parent diff --git a/backend/operate/ledger/abis/ERC20.json b/backend/operate/data/abis/ERC20.json similarity index 100% rename from backend/operate/ledger/abis/ERC20.json rename to backend/operate/data/abis/ERC20.json diff --git a/backend/operate/ledger/abis/ServiceStakingToken.json b/backend/operate/data/abis/ServiceStakingToken.json similarity index 100% rename from backend/operate/ledger/abis/ServiceStakingToken.json rename to backend/operate/data/abis/ServiceStakingToken.json From 19ecb1e59813c632971658183a9f2d9d88e0614b Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Fri, 16 Feb 2024 13:02:22 +0530 Subject: [PATCH 4/9] feat: add staking contract --- backend/operate/data/abis/ERC20.json | 288 ---- .../data/abis/ServiceStakingToken.json | 1355 ----------------- backend/operate/data/contracts/__init__.py | 20 + .../service_staking_token/__init__.py | 20 + .../build/ServiceStakingToken.json | 1134 ++++++++++++++ .../service_staking_token/contract.py | 135 ++ .../service_staking_token/contract.yaml | 23 + 7 files changed, 1332 insertions(+), 1643 deletions(-) delete mode 100644 backend/operate/data/abis/ERC20.json delete mode 100644 backend/operate/data/abis/ServiceStakingToken.json create mode 100644 backend/operate/data/contracts/__init__.py create mode 100644 backend/operate/data/contracts/service_staking_token/__init__.py create mode 100644 backend/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json create mode 100644 backend/operate/data/contracts/service_staking_token/contract.py create mode 100644 backend/operate/data/contracts/service_staking_token/contract.yaml diff --git a/backend/operate/data/abis/ERC20.json b/backend/operate/data/abis/ERC20.json deleted file mode 100644 index da6252cad..000000000 --- a/backend/operate/data/abis/ERC20.json +++ /dev/null @@ -1,288 +0,0 @@ -{ - "_format": "", - "contractName": "", - "sourceName": "", - "abi": [ - { - "constant": true, - "inputs": [], - "name": "name", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "guy", - "type": "address" - }, - { - "name": "wad", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "src", - "type": "address" - }, - { - "name": "dst", - "type": "address" - }, - { - "name": "wad", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "wad", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "decimals", - "outputs": [ - { - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "symbol", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "dst", - "type": "address" - }, - { - "name": "wad", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "deposit", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - }, - { - "name": "", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "payable": true, - "stateMutability": "payable", - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "src", - "type": "address" - }, - { - "indexed": true, - "name": "guy", - "type": "address" - }, - { - "indexed": false, - "name": "wad", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "src", - "type": "address" - }, - { - "indexed": true, - "name": "dst", - "type": "address" - }, - { - "indexed": false, - "name": "wad", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "dst", - "type": "address" - }, - { - "indexed": false, - "name": "wad", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "src", - "type": "address" - }, - { - "indexed": false, - "name": "wad", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - } - ], - "bytecode": "", - "deployedBytecode": "", - "linkReferences": {}, - "deployedLinkReferences": {} -} \ No newline at end of file diff --git a/backend/operate/data/abis/ServiceStakingToken.json b/backend/operate/data/abis/ServiceStakingToken.json deleted file mode 100644 index e1405c0bf..000000000 --- a/backend/operate/data/abis/ServiceStakingToken.json +++ /dev/null @@ -1,1355 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "ServiceStakingToken", - "sourceName": "contracts/staking/ServiceStakingToken.sol", - "abi": [ - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "maxNumServices", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "rewardsPerSecond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minStakingDeposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minNumStakingPeriods", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxNumInactivityPeriods", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "livenessPeriod", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "livenessRatio", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "numAgentInstances", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "agentIds", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "threshold", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "configHash", - "type": "bytes32" - } - ], - "internalType": "struct ServiceStakingBase.StakingParams", - "name": "_stakingParams", - "type": "tuple" - }, - { - "internalType": "address", - "name": "_serviceRegistry", - "type": "address" - }, - { - "internalType": "address", - "name": "_serviceRegistryTokenUtility", - "type": "address" - }, - { - "internalType": "address", - "name": "_stakingToken", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_proxyHash", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "AgentInstanceRegistered", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "AgentInstancesSlotsFilled", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "agentId", - "type": "uint256" - } - ], - "name": "AgentNotFound", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "agentId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "AgentNotInService", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "componentId", - "type": "uint256" - } - ], - "name": "ComponentNotFound", - "type": "error" - }, - { - "inputs": [], - "name": "HashExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "sent", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "IncorrectAgentBondingValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "sent", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "IncorrectRegistrationDepositValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "provided", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - } - ], - "name": "LowerThan", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "manager", - "type": "address" - } - ], - "name": "ManagerOnly", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxNumServices", - "type": "uint256" - } - ], - "name": "MaxNumServicesReached", - "type": "error" - }, - { - "inputs": [], - "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": [ - { - "internalType": "address", - "name": "provided", - "type": "address" - }, - { - "internalType": "address", - "name": "expected", - "type": "address" - }, - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "OnlyOwnServiceMultisig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "OperatorHasNoInstances", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "provided", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "max", - "type": "uint256" - } - ], - "name": "Overflow", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnerOnly", - "type": "error" - }, - { - "inputs": [], - "name": "Paused", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrancyGuard", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "ServiceMustBeInactive", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "ServiceNotUnstaked", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "TokenTransferFailed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "multisig", - "type": "address" - } - ], - "name": "UnauthorizedMultisig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "provided", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - } - ], - "name": "ValueLowerThan", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "agentId", - "type": "uint256" - } - ], - "name": "WrongAgentId", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numValues1", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "numValues2", - "type": "uint256" - } - ], - "name": "WrongArrayLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "WrongOperator", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "WrongServiceConfiguration", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "state", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "WrongServiceState", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "expected", - "type": "address" - }, - { - "internalType": "address", - "name": "provided", - "type": "address" - } - ], - "name": "WrongStakingToken", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "currentThreshold", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minThreshold", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxThreshold", - "type": "uint256" - } - ], - "name": "WrongThreshold", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroValue", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "availableRewards", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "serviceIds", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "rewards", - "type": "uint256[]" - } - ], - "name": "Checkpoint", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "availableRewards", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "multisig", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "nonces", - "type": "uint256[]" - } - ], - "name": "ServiceStaked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "multisig", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "nonces", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "reward", - "type": "uint256" - } - ], - "name": "ServiceUnstaked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "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": "ServicesEvicted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdraw", - "type": "event" - }, - { - "inputs": [], - "name": "VERSION", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "agentIds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "availableRewards", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "balance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "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": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "calculateServiceStakingReward", - "outputs": [ - { - "internalType": "uint256", - "name": "reward", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "checkpoint", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "uint256[][]", - "name": "", - "type": "uint256[][]" - }, - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "evictServiceIds", - "type": "uint256[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "configHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "deposit", - "outputs": [], - "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", - "outputs": [ - { - "internalType": "uint256", - "name": "tsNext", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getServiceIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "getServiceInfo", - "outputs": [ - { - "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", - "type": "function" - }, - { - "inputs": [], - "name": "livenessPeriod", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "livenessRatio", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "mapServiceInfo", - "outputs": [ - { - "internalType": "address", - "name": "multisig", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tsStart", - "type": "uint256" - }, - { - "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", - "type": "function" - }, - { - "inputs": [], - "name": "maxNumServices", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minStakingDeposit", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minStakingDuration", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "numAgentInstances", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "onERC721Received", - "outputs": [ - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "proxyHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "rewardsPerSecond", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "serviceRegistry", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "serviceRegistryTokenUtility", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "setServiceIds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "stake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "stakingToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "threshold", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "tsCheckpoint", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "serviceId", - "type": "uint256" - } - ], - "name": "unstake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x6102606040523480156200001257600080fd5b506040516200383a3803806200383a833981016040819052620000359162000453565b8484828260000151600014806200004e57506020830151155b806200005c575060a0830151155b806200006a575060c0830151155b8062000078575060e0830151155b806200008657506060830151155b806200009457506080830151155b15620000b357604051637c946ed760e01b815260040160405180910390fd5b826080015183606001511015620000f5576060830151608084015160405163491a2bb160e01b8152600481019290925260248201526044015b60405180910390fd5b6002836040015110156200012d57604080840151905163491a2bb160e01b8152600481019190915260026024820152604401620000ec565b6001600160a01b038216620001555760405163d92e233d60e01b815260040160405180910390fd5b82516080908152602084015160a0908152604085015160c09081529185015160e0908152908501516101005290840151610120908152908401516101409081526001600160a01b0384166101a0529084015161016052830151610180526000805b846101000151518110156200029257818561010001518281518110620001e057620001e062000576565b6020026020010151116200022d57846101000151818151811062000208576200020862000576565b6020026020010151604051632ab10b0b60e21b8152600401620000ec91815260200190565b846101000151818151811062000247576200024762000576565b602090810291909101015160048054600181810183556000929092527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0182905590925001620001b6565b5081620002b257604051637c946ed760e01b815260040160405180910390fd5b6101c0829052610100516060850151620002cd91906200058c565b6101e052610100516080850151620002e691906200058c565b6102005250504260035550506001600160a01b03821615806200031057506001600160a01b038316155b156200032f5760405163d92e233d60e01b815260040160405180910390fd5b506001600160a01b0390811661024052166102205250620005b89050565b634e487b7160e01b600052604160045260246000fd5b60405161016081016001600160401b03811182821017156200038957620003896200034d565b60405290565b600082601f830112620003a157600080fd5b815160206001600160401b0380831115620003c057620003c06200034d565b8260051b604051601f19603f83011681018181108482111715620003e857620003e86200034d565b60405293845260208187018101949081019250878511156200040957600080fd5b6020870191505b848210156200042b5781518352918301919083019062000410565b979650505050505050565b80516001600160a01b03811681146200044e57600080fd5b919050565b600080600080600060a086880312156200046c57600080fd5b85516001600160401b03808211156200048457600080fd5b90870190610160828a0312156200049a57600080fd5b620004a462000363565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e082015261010080840151838111156200050357600080fd5b620005118c8287016200038f565b918301919091525061012083810151908201526101409283015192810192909252509450620005436020870162000436565b9350620005536040870162000436565b9250620005636060870162000436565b9150608086015190509295509295909350565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417620005b257634e487b7160e01b600052601160045260246000fd5b92915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161311962000721600039600081816104110152818161130901528181611c1401528181611d1e0152611d6201526000818161030501528181611ca40152611e0e01526000818161068e015281816118a50152611b1401526000818161024b0152818161074d015261079f01526000818161044b0152610fca0152600081816105cf01528181610a0101528181610d8601526111bd0152600081816105f601528181610e4e0152610e7d01526000818161036201528181610ec40152610ef80152600081816103c30152610e0c0152600081816103ea015261294a01526000818161038901528181611bc60152611fb80152600061049b01526000818161061d0152611d9901526000818161064401526122ae0152600081816102de01528181610d0d0152610d4101526131196000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c8063a0ed60e011610145578063cbcf252a116100bd578063eb338c961161008c578063f4dce71411610071578063f4dce71414610681578063f86ad2b614610689578063ffa1ad74146106b057600080fd5b8063eb338c9614610666578063f189e85a1461067957600080fd5b8063cbcf252a146105ca578063e1f1176d146105f1578063e77cdcc914610618578063eacdaabc1461063f57600080fd5b8063b69ef8a811610114578063c2c4c5c1116100f9578063c2c4c5c11461057e578063c889921d14610597578063cae2a5f0146105aa57600080fd5b8063b69ef8a814610562578063b6b55f251461056b57600080fd5b8063a0ed60e014610496578063a694fc3a146104bd578063a74466ad146104d0578063b15087601461054d57600080fd5b806352c824f5116101d857806372f702f3116101a7578063809cee2f1161018c578063809cee2f1461044657806382a8ea581461046d578063879d90901461048d57600080fd5b806372f702f31461040c57806378e061361461043357600080fd5b806352c824f51461038457806356e76058146103ab5780635829c5ec146103be578063592cf3fb146103e557600080fd5b8063287140511161021457806328714051146103005780632e17de781461033f5780633e7329971461035457806342cde4e81461035d57600080fd5b806308ae7e541461024657806314b19c5a14610280578063150b7a021461028957806316a75172146102d9575b600080fd5b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61026d60005481565b6102a8610297366004612a0a565b630a85bd0160e11b95945050505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610277565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610277565b61035261034d366004612aa9565b6106e1565b005b61026d60035481565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d6103b9366004612aa9565b610acf565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b61026d610441366004612aa9565b610af0565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61048061047b366004612aa9565b610bba565b6040516102779190612afe565b61026d60025481565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103526104cb366004612aa9565b610cb1565b61051a6104de366004612aa9565b6005602081905260009182526040909120805460018201546003830154600484015493909401546001600160a01b039283169492909116929085565b604080516001600160a01b039687168152959094166020860152928401919091526060830152608082015260a001610277565b61055561127e565b6040516102779190612b65565b61026d60015481565b610352610579366004612aa9565b6112d6565b610586611378565b604051610277959493929190612b78565b61026d6105a5366004612aa9565b6119ad565b6105bd6105b8366004612aa9565b611a69565b6040516102779190612c3d565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d610674366004612aa9565b611b5c565b610555611b6c565b61026d611bc2565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6106d4604051806040016040528060058152602001640302e312e360dc1b81525081565b6040516102779190612c65565b600081815260056020526040902060018101546001600160a01b0316331461073857600181015460405163521eb56d60e11b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b600381015460006107498242612cca565b90507f0000000000000000000000000000000000000000000000000000000000000000811115801561077d57506000600254115b156107cb5760405163ba2bbc6b60e01b815260048101859052602481018290527f0000000000000000000000000000000000000000000000000000000000000000604482015260640161072f565b6000806107d6611378565b945050505091508151600003610837576107ee611b6c565b9150815167ffffffffffffffff81111561080a5761080a612cdd565b604051908082528060200260200182016040528015610833578160200160208202803683370190505b5090505b6000805b8351821015610898578783838151811061085757610857612cf3565b60200260200101510315610898578784838151811061087857610878612cf3565b60200260200101510361088d57506001610898565b81600101915061083b565b600487015460028801805460408051602080840282018101909252828152600093909290918301828280156108ec57602002820191906000526020600020905b8154815260200190600101908083116108d8575b50508c5460008f8152600560205260408120805473ffffffffffffffffffffffffffffffffffffffff19908116825560018201805490911690559596506001600160a01b03909116949350915061094890506002830182612974565b506000600382018190556004820181905560059091015583156109d7576006805461097590600190612cca565b8154811061098557610985612cf3565b9060005260206000200154600686815481106109a3576109a3612cf3565b60009182526020909120015560068054806109c0576109c0612d09565b600190038181906000526020600020016000905590555b604051632142170760e11b8152306004820152336024820152604481018c90526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90606401600060405180830381600087803b158015610a4557600080fd5b505af1158015610a59573d6000803e3d6000fd5b505050506000831115610a7057610a708184611bf7565b806001600160a01b0316336001600160a01b03168c7f950733f4c0bf951b8e770f3cc619a4288e7b59b1236d59aeaf2c238488e8ae816000548688604051610aba93929190612d1f565b60405180910390a45050505050505050505050565b60048181548110610adf57600080fd5b600091825260209091200154905081565b6000818152600560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015610b7057602002820191906000526020600020905b815481526020019060010190808311610b5c575b505050505081526020016003820154815260200160048201548152602001600582015481525050905080608001519150610ba9836119ad565b610bb39083612d48565b9392505050565b610c056040518060c0016040528060006001600160a01b0316815260200160006001600160a01b03168152602001606081526020016000815260200160008152602001600081525090565b600082815260056020908152604091829020825160c08101845281546001600160a01b0390811682526001830154168184015260028201805485518186028101860187528181529295939493860193830182828015610c8357602002820191906000526020600020905b815481526020019060010190808311610c6f575b5050505050815260200160038201548152602001600482015481526020016005820154815250509050919050565b600254600003610cd45760405163afb0be3360e01b815260040160405180910390fd5b6000818152600560205260409020600381015415610d085760405163b4817ce760e01b81526004810183905260240161072f565b6006547f00000000000000000000000000000000000000000000000000000000000000008103610d6d5760405163fd20861560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015260240161072f565b60405163ef0e239b60e01b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef0e239b90602401600060405180830381865afa158015610dd5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dfd9190810190612e79565b9050806080015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014610e4c57604051637ad404bf60e11b81526004810185905260240161072f565b7f000000000000000000000000000000000000000000000000000000000000000015801590610e9f575080604001517f000000000000000000000000000000000000000000000000000000000000000014155b15610ec057604051637ad404bf60e11b81526004810185905260240161072f565b60007f0000000000000000000000000000000000000000000000000000000000000000118015610f1a5750806060015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014155b15610f3b57604051637ad404bf60e11b81526004810185905260240161072f565b60048160c001516005811115610f5357610f53612c27565b14610f92578060c001516005811115610f6e57610f6e612c27565b604051633c053f9d60e21b815260048101919091526024810185905260440161072f565b600081602001516001600160a01b0316803b806020016040519081016040528181526000908060200190933c805190602001209050807f00000000000000000000000000000000000000000000000000000000000000001461101757602082015160405162a2307960e51b81526001600160a01b03909116600482015260240161072f565b60045480156110e05760e08301515181811461104957604051637ad404bf60e11b81526004810188905260240161072f565b60005b818110156110dd578460e00151818151811061106a5761106a612cf3565b602002602001015163ffffffff166004828154811061108b5761108b612cf3565b9060005260206000200154146110d557600481815481106110ae576110ae612cf3565b9060005260206000200154604051632ab10b0b60e21b815260040161072f91815260200190565b60010161104c565b50505b6111018684600001516bffffffffffffffffffffffff168560e00151611c81565b602083015185546001600160a01b03821673ffffffffffffffffffffffffffffffffffffffff199182161787556001870180549091163317905560009061114790611f02565b805190915061115f9060028801906020840190612995565b50426003870155600680546001810182556000919091527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01879055604051632142170760e11b8152336004820152306024820152604481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342842e0e90606401600060405180830381600087803b15801561120957600080fd5b505af115801561121d573d6000803e3d6000fd5b5050505083602001516001600160a01b0316336001600160a01b0316887faa6b005b4958114a0c90492461c24af6525ae0178db7fbf44125ae9217c69ccb6000548560405161126d929190612f57565b60405180910390a450505050505050565b606060048054806020026020016040519081016040528092919081815260200182805480156112cc57602002820191906000526020600020905b8154815260200190600101908083116112b8575b5050505050905090565b6000816001546112e69190612d48565b90506000826002546112f89190612d48565b6001839055600281905590506113307f0000000000000000000000000000000000000000000000000000000000000000333086611f13565b604080518481526020810184905290810182905233907f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e9060600160405180910390a2505050565b6060806060806060600080600080600080600080611394611f9d565b97509750975097509750975097509750606080845167ffffffffffffffff8111156113c1576113c1612cdd565b6040519080825280602002602001820160405280156113ea578160200160208202803683370190505b509a506000891561177d578967ffffffffffffffff81111561140e5761140e612cdd565b604051908082528060200260200182016040528015611437578160200160208202803683370190505b5092508967ffffffffffffffff81111561145357611453612cdd565b60405190808252806020026020018201604052801561147c578160200160208202803683370190505b5091508a8911156116865760008060015b8c811015611579578b8e8b83815181106114a9576114a9612cf3565b60200260200101516114bb9190612f70565b6114c59190612f87565b92506114d18383612d48565b91508a81815181106114e5576114e5612cf3565b602002602001015193508a818151811061150157611501612cf3565b602002602001015186828151811061151b5761151b612cf3565b6020026020010181815250508285828151811061153a5761153a612cf3565b6020026020010181815250508260056000868152602001908152602001600020600401600082825461156c9190612d48565b909155505060010161148d565b508a8d8a60008151811061158f5761158f612cf3565b60200260200101516115a19190612f70565b6115ab9190612f87565b91506115b78282612d48565b9050896000815181106115cc576115cc612cf3565b60200260200101519250896000815181106115e9576115e9612cf3565b60200260200101518560008151811061160457611604612cf3565b602002602001018181525050808d111561162f57611622818e612cca565b61162c9083612d48565b91505b818460008151811061164357611643612cf3565b602002602001018181525050816005600085815260200190815260200160002060040160008282546116759190612d48565b9091555060009d5061177792505050565b60005b8a811015611769578881815181106116a3576116a3612cf3565b602002602001015191508881815181106116bf576116bf612cf3565b60200260200101518482815181106116d9576116d9612cf3565b6020026020010181815250508781815181106116f7576116f7612cf3565b602002602001015183828151811061171157611711612cf3565b60200260200101818152505087818151811061172f5761172f612cf3565b602002602001015160056000848152602001908152602001600020600401600082825461175c9190612d48565b9091555050600101611689565b50611774898c612cca565b9a505b60028b90555b855115611997576000995060005b8651811015611930578681815181106117a6576117a6612cf3565b602002602001015191508581815181106117c2576117c2612cf3565b60200260200101516005600084815260200190815260200160002060020190805190602001906117f3929190612995565b50600085828151811061180857611808612cf3565b602002602001015111156119155784818151811061182857611828612cf3565b602002602001015160056000848152602001908152602001600020600501546118519190612d48565b85828151811061186357611863612cf3565b60200260200101818152505084818151811061188157611881612cf3565b602002602001015160056000848152602001908152602001600020600501819055507f00000000000000000000000000000000000000000000000000000000000000008582815181106118d6576118d6612cf3565b6020026020010151111561191057818d82815181106118f7576118f7612cf3565b60209081029190910101528a61190c81612fa9565b9b50505b611928565b6000828152600560208190526040822001555b60010161178b565b508915611942576119428c858c61239b565b42600355600054611954816001612d48565b60005560405181907f06a98bdd4732811ab3214800ed1ada2dce66a2bce301d250c3ca7d6b461ee6669061198d908f9088908890612fc2565b60405180910390a2505b50939e929d509b50919950969750505050505050565b6000806000806000806119be611f9d565b5050509450945094509450945060005b84811015611a5e57878382815181106119e9576119e9612cf3565b602002602001015103611a565785841115611a35578386838381518110611a1257611a12612cf3565b6020026020010151611a249190612f70565b611a2e9190612f87565b9650611a5e565b818181518110611a4757611a47612cf3565b60200260200101519650611a5e565b6001016119ce565b505050505050919050565b6000818152600560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015611ae957602002820191906000526020600020905b815481526020019060010190808311611ad5575b50505050508152602001600382015481526020016004820154815260200160058201548152505090507f00000000000000000000000000000000000000000000000000000000000000008160a001511115611b475760029150611b56565b606081015115611b5657600191505b50919050565b60068181548110610adf57600080fd5b606060068054806020026020016040519081016040528092919081815260200182805480156112cc57602002820191906000526020600020908154815260200190600101908083116112b8575050505050905090565b60007f0000000000000000000000000000000000000000000000000000000000000000600354611bf29190612d48565b905090565b8060016000828254611c099190612cca565b90915550611c3a90507f00000000000000000000000000000000000000000000000000000000000000008383612760565b816001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436482604051611c7591815260200190565b60405180910390a25050565b604051633cebfa4f60e01b81526004810184905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633cebfa4f906024016040805180830381865afa158015611cea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0e9190612ff7565b91509150816001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614611d9757604051630b80380d60e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301528316602482015260440161072f565b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff8216811115611dfe57604051632b30b24760e21b81526bffffffffffffffffffffffff831660048201526024810182905260440161072f565b60005b8451811015611ef95760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166375c1f93489888581518110611e4e57611e4e612cf3565b60200260200101516040518363ffffffff1660e01b8152600401611e8292919091825263ffffffff16602082015260400190565b602060405180830381865afa158015611e9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec3919061302c565b905082811015611ef057604051632b30b24760e21b8152600481018290526024810184905260440161072f565b50600101611e01565b50505050505050565b6060611f0d826127e3565b92915050565b60006040516323b872dd60e01b6000528460045283602452826044526020600060646000808a5af13d15601f3d1160016000511416171691506000606052806040525080611f965760405163abae3d6d60e01b81526001600160a01b0380871660048301528086166024830152841660448201526064810183905260840161072f565b5050505050565b600080600060608060608060606000600354905060025498507f00000000000000000000000000000000000000000000000000000000000000008142611fe39190612cca565b10158015611ff15750600089115b15612390576006548067ffffffffffffffff81111561201257612012612cdd565b60405190808252806020026020018201604052801561203b578160200160208202803683370190505b5094508067ffffffffffffffff81111561205757612057612cdd565b604051908082528060200260200182016040528015612080578160200160208202803683370190505b5096508067ffffffffffffffff81111561209c5761209c612cdd565b6040519080825280602002602001820160405280156120c5578160200160208202803683370190505b5095508067ffffffffffffffff8111156120e1576120e1612cdd565b60405190808252806020026020018201604052801561211457816020015b60608152602001906001900390816120ff5790505b5093508067ffffffffffffffff81111561213057612130612cdd565b604051908082528060200260200182016040528015612159578160200160208202803683370190505b50925060005b8181101561238d576006818154811061217a5761217a612cf3565b906000526020600020015486828151811061219757612197612cf3565b6020026020010181815250506000600560008884815181106121bb576121bb612cf3565b602090810291909101810151825281019190915260400160002080549091506121ec906001600160a01b0316611f02565b8683815181106121fe576121fe612cf3565b6020908102919091010152600381015484908181111561221c578091505b6122268242612cca565b905060006122a089868151811061223f5761223f612cf3565b60200260200101518560020180548060200260200160405190810160405280929190818152602001828054801561229557602002820191906000526020600020905b815481526020019060010190808311612281575b50505050508461288b565b9050801561235e576122d2827f0000000000000000000000000000000000000000000000000000000000000000612f70565b8b8f815181106122e4576122e4612cf3565b6020026020010181815250508a8e8151811061230257612302612cf3565b60200260200101518d6123159190612d48565b9c5089858151811061232957612329612cf3565b60200260200101518c8f8151811061234357612343612cf3565b60209081029190910101526123578e612fa9565b9d5061237e565b8188868151811061237157612371612cf3565b6020026020010181815250505b5050505080600101905061215f565b50505b509091929394959697565b825160008267ffffffffffffffff8111156123b8576123b8612cdd565b6040519080825280602002602001820160405280156123e1578160200160208202803683370190505b50905060008367ffffffffffffffff8111156123ff576123ff612cdd565b604051908082528060200260200182016040528015612428578160200160208202803683370190505b50905060008467ffffffffffffffff81111561244657612446612cdd565b60405190808252806020026020018201604052801561246f578160200160208202803683370190505b50905060008567ffffffffffffffff81111561248d5761248d612cdd565b6040519080825280602002602001820160405280156124b6578160200160208202803683370190505b50905060008667ffffffffffffffff8111156124d4576124d4612cdd565b6040519080825280602002602001820160405280156124fd578160200160208202803683370190505b50905060008060005b8881101561265d5760008c828151811061252257612522612cf3565b60200260200101511115612655578b818151811061254257612542612cf3565b602002602001015191508188848151811061255f5761255f612cf3565b6020908102919091018101919091526000838152600590915260409020600181015488516001600160a01b03909116908990869081106125a1576125a1612cf3565b6001600160a01b039283166020918202929092010152815488519116908890869081106125d0576125d0612cf3565b60200260200101906001600160a01b031690816001600160a01b0316815250508b828151811061260257612602612cf3565b602002602001015186858151811061261c5761261c612cf3565b6020026020010181815250508185858151811061263b5761263b612cf3565b60209081029190910101528361265081612fa9565b945050505b600101612506565b50885b8015612712578861267081613045565b99506000905084612682600184612cca565b8151811061269257612692612cf3565b6020026020010151905060068a815481106126af576126af612cf3565b9060005260206000200154600682815481106126cd576126cd612cf3565b60009182526020909120015560068054806126ea576126ea612d09565b60019003818190600052602060002001600090559055508061270b90613045565b9050612660565b506000547fd19a3d42ed383465e4058c322d9411aeac76ddb8454d22e139fc99808bd569528888888860405161274b9493929190613096565b60405180910390a25050505050505050505050565b600060405163a9059cbb60e01b6000528360045282602452602060006044600080895af13d15601f3d11600160005114161716915060006060528060405250806127dd5760405163abae3d6d60e01b81526001600160a01b038086166004830152306024830152841660448201526064810183905260840161072f565b50505050565b60408051600180825281830190925260609160208083019080368337019050509050816001600160a01b031663affed0e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612843573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612867919061302c565b8160008151811061287a5761287a612cf3565b602002602001018181525050919050565b60006128988484846128a0565b949350505050565b600080821180156128e45750826000815181106128bf576128bf612cf3565b6020026020010151846000815181106128da576128da612cf3565b6020026020010151115b15610bb357600082846000815181106128ff576128ff612cf3565b60200260200101518660008151811061291a5761291a612cf3565b602002602001015161292c9190612cca565b61293e90670de0b6b3a7640000612f70565b6129489190612f87565b7f0000000000000000000000000000000000000000000000000000000000000000111595945050505050565b508054600082559060005260206000209081019061299291906129e0565b50565b8280548282559060005260206000209081019282156129d0579160200282015b828111156129d05782518255916020019190600101906129b5565b506129dc9291506129e0565b5090565b5b808211156129dc57600081556001016129e1565b6001600160a01b038116811461299257600080fd5b600080600080600060808688031215612a2257600080fd5b8535612a2d816129f5565b94506020860135612a3d816129f5565b935060408601359250606086013567ffffffffffffffff80821115612a6157600080fd5b818801915088601f830112612a7557600080fd5b813581811115612a8457600080fd5b896020828501011115612a9657600080fd5b9699959850939650602001949392505050565b600060208284031215612abb57600080fd5b5035919050565b60008151808452602080850194506020840160005b83811015612af357815187529582019590820190600101612ad7565b509495945050505050565b6020815260006001600160a01b0380845116602084015280602085015116604084015250604083015160c06060840152612b3b60e0840182612ac2565b905060608401516080840152608084015160a084015260a084015160c08401528091505092915050565b602081526000610bb36020830184612ac2565b60a081526000612b8b60a0830188612ac2565b6020838203818501528188518084528284019150828160051b850101838b0160005b83811015612bdb57601f19878403018552612bc9838351612ac2565b94860194925090850190600101612bad565b50508681036040880152612bef818b612ac2565b9450505050508281036060840152612c078186612ac2565b90508281036080840152612c1b8185612ac2565b98975050505050505050565b634e487b7160e01b600052602160045260246000fd5b6020810160038310612c5f57634e487b7160e01b600052602160045260246000fd5b91905290565b60006020808352835180602085015260005b81811015612c9357858101830151858201604001528201612c77565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115611f0d57611f0d612cb4565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b838152606060208201526000612d386060830185612ac2565b9050826040830152949350505050565b80820180821115611f0d57611f0d612cb4565b604051610100810167ffffffffffffffff81118282101715612d7f57612d7f612cdd565b60405290565b80516bffffffffffffffffffffffff81168114612da157600080fd5b919050565b8051612da1816129f5565b805163ffffffff81168114612da157600080fd5b805160068110612da157600080fd5b600082601f830112612de557600080fd5b8151602067ffffffffffffffff80831115612e0257612e02612cdd565b8260051b604051601f19603f83011681018181108482111715612e2757612e27612cdd565b6040529384526020818701810194908101925087851115612e4757600080fd5b6020870191505b84821015612e6e57612e5f82612db1565b83529183019190830190612e4e565b979650505050505050565b600060208284031215612e8b57600080fd5b815167ffffffffffffffff80821115612ea357600080fd5b908301906101008286031215612eb857600080fd5b612ec0612d5b565b612ec983612d85565b8152612ed760208401612da6565b602082015260408301516040820152612ef260608401612db1565b6060820152612f0360808401612db1565b6080820152612f1460a08401612db1565b60a0820152612f2560c08401612dc5565b60c082015260e083015182811115612f3c57600080fd5b612f4887828601612dd4565b60e08301525095945050505050565b8281526040602082015260006128986040830184612ac2565b8082028115828204841417611f0d57611f0d612cb4565b600082612fa457634e487b7160e01b600052601260045260246000fd5b500490565b600060018201612fbb57612fbb612cb4565b5060010190565b838152606060208201526000612fdb6060830185612ac2565b8281036040840152612fed8185612ac2565b9695505050505050565b6000806040838503121561300a57600080fd5b8251613015816129f5565b915061302360208401612d85565b90509250929050565b60006020828403121561303e57600080fd5b5051919050565b60008161305457613054612cb4565b506000190190565b60008151808452602080850194506020840160005b83811015612af35781516001600160a01b031687529582019590820190600101613071565b6080815260006130a96080830187612ac2565b82810360208401526130bb818761305c565b905082810360408401526130cf818661305c565b90508281036060840152612e6e8185612ac256fea26469706673582212201cbb3243bdf2246a74a754c4b24385dc52b256b192f67778a3b3a76648374a5864736f6c63430008170033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102415760003560e01c8063a0ed60e011610145578063cbcf252a116100bd578063eb338c961161008c578063f4dce71411610071578063f4dce71414610681578063f86ad2b614610689578063ffa1ad74146106b057600080fd5b8063eb338c9614610666578063f189e85a1461067957600080fd5b8063cbcf252a146105ca578063e1f1176d146105f1578063e77cdcc914610618578063eacdaabc1461063f57600080fd5b8063b69ef8a811610114578063c2c4c5c1116100f9578063c2c4c5c11461057e578063c889921d14610597578063cae2a5f0146105aa57600080fd5b8063b69ef8a814610562578063b6b55f251461056b57600080fd5b8063a0ed60e014610496578063a694fc3a146104bd578063a74466ad146104d0578063b15087601461054d57600080fd5b806352c824f5116101d857806372f702f3116101a7578063809cee2f1161018c578063809cee2f1461044657806382a8ea581461046d578063879d90901461048d57600080fd5b806372f702f31461040c57806378e061361461043357600080fd5b806352c824f51461038457806356e76058146103ab5780635829c5ec146103be578063592cf3fb146103e557600080fd5b8063287140511161021457806328714051146103005780632e17de781461033f5780633e7329971461035457806342cde4e81461035d57600080fd5b806308ae7e541461024657806314b19c5a14610280578063150b7a021461028957806316a75172146102d9575b600080fd5b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61026d60005481565b6102a8610297366004612a0a565b630a85bd0160e11b95945050505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610277565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610277565b61035261034d366004612aa9565b6106e1565b005b61026d60035481565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d6103b9366004612aa9565b610acf565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b61026d610441366004612aa9565b610af0565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61048061047b366004612aa9565b610bba565b6040516102779190612afe565b61026d60025481565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6103526104cb366004612aa9565b610cb1565b61051a6104de366004612aa9565b6005602081905260009182526040909120805460018201546003830154600484015493909401546001600160a01b039283169492909116929085565b604080516001600160a01b039687168152959094166020860152928401919091526060830152608082015260a001610277565b61055561127e565b6040516102779190612b65565b61026d60015481565b610352610579366004612aa9565b6112d6565b610586611378565b604051610277959493929190612b78565b61026d6105a5366004612aa9565b6119ad565b6105bd6105b8366004612aa9565b611a69565b6040516102779190612c3d565b6103277f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b61026d610674366004612aa9565b611b5c565b610555611b6c565b61026d611bc2565b61026d7f000000000000000000000000000000000000000000000000000000000000000081565b6106d4604051806040016040528060058152602001640302e312e360dc1b81525081565b6040516102779190612c65565b600081815260056020526040902060018101546001600160a01b0316331461073857600181015460405163521eb56d60e11b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b600381015460006107498242612cca565b90507f0000000000000000000000000000000000000000000000000000000000000000811115801561077d57506000600254115b156107cb5760405163ba2bbc6b60e01b815260048101859052602481018290527f0000000000000000000000000000000000000000000000000000000000000000604482015260640161072f565b6000806107d6611378565b945050505091508151600003610837576107ee611b6c565b9150815167ffffffffffffffff81111561080a5761080a612cdd565b604051908082528060200260200182016040528015610833578160200160208202803683370190505b5090505b6000805b8351821015610898578783838151811061085757610857612cf3565b60200260200101510315610898578784838151811061087857610878612cf3565b60200260200101510361088d57506001610898565b81600101915061083b565b600487015460028801805460408051602080840282018101909252828152600093909290918301828280156108ec57602002820191906000526020600020905b8154815260200190600101908083116108d8575b50508c5460008f8152600560205260408120805473ffffffffffffffffffffffffffffffffffffffff19908116825560018201805490911690559596506001600160a01b03909116949350915061094890506002830182612974565b506000600382018190556004820181905560059091015583156109d7576006805461097590600190612cca565b8154811061098557610985612cf3565b9060005260206000200154600686815481106109a3576109a3612cf3565b60009182526020909120015560068054806109c0576109c0612d09565b600190038181906000526020600020016000905590555b604051632142170760e11b8152306004820152336024820152604481018c90526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90606401600060405180830381600087803b158015610a4557600080fd5b505af1158015610a59573d6000803e3d6000fd5b505050506000831115610a7057610a708184611bf7565b806001600160a01b0316336001600160a01b03168c7f950733f4c0bf951b8e770f3cc619a4288e7b59b1236d59aeaf2c238488e8ae816000548688604051610aba93929190612d1f565b60405180910390a45050505050505050505050565b60048181548110610adf57600080fd5b600091825260209091200154905081565b6000818152600560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015610b7057602002820191906000526020600020905b815481526020019060010190808311610b5c575b505050505081526020016003820154815260200160048201548152602001600582015481525050905080608001519150610ba9836119ad565b610bb39083612d48565b9392505050565b610c056040518060c0016040528060006001600160a01b0316815260200160006001600160a01b03168152602001606081526020016000815260200160008152602001600081525090565b600082815260056020908152604091829020825160c08101845281546001600160a01b0390811682526001830154168184015260028201805485518186028101860187528181529295939493860193830182828015610c8357602002820191906000526020600020905b815481526020019060010190808311610c6f575b5050505050815260200160038201548152602001600482015481526020016005820154815250509050919050565b600254600003610cd45760405163afb0be3360e01b815260040160405180910390fd5b6000818152600560205260409020600381015415610d085760405163b4817ce760e01b81526004810183905260240161072f565b6006547f00000000000000000000000000000000000000000000000000000000000000008103610d6d5760405163fd20861560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015260240161072f565b60405163ef0e239b60e01b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef0e239b90602401600060405180830381865afa158015610dd5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dfd9190810190612e79565b9050806080015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014610e4c57604051637ad404bf60e11b81526004810185905260240161072f565b7f000000000000000000000000000000000000000000000000000000000000000015801590610e9f575080604001517f000000000000000000000000000000000000000000000000000000000000000014155b15610ec057604051637ad404bf60e11b81526004810185905260240161072f565b60007f0000000000000000000000000000000000000000000000000000000000000000118015610f1a5750806060015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014155b15610f3b57604051637ad404bf60e11b81526004810185905260240161072f565b60048160c001516005811115610f5357610f53612c27565b14610f92578060c001516005811115610f6e57610f6e612c27565b604051633c053f9d60e21b815260048101919091526024810185905260440161072f565b600081602001516001600160a01b0316803b806020016040519081016040528181526000908060200190933c805190602001209050807f00000000000000000000000000000000000000000000000000000000000000001461101757602082015160405162a2307960e51b81526001600160a01b03909116600482015260240161072f565b60045480156110e05760e08301515181811461104957604051637ad404bf60e11b81526004810188905260240161072f565b60005b818110156110dd578460e00151818151811061106a5761106a612cf3565b602002602001015163ffffffff166004828154811061108b5761108b612cf3565b9060005260206000200154146110d557600481815481106110ae576110ae612cf3565b9060005260206000200154604051632ab10b0b60e21b815260040161072f91815260200190565b60010161104c565b50505b6111018684600001516bffffffffffffffffffffffff168560e00151611c81565b602083015185546001600160a01b03821673ffffffffffffffffffffffffffffffffffffffff199182161787556001870180549091163317905560009061114790611f02565b805190915061115f9060028801906020840190612995565b50426003870155600680546001810182556000919091527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01879055604051632142170760e11b8152336004820152306024820152604481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342842e0e90606401600060405180830381600087803b15801561120957600080fd5b505af115801561121d573d6000803e3d6000fd5b5050505083602001516001600160a01b0316336001600160a01b0316887faa6b005b4958114a0c90492461c24af6525ae0178db7fbf44125ae9217c69ccb6000548560405161126d929190612f57565b60405180910390a450505050505050565b606060048054806020026020016040519081016040528092919081815260200182805480156112cc57602002820191906000526020600020905b8154815260200190600101908083116112b8575b5050505050905090565b6000816001546112e69190612d48565b90506000826002546112f89190612d48565b6001839055600281905590506113307f0000000000000000000000000000000000000000000000000000000000000000333086611f13565b604080518481526020810184905290810182905233907f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e9060600160405180910390a2505050565b6060806060806060600080600080600080600080611394611f9d565b97509750975097509750975097509750606080845167ffffffffffffffff8111156113c1576113c1612cdd565b6040519080825280602002602001820160405280156113ea578160200160208202803683370190505b509a506000891561177d578967ffffffffffffffff81111561140e5761140e612cdd565b604051908082528060200260200182016040528015611437578160200160208202803683370190505b5092508967ffffffffffffffff81111561145357611453612cdd565b60405190808252806020026020018201604052801561147c578160200160208202803683370190505b5091508a8911156116865760008060015b8c811015611579578b8e8b83815181106114a9576114a9612cf3565b60200260200101516114bb9190612f70565b6114c59190612f87565b92506114d18383612d48565b91508a81815181106114e5576114e5612cf3565b602002602001015193508a818151811061150157611501612cf3565b602002602001015186828151811061151b5761151b612cf3565b6020026020010181815250508285828151811061153a5761153a612cf3565b6020026020010181815250508260056000868152602001908152602001600020600401600082825461156c9190612d48565b909155505060010161148d565b508a8d8a60008151811061158f5761158f612cf3565b60200260200101516115a19190612f70565b6115ab9190612f87565b91506115b78282612d48565b9050896000815181106115cc576115cc612cf3565b60200260200101519250896000815181106115e9576115e9612cf3565b60200260200101518560008151811061160457611604612cf3565b602002602001018181525050808d111561162f57611622818e612cca565b61162c9083612d48565b91505b818460008151811061164357611643612cf3565b602002602001018181525050816005600085815260200190815260200160002060040160008282546116759190612d48565b9091555060009d5061177792505050565b60005b8a811015611769578881815181106116a3576116a3612cf3565b602002602001015191508881815181106116bf576116bf612cf3565b60200260200101518482815181106116d9576116d9612cf3565b6020026020010181815250508781815181106116f7576116f7612cf3565b602002602001015183828151811061171157611711612cf3565b60200260200101818152505087818151811061172f5761172f612cf3565b602002602001015160056000848152602001908152602001600020600401600082825461175c9190612d48565b9091555050600101611689565b50611774898c612cca565b9a505b60028b90555b855115611997576000995060005b8651811015611930578681815181106117a6576117a6612cf3565b602002602001015191508581815181106117c2576117c2612cf3565b60200260200101516005600084815260200190815260200160002060020190805190602001906117f3929190612995565b50600085828151811061180857611808612cf3565b602002602001015111156119155784818151811061182857611828612cf3565b602002602001015160056000848152602001908152602001600020600501546118519190612d48565b85828151811061186357611863612cf3565b60200260200101818152505084818151811061188157611881612cf3565b602002602001015160056000848152602001908152602001600020600501819055507f00000000000000000000000000000000000000000000000000000000000000008582815181106118d6576118d6612cf3565b6020026020010151111561191057818d82815181106118f7576118f7612cf3565b60209081029190910101528a61190c81612fa9565b9b50505b611928565b6000828152600560208190526040822001555b60010161178b565b508915611942576119428c858c61239b565b42600355600054611954816001612d48565b60005560405181907f06a98bdd4732811ab3214800ed1ada2dce66a2bce301d250c3ca7d6b461ee6669061198d908f9088908890612fc2565b60405180910390a2505b50939e929d509b50919950969750505050505050565b6000806000806000806119be611f9d565b5050509450945094509450945060005b84811015611a5e57878382815181106119e9576119e9612cf3565b602002602001015103611a565785841115611a35578386838381518110611a1257611a12612cf3565b6020026020010151611a249190612f70565b611a2e9190612f87565b9650611a5e565b818181518110611a4757611a47612cf3565b60200260200101519650611a5e565b6001016119ce565b505050505050919050565b6000818152600560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015611ae957602002820191906000526020600020905b815481526020019060010190808311611ad5575b50505050508152602001600382015481526020016004820154815260200160058201548152505090507f00000000000000000000000000000000000000000000000000000000000000008160a001511115611b475760029150611b56565b606081015115611b5657600191505b50919050565b60068181548110610adf57600080fd5b606060068054806020026020016040519081016040528092919081815260200182805480156112cc57602002820191906000526020600020908154815260200190600101908083116112b8575050505050905090565b60007f0000000000000000000000000000000000000000000000000000000000000000600354611bf29190612d48565b905090565b8060016000828254611c099190612cca565b90915550611c3a90507f00000000000000000000000000000000000000000000000000000000000000008383612760565b816001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436482604051611c7591815260200190565b60405180910390a25050565b604051633cebfa4f60e01b81526004810184905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633cebfa4f906024016040805180830381865afa158015611cea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0e9190612ff7565b91509150816001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614611d9757604051630b80380d60e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301528316602482015260440161072f565b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff8216811115611dfe57604051632b30b24760e21b81526bffffffffffffffffffffffff831660048201526024810182905260440161072f565b60005b8451811015611ef95760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166375c1f93489888581518110611e4e57611e4e612cf3565b60200260200101516040518363ffffffff1660e01b8152600401611e8292919091825263ffffffff16602082015260400190565b602060405180830381865afa158015611e9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec3919061302c565b905082811015611ef057604051632b30b24760e21b8152600481018290526024810184905260440161072f565b50600101611e01565b50505050505050565b6060611f0d826127e3565b92915050565b60006040516323b872dd60e01b6000528460045283602452826044526020600060646000808a5af13d15601f3d1160016000511416171691506000606052806040525080611f965760405163abae3d6d60e01b81526001600160a01b0380871660048301528086166024830152841660448201526064810183905260840161072f565b5050505050565b600080600060608060608060606000600354905060025498507f00000000000000000000000000000000000000000000000000000000000000008142611fe39190612cca565b10158015611ff15750600089115b15612390576006548067ffffffffffffffff81111561201257612012612cdd565b60405190808252806020026020018201604052801561203b578160200160208202803683370190505b5094508067ffffffffffffffff81111561205757612057612cdd565b604051908082528060200260200182016040528015612080578160200160208202803683370190505b5096508067ffffffffffffffff81111561209c5761209c612cdd565b6040519080825280602002602001820160405280156120c5578160200160208202803683370190505b5095508067ffffffffffffffff8111156120e1576120e1612cdd565b60405190808252806020026020018201604052801561211457816020015b60608152602001906001900390816120ff5790505b5093508067ffffffffffffffff81111561213057612130612cdd565b604051908082528060200260200182016040528015612159578160200160208202803683370190505b50925060005b8181101561238d576006818154811061217a5761217a612cf3565b906000526020600020015486828151811061219757612197612cf3565b6020026020010181815250506000600560008884815181106121bb576121bb612cf3565b602090810291909101810151825281019190915260400160002080549091506121ec906001600160a01b0316611f02565b8683815181106121fe576121fe612cf3565b6020908102919091010152600381015484908181111561221c578091505b6122268242612cca565b905060006122a089868151811061223f5761223f612cf3565b60200260200101518560020180548060200260200160405190810160405280929190818152602001828054801561229557602002820191906000526020600020905b815481526020019060010190808311612281575b50505050508461288b565b9050801561235e576122d2827f0000000000000000000000000000000000000000000000000000000000000000612f70565b8b8f815181106122e4576122e4612cf3565b6020026020010181815250508a8e8151811061230257612302612cf3565b60200260200101518d6123159190612d48565b9c5089858151811061232957612329612cf3565b60200260200101518c8f8151811061234357612343612cf3565b60209081029190910101526123578e612fa9565b9d5061237e565b8188868151811061237157612371612cf3565b6020026020010181815250505b5050505080600101905061215f565b50505b509091929394959697565b825160008267ffffffffffffffff8111156123b8576123b8612cdd565b6040519080825280602002602001820160405280156123e1578160200160208202803683370190505b50905060008367ffffffffffffffff8111156123ff576123ff612cdd565b604051908082528060200260200182016040528015612428578160200160208202803683370190505b50905060008467ffffffffffffffff81111561244657612446612cdd565b60405190808252806020026020018201604052801561246f578160200160208202803683370190505b50905060008567ffffffffffffffff81111561248d5761248d612cdd565b6040519080825280602002602001820160405280156124b6578160200160208202803683370190505b50905060008667ffffffffffffffff8111156124d4576124d4612cdd565b6040519080825280602002602001820160405280156124fd578160200160208202803683370190505b50905060008060005b8881101561265d5760008c828151811061252257612522612cf3565b60200260200101511115612655578b818151811061254257612542612cf3565b602002602001015191508188848151811061255f5761255f612cf3565b6020908102919091018101919091526000838152600590915260409020600181015488516001600160a01b03909116908990869081106125a1576125a1612cf3565b6001600160a01b039283166020918202929092010152815488519116908890869081106125d0576125d0612cf3565b60200260200101906001600160a01b031690816001600160a01b0316815250508b828151811061260257612602612cf3565b602002602001015186858151811061261c5761261c612cf3565b6020026020010181815250508185858151811061263b5761263b612cf3565b60209081029190910101528361265081612fa9565b945050505b600101612506565b50885b8015612712578861267081613045565b99506000905084612682600184612cca565b8151811061269257612692612cf3565b6020026020010151905060068a815481106126af576126af612cf3565b9060005260206000200154600682815481106126cd576126cd612cf3565b60009182526020909120015560068054806126ea576126ea612d09565b60019003818190600052602060002001600090559055508061270b90613045565b9050612660565b506000547fd19a3d42ed383465e4058c322d9411aeac76ddb8454d22e139fc99808bd569528888888860405161274b9493929190613096565b60405180910390a25050505050505050505050565b600060405163a9059cbb60e01b6000528360045282602452602060006044600080895af13d15601f3d11600160005114161716915060006060528060405250806127dd5760405163abae3d6d60e01b81526001600160a01b038086166004830152306024830152841660448201526064810183905260840161072f565b50505050565b60408051600180825281830190925260609160208083019080368337019050509050816001600160a01b031663affed0e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612843573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612867919061302c565b8160008151811061287a5761287a612cf3565b602002602001018181525050919050565b60006128988484846128a0565b949350505050565b600080821180156128e45750826000815181106128bf576128bf612cf3565b6020026020010151846000815181106128da576128da612cf3565b6020026020010151115b15610bb357600082846000815181106128ff576128ff612cf3565b60200260200101518660008151811061291a5761291a612cf3565b602002602001015161292c9190612cca565b61293e90670de0b6b3a7640000612f70565b6129489190612f87565b7f0000000000000000000000000000000000000000000000000000000000000000111595945050505050565b508054600082559060005260206000209081019061299291906129e0565b50565b8280548282559060005260206000209081019282156129d0579160200282015b828111156129d05782518255916020019190600101906129b5565b506129dc9291506129e0565b5090565b5b808211156129dc57600081556001016129e1565b6001600160a01b038116811461299257600080fd5b600080600080600060808688031215612a2257600080fd5b8535612a2d816129f5565b94506020860135612a3d816129f5565b935060408601359250606086013567ffffffffffffffff80821115612a6157600080fd5b818801915088601f830112612a7557600080fd5b813581811115612a8457600080fd5b896020828501011115612a9657600080fd5b9699959850939650602001949392505050565b600060208284031215612abb57600080fd5b5035919050565b60008151808452602080850194506020840160005b83811015612af357815187529582019590820190600101612ad7565b509495945050505050565b6020815260006001600160a01b0380845116602084015280602085015116604084015250604083015160c06060840152612b3b60e0840182612ac2565b905060608401516080840152608084015160a084015260a084015160c08401528091505092915050565b602081526000610bb36020830184612ac2565b60a081526000612b8b60a0830188612ac2565b6020838203818501528188518084528284019150828160051b850101838b0160005b83811015612bdb57601f19878403018552612bc9838351612ac2565b94860194925090850190600101612bad565b50508681036040880152612bef818b612ac2565b9450505050508281036060840152612c078186612ac2565b90508281036080840152612c1b8185612ac2565b98975050505050505050565b634e487b7160e01b600052602160045260246000fd5b6020810160038310612c5f57634e487b7160e01b600052602160045260246000fd5b91905290565b60006020808352835180602085015260005b81811015612c9357858101830151858201604001528201612c77565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052601160045260246000fd5b81810381811115611f0d57611f0d612cb4565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b838152606060208201526000612d386060830185612ac2565b9050826040830152949350505050565b80820180821115611f0d57611f0d612cb4565b604051610100810167ffffffffffffffff81118282101715612d7f57612d7f612cdd565b60405290565b80516bffffffffffffffffffffffff81168114612da157600080fd5b919050565b8051612da1816129f5565b805163ffffffff81168114612da157600080fd5b805160068110612da157600080fd5b600082601f830112612de557600080fd5b8151602067ffffffffffffffff80831115612e0257612e02612cdd565b8260051b604051601f19603f83011681018181108482111715612e2757612e27612cdd565b6040529384526020818701810194908101925087851115612e4757600080fd5b6020870191505b84821015612e6e57612e5f82612db1565b83529183019190830190612e4e565b979650505050505050565b600060208284031215612e8b57600080fd5b815167ffffffffffffffff80821115612ea357600080fd5b908301906101008286031215612eb857600080fd5b612ec0612d5b565b612ec983612d85565b8152612ed760208401612da6565b602082015260408301516040820152612ef260608401612db1565b6060820152612f0360808401612db1565b6080820152612f1460a08401612db1565b60a0820152612f2560c08401612dc5565b60c082015260e083015182811115612f3c57600080fd5b612f4887828601612dd4565b60e08301525095945050505050565b8281526040602082015260006128986040830184612ac2565b8082028115828204841417611f0d57611f0d612cb4565b600082612fa457634e487b7160e01b600052601260045260246000fd5b500490565b600060018201612fbb57612fbb612cb4565b5060010190565b838152606060208201526000612fdb6060830185612ac2565b8281036040840152612fed8185612ac2565b9695505050505050565b6000806040838503121561300a57600080fd5b8251613015816129f5565b915061302360208401612d85565b90509250929050565b60006020828403121561303e57600080fd5b5051919050565b60008161305457613054612cb4565b506000190190565b60008151808452602080850194506020840160005b83811015612af35781516001600160a01b031687529582019590820190600101613071565b6080815260006130a96080830187612ac2565b82810360208401526130bb818761305c565b905082810360408401526130cf818661305c565b90508281036060840152612e6e8185612ac256fea26469706673582212201cbb3243bdf2246a74a754c4b24385dc52b256b192f67778a3b3a76648374a5864736f6c63430008170033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/backend/operate/data/contracts/__init__.py b/backend/operate/data/contracts/__init__.py new file mode 100644 index 000000000..4407dec6d --- /dev/null +++ b/backend/operate/data/contracts/__init__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2023 Valory AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ + +"""Contract packages.""" diff --git a/backend/operate/data/contracts/service_staking_token/__init__.py b/backend/operate/data/contracts/service_staking_token/__init__.py new file mode 100644 index 000000000..cf1e8467e --- /dev/null +++ b/backend/operate/data/contracts/service_staking_token/__init__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2023 Valory AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ + +"""This module contains the support resources for the agent registry contract.""" diff --git a/backend/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json b/backend/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json new file mode 100644 index 000000000..27185c342 --- /dev/null +++ b/backend/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json @@ -0,0 +1,1134 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ServiceStakingToken", + "sourceName": "contracts/staking/ServiceStakingToken.sol", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "maxNumServices", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardsPerSecond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minStakingDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "livenessPeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "livenessRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numAgentInstances", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "agentIds", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "configHash", + "type": "bytes32" + } + ], + "internalType": "struct ServiceStakingBase.StakingParams", + "name": "_stakingParams", + "type": "tuple" + }, + { + "internalType": "address", + "name": "_serviceRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "_serviceRegistryTokenUtility", + "type": "address" + }, + { + "internalType": "address", + "name": "_stakingToken", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_proxyHash", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "AgentInstanceRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "AgentInstancesSlotsFilled", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "agentId", + "type": "uint256" + } + ], + "name": "AgentNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "agentId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "AgentNotInService", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "componentId", + "type": "uint256" + } + ], + "name": "ComponentNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "HashExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "IncorrectAgentBondingValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "IncorrectRegistrationDepositValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "provided", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "LowerThan", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "manager", + "type": "address" + } + ], + "name": "ManagerOnly", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxNumServices", + "type": "uint256" + } + ], + "name": "MaxNumServicesReached", + "type": "error" + }, + { + "inputs": [], + "name": "NoRewardsAvailable", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "provided", + "type": "address" + }, + { + "internalType": "address", + "name": "expected", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "OnlyOwnServiceMultisig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "OperatorHasNoInstances", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "provided", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "Overflow", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnerOnly", + "type": "error" + }, + { + "inputs": [], + "name": "Paused", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuard", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "ServiceMustBeInactive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "ServiceNotStaked", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TokenTransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "multisig", + "type": "address" + } + ], + "name": "UnauthorizedMultisig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "provided", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "ValueLowerThan", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "agentId", + "type": "uint256" + } + ], + "name": "WrongAgentId", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numValues1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numValues2", + "type": "uint256" + } + ], + "name": "WrongArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "WrongOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "WrongServiceConfiguration", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "state", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "WrongServiceState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "expected", + "type": "address" + }, + { + "internalType": "address", + "name": "provided", + "type": "address" + } + ], + "name": "WrongStakingToken", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxThreshold", + "type": "uint256" + } + ], + "name": "WrongThreshold", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValue", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "availableRewards", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "numServices", + "type": "uint256" + } + ], + "name": "Checkpoint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "availableRewards", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "multisig", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "nonces", + "type": "uint256[]" + } + ], + "name": "ServiceStaked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "multisig", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "nonces", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tsStart", + "type": "uint256" + } + ], + "name": "ServiceUnstaked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "agentIds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "availableRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "balance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "calculateServiceStakingReward", + "outputs": [ + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkpoint", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[][]", + "name": "", + "type": "uint256[][]" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "configHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getNextRewardCheckpointTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "tsNext", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getServiceIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "serviceIds", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "isServiceStaked", + "outputs": [ + { + "internalType": "bool", + "name": "isStaked", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "livenessPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "livenessRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "mapServiceInfo", + "outputs": [ + { + "internalType": "address", + "name": "multisig", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tsStart", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxNumServices", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minStakingDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numAgentInstances", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proxyHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardsPerSecond", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "serviceRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "serviceRegistryTokenUtility", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "setServiceIds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stakingToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "threshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tsCheckpoint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6102006040523480156200001257600080fd5b506040516200294c3803806200294c8339810160408190526200003591620003bc565b8484828260000151600014806200004e57506020830151155b806200005c57506060830151155b806200006a57506080830151155b8062000078575060a0830151155b156200009757604051637c946ed760e01b815260040160405180910390fd5b600283604001511015620000d357604080840151905163491a2bb160e01b81526004810191909152600260248201526044015b60405180910390fd5b6001600160a01b038216620000fb5760405163d92e233d60e01b815260040160405180910390fd5b82516080908152602084015160a0908152604085015160c052606085015160e09081529185015161010090815290850151610120526001600160a01b038416610180529084015161014052830151610160526000805b8460c00151518110156200023357818560c001518281518110620001795762000179620004c6565b602002602001015111620001c5578460c001518181518110620001a057620001a0620004c6565b6020026020010151604051632ab10b0b60e21b8152600401620000ca91815260200190565b8460c001518181518110620001de57620001de620004c6565b6020908102919091010151600380546001810182556000919091527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0181905591506200022b81620004dc565b905062000151565b50816200025357604051637c946ed760e01b815260040160405180910390fd5b506101a0525050426002556001600160a01b03821615806200027c57506001600160a01b038316155b156200029b5760405163d92e233d60e01b815260040160405180910390fd5b506001600160a01b039081166101e052166101c05250620005049050565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b0381118282101715620002f557620002f5620002b9565b60405290565b600082601f8301126200030d57600080fd5b815160206001600160401b03808311156200032c576200032c620002b9565b8260051b604051601f19603f83011681018181108482111715620003545762000354620002b9565b6040529384528581018301938381019250878511156200037357600080fd5b83870191505b84821015620003945781518352918301919083019062000379565b979650505050505050565b80516001600160a01b0381168114620003b757600080fd5b919050565b600080600080600060a08688031215620003d557600080fd5b85516001600160401b0380821115620003ed57600080fd5b90870190610120828a0312156200040357600080fd5b6200040d620002cf565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c0830151828111156200045657600080fd5b620004648b828601620002fb565b60c08301525060e08381015190820152610100928301519281019290925250945062000493602087016200039f565b9350620004a3604087016200039f565b9250620004b3606087016200039f565b9150608086015190509295509295909350565b634e487b7160e01b600052603260045260246000fd5b600060018201620004fd57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161231c620006306000396000818161036401528181611030015281816114a50152818161192e015261197201526000818161025801526118b401526000818161039e0152610d3b015260008181610486015281816107cc01528181610af70152610f400152600081816104e201528181610bbf0152610bee0152600081816102b501528181610c350152610c690152600081816103160152610b7d01526000818161033d0152611cb10152600081816102dc015281816114580152611529015260008181610509015281816119a90152611a0001526000818161053001526117da01526000818161022301528181610a7e0152610ab2015261231c6000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c8063a694fc3a116100f9578063e1f1176d11610097578063eb338c9611610071578063eb338c9614610552578063f189e85a14610565578063f4dce7141461057a578063ffa1ad741461058257600080fd5b8063e1f1176d146104dd578063e77cdcc914610504578063eacdaabc1461052b57600080fd5b8063b6b55f25116100d3578063b6b55f2514610454578063c2c4c5c114610467578063cbcf252a14610481578063cd25fe38146104a857600080fd5b8063a694fc3a146103c9578063a74466ad146103dc578063b69ef8a81461044b57600080fd5b806356e760581161016657806372f702f31161014057806372f702f31461035f57806378e0613614610386578063809cee2f14610399578063879d9090146103c057600080fd5b806356e76058146102fe5780635829c5ec14610311578063592cf3fb1461033857600080fd5b80632e17de78116101a25780632e17de78146102925780633e732997146102a757806342cde4e8146102b057806352c824f5146102d757600080fd5b8063150b7a02146101c957806316a751721461021e5780632871405114610253575b600080fd5b6101e86101d7366004611d73565b630a85bd0160e11b95945050505050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020015b60405180910390f35b6102457f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610215565b61027a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610215565b6102a56102a0366004611e12565b6105b3565b005b61024560025481565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b61024561030c366004611e12565b610896565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b61027a7f000000000000000000000000000000000000000000000000000000000000000081565b610245610394366004611e12565b6108b7565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b61024560015481565b6102a56103d7366004611e12565b610a56565b6104206103ea366004611e12565b600460208190526000918252604090912080546001820154600383015492909301546001600160a01b0391821693909116919084565b604080516001600160a01b039586168152949093166020850152918301526060820152608001610215565b61024560005481565b6102a5610462366004611e12565b610ffd565b61046f61109f565b60405161021596959493929190611e66565b61027a7f000000000000000000000000000000000000000000000000000000000000000081565b6104cd6104b6366004611e12565b600090815260046020526040902060030154151590565b6040519015158152602001610215565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b610245610560366004611e12565b61139e565b61056d6113ae565b6040516102159190611f3e565b610245611454565b6105a6604051806040016040528060058152602001640302e312e360dc1b81525081565b6040516102159190611f51565b600081815260046020526040902060018101546001600160a01b0316331461060a57600181015460405163521eb56d60e11b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b60008061061561109f565b95505050505091508061062d5761062a6113ae565b91505b60005b825181101561066a578483828151811061064c5761064c611f9f565b6020026020010151031561066a5761066381611fcb565b9050610630565b600484015460028501805460408051602080840282018101909252828152600093909290918301828280156106be57602002820191906000526020600020905b8154815260200190600101908083116106aa575b5050506003890154895460008c8152600460205260408120805473ffffffffffffffffffffffffffffffffffffffff199081168255600182018054909116905595965091946001600160a01b039091169350915061071f6002830182611cdd565b506000600382018190556004909101556005805461073f90600190611fe4565b8154811061074f5761074f611f9f565b90600052602060002001546005868154811061076d5761076d611f9f565b600091825260209091200155600580548061078a5761078a611ff7565b600082815260208120820160001990810191909155019055604051632142170760e11b8152306004820152336024820152604481018a90526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90606401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b50505050600084111561083b5761083b8185611489565b806001600160a01b0316336001600160a01b03168a7f246ee6115bfd84e00097b16569c2ff2f822026bb9595a82cd2c1e69d4b6ea50c8688876040516108839392919061200d565b60405180910390a4505050505050505050565b600381815481106108a657600080fd5b600091825260209091200154905081565b6000818152600460209081526040808320815160a08101835281546001600160a01b039081168252600183015416818501526002820180548451818702810187018652818152879693958601939092919083018282801561093757602002820191906000526020600020905b815481526020019060010190808311610923575b505050505081526020016003820154815260200160048201548152505090508060800151915080606001516000036109855760405163e0606b6360e01b815260048101849052602401610601565b6000806000806000610995611512565b50509450945094509450945060005b84811015610a4a57888382815181106109bf576109bf611f9f565b602002602001015103610a3a5785841115610a155783868383815181106109e8576109e8611f9f565b60200260200101516109fa9190612032565b610a049190612049565b610a0e908961206b565b9750610a4a565b818181518110610a2757610a27611f9f565b602002602001015188610a0e919061206b565b610a4381611fcb565b90506109a4565b50505050505050919050565b600154600003610a795760405163afb0be3360e01b815260040160405180910390fd5b6005547f00000000000000000000000000000000000000000000000000000000000000008103610ade5760405163fd20861560e01b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610601565b60405163ef0e239b60e01b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef0e239b90602401600060405180830381865afa158015610b46573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b6e91908101906121a4565b9050806080015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014610bbd57604051637ad404bf60e11b815260048101849052602401610601565b7f000000000000000000000000000000000000000000000000000000000000000015801590610c10575080604001517f000000000000000000000000000000000000000000000000000000000000000014155b15610c3157604051637ad404bf60e11b815260048101849052602401610601565b60007f0000000000000000000000000000000000000000000000000000000000000000118015610c8b5750806060015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014155b15610cac57604051637ad404bf60e11b815260048101849052602401610601565b60048160c001516005811115610cc457610cc4612282565b14610d03578060c001516005811115610cdf57610cdf612282565b604051633c053f9d60e21b8152600481019190915260248101849052604401610601565b600081602001516001600160a01b0316803b806020016040519081016040528181526000908060200190933c805190602001209050807f000000000000000000000000000000000000000000000000000000000000000014610d8857602082015160405162a2307960e51b81526001600160a01b039091166004820152602401610601565b6003548015610e595760e083015151818114610dba57604051637ad404bf60e11b815260048101879052602401610601565b60005b81811015610e56578460e001518181518110610ddb57610ddb611f9f565b602002602001015163ffffffff1660038281548110610dfc57610dfc611f9f565b906000526020600020015414610e465760038181548110610e1f57610e1f611f9f565b9060005260206000200154604051632ab10b0b60e21b815260040161060191815260200190565b610e4f81611fcb565b9050610dbd565b50505b610e758584600001516bffffffffffffffffffffffff16611891565b600085815260046020908152604082209085015181546001600160a01b03821673ffffffffffffffffffffffffffffffffffffffff1991821617835560018301805490911633179055909190610eca90611a32565b8051909150610ee29060028401906020840190611cfe565b50426003830155600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db001879055604051632142170760e11b8152336004820152306024820152604481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342842e0e90606401600060405180830381600087803b158015610f8c57600080fd5b505af1158015610fa0573d6000803e3d6000fd5b5050505084602001516001600160a01b0316336001600160a01b0316887f5d43ac9b1b213902df90d405b0006308578486b6c62182c5df202ed572c844e484604051610fec9190611f3e565b60405180910390a450505050505050565b60008160005461100d919061206b565b905060008260015461101f919061206b565b6000839055600181905590506110577f0000000000000000000000000000000000000000000000000000000000000000333086611a43565b604080518481526020810184905290810182905233907f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e9060600160405180910390a2505050565b60608060006060806000806000806000806000806110bb611512565b965096509650965096509650965060008611156112bf5760008786111561122e5760008060015b8981101561118057888b8883815181106110fe576110fe611f9f565b60200260200101516111109190612032565b61111a9190612049565b9250611126838361206b565b915087818151811061113a5761113a611f9f565b602002602001015193508260046000868152602001908152602001600020600401600082825461116a919061206b565b90915550611179905081611fcb565b90506110e2565b50878a8760008151811061119657611196611f9f565b60200260200101516111a89190612032565b6111b29190612049565b91506111be828261206b565b9050866000815181106111d3576111d3611f9f565b60200260200101519250808a11156111fc576111ef818b611fe4565b6111f9908361206b565b91505b6000838152600460208190526040822001805484929061121d90849061206b565b9091555060009a506112b892505050565b60005b878110156112aa5785818151811061124b5761124b611f9f565b6020026020010151915084818151811061126757611267611f9f565b6020026020010151600460008481526020019081526020016000206004016000828254611294919061206b565b909155506112a3905081611fcb565b9050611231565b506112b58689611fe4565b97505b5060018790555b8051156113895760005b82518110156113465760008382815181106112e6576112e6611f9f565b6020026020010151905082828151811061130257611302611f9f565b6020026020010151600460008381526020019081526020016000206002019080519060200190611333929190611cfe565b50508061133f90611fcb565b90506112c9565b50426002556040805188815260208101889052600199507f21d81d5d656869e8ce3ba8d65526a2f0dbbcd3d36f5f9999eb7c84360e45eced910160405180910390a15b909c909b509399509097509550929350915050565b600581815481106108a657600080fd5b6005546060908067ffffffffffffffff8111156113cd576113cd61207e565b6040519080825280602002602001820160405280156113f6578160200160208202803683370190505b50915060005b8181101561144f576005818154811061141757611417611f9f565b906000526020600020015483828151811061143457611434611f9f565b602090810291909101015261144881611fcb565b90506113fc565b505090565b60007f0000000000000000000000000000000000000000000000000000000000000000600254611484919061206b565b905090565b8060008082825461149a9190611fe4565b909155506114cb90507f00000000000000000000000000000000000000000000000000000000000000008383611acd565b816001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243648260405161150691815260200190565b60405180910390a25050565b6002546001549060009081906060908190819081907f00000000000000000000000000000000000000000000000000000000000000006115528242611fe4565b101580156115605750600088115b15611887576005548067ffffffffffffffff8111156115815761158161207e565b6040519080825280602002602001820160405280156115aa578160200160208202803683370190505b5093508067ffffffffffffffff8111156115c6576115c661207e565b6040519080825280602002602001820160405280156115ef578160200160208202803683370190505b5095508067ffffffffffffffff81111561160b5761160b61207e565b604051908082528060200260200182016040528015611634578160200160208202803683370190505b5094508067ffffffffffffffff8111156116505761165061207e565b60405190808252806020026020018201604052801561168357816020015b606081526020019060019003908161166e5790505b50925060005b8181101561188457600581815481106116a4576116a4611f9f565b90600052602060002001548582815181106116c1576116c1611f9f565b6020026020010181815250506000600460008784815181106116e5576116e5611f9f565b60209081029190910181015182528101919091526040016000208054909150611716906001600160a01b0316611a32565b85838151811061172857611728611f9f565b60209081029190910101526003810154849081811115611746578091505b6117508242611fe4565b905060006117ca88868151811061176957611769611f9f565b6020026020010151856002018054806020026020016040519081016040528092919081815260200182805480156117bf57602002820191906000526020600020905b8154815260200190600101908083116117ab575b505050505084611b4a565b9050801561186f5760006117fe837f0000000000000000000000000000000000000000000000000000000000000000612032565b905061180a818e61206b565b9c50808b8f8151811061181f5761181f611f9f565b60200260200101818152505089868151811061183d5761183d611f9f565b60200260200101518c8f8151811061185757611857611f9f565b602090810291909101015261186b8e611fcb565b9d50505b505050508061187d90611fcb565b9050611689565b50505b5090919293949596565b604051633cebfa4f60e01b81526004810183905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633cebfa4f906024016040805180830381865afa1580156118fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191e9190612298565b91509150816001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146119a757604051630b80380d60e31b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015283166024820152604401610601565b7f0000000000000000000000000000000000000000000000000000000000000000816bffffffffffffffffffffffff161015611a2c57604051632b30b24760e21b81526bffffffffffffffffffffffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006024820152604401610601565b50505050565b6060611a3d82611b5f565b92915050565b60006040516323b872dd60e01b6000528460045283602452826044526020600060646000808a5af13d15601f3d1160016000511416171691506000606052806040525080611ac65760405163abae3d6d60e01b81526001600160a01b03808716600483015280861660248301528416604482015260648101839052608401610601565b5050505050565b600060405163a9059cbb60e01b6000528360045282602452602060006044600080895af13d15601f3d1160016000511416171691506000606052806040525080611a2c5760405163abae3d6d60e01b81526001600160a01b0380861660048301523060248301528416604482015260648101839052608401610601565b6000611b57848484611c07565b949350505050565b60408051600180825281830190925260609160208083019080368337019050509050816001600160a01b031663affed0e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be391906122cd565b81600081518110611bf657611bf6611f9f565b602002602001018181525050919050565b60008082118015611c4b575082600081518110611c2657611c26611f9f565b602002602001015184600081518110611c4157611c41611f9f565b6020026020010151115b15611cd65760008284600081518110611c6657611c66611f9f565b602002602001015186600081518110611c8157611c81611f9f565b6020026020010151611c939190611fe4565b611ca590670de0b6b3a7640000612032565b611caf9190612049565b7f000000000000000000000000000000000000000000000000000000000000000011159150505b9392505050565b5080546000825590600052602060002090810190611cfb9190611d49565b50565b828054828255906000526020600020908101928215611d39579160200282015b82811115611d39578251825591602001919060010190611d1e565b50611d45929150611d49565b5090565b5b80821115611d455760008155600101611d4a565b6001600160a01b0381168114611cfb57600080fd5b600080600080600060808688031215611d8b57600080fd5b8535611d9681611d5e565b94506020860135611da681611d5e565b935060408601359250606086013567ffffffffffffffff80821115611dca57600080fd5b818801915088601f830112611dde57600080fd5b813581811115611ded57600080fd5b896020828501011115611dff57600080fd5b9699959850939650602001949392505050565b600060208284031215611e2457600080fd5b5035919050565b600081518084526020808501945080840160005b83811015611e5b57815187529582019590820190600101611e3f565b509495945050505050565b60c081526000611e7960c0830189611e2b565b6020838203818501528189518084528284019150828160051b850101838c016000805b84811015611eef57878403601f19018652825180518086529088019088860190845b81811015611eda5783518352928a0192918a0191600101611ebe565b50509688019694505091860191600101611e9c565b5050508a60408801528681036060880152611f0a818b611e2b565b9450505050508281036080840152611f228186611e2b565b915050611f3360a083018415159052565b979650505050505050565b602081526000611cd66020830184611e2b565b600060208083528351808285015260005b81811015611f7e57858101830151858201604001528201611f62565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611fdd57611fdd611fb5565b5060010190565b81810381811115611a3d57611a3d611fb5565b634e487b7160e01b600052603160045260246000fd5b6060815260006120206060830186611e2b565b60208301949094525060400152919050565b8082028115828204841417611a3d57611a3d611fb5565b60008261206657634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115611a3d57611a3d611fb5565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156120b8576120b861207e565b60405290565b80516bffffffffffffffffffffffff811681146120da57600080fd5b919050565b80516120da81611d5e565b805163ffffffff811681146120da57600080fd5b8051600681106120da57600080fd5b600082601f83011261211e57600080fd5b8151602067ffffffffffffffff8083111561213b5761213b61207e565b8260051b604051601f19603f830116810181811084821117156121605761216061207e565b60405293845285810183019383810192508785111561217e57600080fd5b83870191505b84821015611f3357612195826120ea565b83529183019190830190612184565b6000602082840312156121b657600080fd5b815167ffffffffffffffff808211156121ce57600080fd5b9083019061010082860312156121e357600080fd5b6121eb612094565b6121f4836120be565b8152612202602084016120df565b60208201526040830151604082015261221d606084016120ea565b606082015261222e608084016120ea565b608082015261223f60a084016120ea565b60a082015261225060c084016120fe565b60c082015260e08301518281111561226757600080fd5b6122738782860161210d565b60e08301525095945050505050565b634e487b7160e01b600052602160045260246000fd5b600080604083850312156122ab57600080fd5b82516122b681611d5e565b91506122c4602084016120be565b90509250929050565b6000602082840312156122df57600080fd5b505191905056fea2646970667358221220892b3547cd047374259e7ce0b4c8c70e47fe8f83349b516cd97fa732cc75de9164736f6c63430008150033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101c45760003560e01c8063a694fc3a116100f9578063e1f1176d11610097578063eb338c9611610071578063eb338c9614610552578063f189e85a14610565578063f4dce7141461057a578063ffa1ad741461058257600080fd5b8063e1f1176d146104dd578063e77cdcc914610504578063eacdaabc1461052b57600080fd5b8063b6b55f25116100d3578063b6b55f2514610454578063c2c4c5c114610467578063cbcf252a14610481578063cd25fe38146104a857600080fd5b8063a694fc3a146103c9578063a74466ad146103dc578063b69ef8a81461044b57600080fd5b806356e760581161016657806372f702f31161014057806372f702f31461035f57806378e0613614610386578063809cee2f14610399578063879d9090146103c057600080fd5b806356e76058146102fe5780635829c5ec14610311578063592cf3fb1461033857600080fd5b80632e17de78116101a25780632e17de78146102925780633e732997146102a757806342cde4e8146102b057806352c824f5146102d757600080fd5b8063150b7a02146101c957806316a751721461021e5780632871405114610253575b600080fd5b6101e86101d7366004611d73565b630a85bd0160e11b95945050505050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020015b60405180910390f35b6102457f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610215565b61027a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610215565b6102a56102a0366004611e12565b6105b3565b005b61024560025481565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b61024561030c366004611e12565b610896565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b61027a7f000000000000000000000000000000000000000000000000000000000000000081565b610245610394366004611e12565b6108b7565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b61024560015481565b6102a56103d7366004611e12565b610a56565b6104206103ea366004611e12565b600460208190526000918252604090912080546001820154600383015492909301546001600160a01b0391821693909116919084565b604080516001600160a01b039586168152949093166020850152918301526060820152608001610215565b61024560005481565b6102a5610462366004611e12565b610ffd565b61046f61109f565b60405161021596959493929190611e66565b61027a7f000000000000000000000000000000000000000000000000000000000000000081565b6104cd6104b6366004611e12565b600090815260046020526040902060030154151590565b6040519015158152602001610215565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b6102457f000000000000000000000000000000000000000000000000000000000000000081565b610245610560366004611e12565b61139e565b61056d6113ae565b6040516102159190611f3e565b610245611454565b6105a6604051806040016040528060058152602001640302e312e360dc1b81525081565b6040516102159190611f51565b600081815260046020526040902060018101546001600160a01b0316331461060a57600181015460405163521eb56d60e11b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b60008061061561109f565b95505050505091508061062d5761062a6113ae565b91505b60005b825181101561066a578483828151811061064c5761064c611f9f565b6020026020010151031561066a5761066381611fcb565b9050610630565b600484015460028501805460408051602080840282018101909252828152600093909290918301828280156106be57602002820191906000526020600020905b8154815260200190600101908083116106aa575b5050506003890154895460008c8152600460205260408120805473ffffffffffffffffffffffffffffffffffffffff199081168255600182018054909116905595965091946001600160a01b039091169350915061071f6002830182611cdd565b506000600382018190556004909101556005805461073f90600190611fe4565b8154811061074f5761074f611f9f565b90600052602060002001546005868154811061076d5761076d611f9f565b600091825260209091200155600580548061078a5761078a611ff7565b600082815260208120820160001990810191909155019055604051632142170760e11b8152306004820152336024820152604481018a90526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342842e0e90606401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b50505050600084111561083b5761083b8185611489565b806001600160a01b0316336001600160a01b03168a7f246ee6115bfd84e00097b16569c2ff2f822026bb9595a82cd2c1e69d4b6ea50c8688876040516108839392919061200d565b60405180910390a4505050505050505050565b600381815481106108a657600080fd5b600091825260209091200154905081565b6000818152600460209081526040808320815160a08101835281546001600160a01b039081168252600183015416818501526002820180548451818702810187018652818152879693958601939092919083018282801561093757602002820191906000526020600020905b815481526020019060010190808311610923575b505050505081526020016003820154815260200160048201548152505090508060800151915080606001516000036109855760405163e0606b6360e01b815260048101849052602401610601565b6000806000806000610995611512565b50509450945094509450945060005b84811015610a4a57888382815181106109bf576109bf611f9f565b602002602001015103610a3a5785841115610a155783868383815181106109e8576109e8611f9f565b60200260200101516109fa9190612032565b610a049190612049565b610a0e908961206b565b9750610a4a565b818181518110610a2757610a27611f9f565b602002602001015188610a0e919061206b565b610a4381611fcb565b90506109a4565b50505050505050919050565b600154600003610a795760405163afb0be3360e01b815260040160405180910390fd5b6005547f00000000000000000000000000000000000000000000000000000000000000008103610ade5760405163fd20861560e01b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610601565b60405163ef0e239b60e01b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef0e239b90602401600060405180830381865afa158015610b46573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b6e91908101906121a4565b9050806080015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014610bbd57604051637ad404bf60e11b815260048101849052602401610601565b7f000000000000000000000000000000000000000000000000000000000000000015801590610c10575080604001517f000000000000000000000000000000000000000000000000000000000000000014155b15610c3157604051637ad404bf60e11b815260048101849052602401610601565b60007f0000000000000000000000000000000000000000000000000000000000000000118015610c8b5750806060015163ffffffff167f000000000000000000000000000000000000000000000000000000000000000014155b15610cac57604051637ad404bf60e11b815260048101849052602401610601565b60048160c001516005811115610cc457610cc4612282565b14610d03578060c001516005811115610cdf57610cdf612282565b604051633c053f9d60e21b8152600481019190915260248101849052604401610601565b600081602001516001600160a01b0316803b806020016040519081016040528181526000908060200190933c805190602001209050807f000000000000000000000000000000000000000000000000000000000000000014610d8857602082015160405162a2307960e51b81526001600160a01b039091166004820152602401610601565b6003548015610e595760e083015151818114610dba57604051637ad404bf60e11b815260048101879052602401610601565b60005b81811015610e56578460e001518181518110610ddb57610ddb611f9f565b602002602001015163ffffffff1660038281548110610dfc57610dfc611f9f565b906000526020600020015414610e465760038181548110610e1f57610e1f611f9f565b9060005260206000200154604051632ab10b0b60e21b815260040161060191815260200190565b610e4f81611fcb565b9050610dbd565b50505b610e758584600001516bffffffffffffffffffffffff16611891565b600085815260046020908152604082209085015181546001600160a01b03821673ffffffffffffffffffffffffffffffffffffffff1991821617835560018301805490911633179055909190610eca90611a32565b8051909150610ee29060028401906020840190611cfe565b50426003830155600580546001810182556000919091527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db001879055604051632142170760e11b8152336004820152306024820152604481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906342842e0e90606401600060405180830381600087803b158015610f8c57600080fd5b505af1158015610fa0573d6000803e3d6000fd5b5050505084602001516001600160a01b0316336001600160a01b0316887f5d43ac9b1b213902df90d405b0006308578486b6c62182c5df202ed572c844e484604051610fec9190611f3e565b60405180910390a450505050505050565b60008160005461100d919061206b565b905060008260015461101f919061206b565b6000839055600181905590506110577f0000000000000000000000000000000000000000000000000000000000000000333086611a43565b604080518481526020810184905290810182905233907f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e9060600160405180910390a2505050565b60608060006060806000806000806000806000806110bb611512565b965096509650965096509650965060008611156112bf5760008786111561122e5760008060015b8981101561118057888b8883815181106110fe576110fe611f9f565b60200260200101516111109190612032565b61111a9190612049565b9250611126838361206b565b915087818151811061113a5761113a611f9f565b602002602001015193508260046000868152602001908152602001600020600401600082825461116a919061206b565b90915550611179905081611fcb565b90506110e2565b50878a8760008151811061119657611196611f9f565b60200260200101516111a89190612032565b6111b29190612049565b91506111be828261206b565b9050866000815181106111d3576111d3611f9f565b60200260200101519250808a11156111fc576111ef818b611fe4565b6111f9908361206b565b91505b6000838152600460208190526040822001805484929061121d90849061206b565b9091555060009a506112b892505050565b60005b878110156112aa5785818151811061124b5761124b611f9f565b6020026020010151915084818151811061126757611267611f9f565b6020026020010151600460008481526020019081526020016000206004016000828254611294919061206b565b909155506112a3905081611fcb565b9050611231565b506112b58689611fe4565b97505b5060018790555b8051156113895760005b82518110156113465760008382815181106112e6576112e6611f9f565b6020026020010151905082828151811061130257611302611f9f565b6020026020010151600460008381526020019081526020016000206002019080519060200190611333929190611cfe565b50508061133f90611fcb565b90506112c9565b50426002556040805188815260208101889052600199507f21d81d5d656869e8ce3ba8d65526a2f0dbbcd3d36f5f9999eb7c84360e45eced910160405180910390a15b909c909b509399509097509550929350915050565b600581815481106108a657600080fd5b6005546060908067ffffffffffffffff8111156113cd576113cd61207e565b6040519080825280602002602001820160405280156113f6578160200160208202803683370190505b50915060005b8181101561144f576005818154811061141757611417611f9f565b906000526020600020015483828151811061143457611434611f9f565b602090810291909101015261144881611fcb565b90506113fc565b505090565b60007f0000000000000000000000000000000000000000000000000000000000000000600254611484919061206b565b905090565b8060008082825461149a9190611fe4565b909155506114cb90507f00000000000000000000000000000000000000000000000000000000000000008383611acd565b816001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243648260405161150691815260200190565b60405180910390a25050565b6002546001549060009081906060908190819081907f00000000000000000000000000000000000000000000000000000000000000006115528242611fe4565b101580156115605750600088115b15611887576005548067ffffffffffffffff8111156115815761158161207e565b6040519080825280602002602001820160405280156115aa578160200160208202803683370190505b5093508067ffffffffffffffff8111156115c6576115c661207e565b6040519080825280602002602001820160405280156115ef578160200160208202803683370190505b5095508067ffffffffffffffff81111561160b5761160b61207e565b604051908082528060200260200182016040528015611634578160200160208202803683370190505b5094508067ffffffffffffffff8111156116505761165061207e565b60405190808252806020026020018201604052801561168357816020015b606081526020019060019003908161166e5790505b50925060005b8181101561188457600581815481106116a4576116a4611f9f565b90600052602060002001548582815181106116c1576116c1611f9f565b6020026020010181815250506000600460008784815181106116e5576116e5611f9f565b60209081029190910181015182528101919091526040016000208054909150611716906001600160a01b0316611a32565b85838151811061172857611728611f9f565b60209081029190910101526003810154849081811115611746578091505b6117508242611fe4565b905060006117ca88868151811061176957611769611f9f565b6020026020010151856002018054806020026020016040519081016040528092919081815260200182805480156117bf57602002820191906000526020600020905b8154815260200190600101908083116117ab575b505050505084611b4a565b9050801561186f5760006117fe837f0000000000000000000000000000000000000000000000000000000000000000612032565b905061180a818e61206b565b9c50808b8f8151811061181f5761181f611f9f565b60200260200101818152505089868151811061183d5761183d611f9f565b60200260200101518c8f8151811061185757611857611f9f565b602090810291909101015261186b8e611fcb565b9d50505b505050508061187d90611fcb565b9050611689565b50505b5090919293949596565b604051633cebfa4f60e01b81526004810183905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633cebfa4f906024016040805180830381865afa1580156118fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191e9190612298565b91509150816001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146119a757604051630b80380d60e31b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015283166024820152604401610601565b7f0000000000000000000000000000000000000000000000000000000000000000816bffffffffffffffffffffffff161015611a2c57604051632b30b24760e21b81526bffffffffffffffffffffffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006024820152604401610601565b50505050565b6060611a3d82611b5f565b92915050565b60006040516323b872dd60e01b6000528460045283602452826044526020600060646000808a5af13d15601f3d1160016000511416171691506000606052806040525080611ac65760405163abae3d6d60e01b81526001600160a01b03808716600483015280861660248301528416604482015260648101839052608401610601565b5050505050565b600060405163a9059cbb60e01b6000528360045282602452602060006044600080895af13d15601f3d1160016000511416171691506000606052806040525080611a2c5760405163abae3d6d60e01b81526001600160a01b0380861660048301523060248301528416604482015260648101839052608401610601565b6000611b57848484611c07565b949350505050565b60408051600180825281830190925260609160208083019080368337019050509050816001600160a01b031663affed0e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be391906122cd565b81600081518110611bf657611bf6611f9f565b602002602001018181525050919050565b60008082118015611c4b575082600081518110611c2657611c26611f9f565b602002602001015184600081518110611c4157611c41611f9f565b6020026020010151115b15611cd65760008284600081518110611c6657611c66611f9f565b602002602001015186600081518110611c8157611c81611f9f565b6020026020010151611c939190611fe4565b611ca590670de0b6b3a7640000612032565b611caf9190612049565b7f000000000000000000000000000000000000000000000000000000000000000011159150505b9392505050565b5080546000825590600052602060002090810190611cfb9190611d49565b50565b828054828255906000526020600020908101928215611d39579160200282015b82811115611d39578251825591602001919060010190611d1e565b50611d45929150611d49565b5090565b5b80821115611d455760008155600101611d4a565b6001600160a01b0381168114611cfb57600080fd5b600080600080600060808688031215611d8b57600080fd5b8535611d9681611d5e565b94506020860135611da681611d5e565b935060408601359250606086013567ffffffffffffffff80821115611dca57600080fd5b818801915088601f830112611dde57600080fd5b813581811115611ded57600080fd5b896020828501011115611dff57600080fd5b9699959850939650602001949392505050565b600060208284031215611e2457600080fd5b5035919050565b600081518084526020808501945080840160005b83811015611e5b57815187529582019590820190600101611e3f565b509495945050505050565b60c081526000611e7960c0830189611e2b565b6020838203818501528189518084528284019150828160051b850101838c016000805b84811015611eef57878403601f19018652825180518086529088019088860190845b81811015611eda5783518352928a0192918a0191600101611ebe565b50509688019694505091860191600101611e9c565b5050508a60408801528681036060880152611f0a818b611e2b565b9450505050508281036080840152611f228186611e2b565b915050611f3360a083018415159052565b979650505050505050565b602081526000611cd66020830184611e2b565b600060208083528351808285015260005b81811015611f7e57858101830151858201604001528201611f62565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611fdd57611fdd611fb5565b5060010190565b81810381811115611a3d57611a3d611fb5565b634e487b7160e01b600052603160045260246000fd5b6060815260006120206060830186611e2b565b60208301949094525060400152919050565b8082028115828204841417611a3d57611a3d611fb5565b60008261206657634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115611a3d57611a3d611fb5565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156120b8576120b861207e565b60405290565b80516bffffffffffffffffffffffff811681146120da57600080fd5b919050565b80516120da81611d5e565b805163ffffffff811681146120da57600080fd5b8051600681106120da57600080fd5b600082601f83011261211e57600080fd5b8151602067ffffffffffffffff8083111561213b5761213b61207e565b8260051b604051601f19603f830116810181811084821117156121605761216061207e565b60405293845285810183019383810192508785111561217e57600080fd5b83870191505b84821015611f3357612195826120ea565b83529183019190830190612184565b6000602082840312156121b657600080fd5b815167ffffffffffffffff808211156121ce57600080fd5b9083019061010082860312156121e357600080fd5b6121eb612094565b6121f4836120be565b8152612202602084016120df565b60208201526040830151604082015261221d606084016120ea565b606082015261222e608084016120ea565b608082015261223f60a084016120ea565b60a082015261225060c084016120fe565b60c082015260e08301518281111561226757600080fd5b6122738782860161210d565b60e08301525095945050505050565b634e487b7160e01b600052602160045260246000fd5b600080604083850312156122ab57600080fd5b82516122b681611d5e565b91506122c4602084016120be565b90509250929050565b6000602082840312156122df57600080fd5b505191905056fea2646970667358221220892b3547cd047374259e7ce0b4c8c70e47fe8f83349b516cd97fa732cc75de9164736f6c63430008150033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/backend/operate/data/contracts/service_staking_token/contract.py b/backend/operate/data/contracts/service_staking_token/contract.py new file mode 100644 index 000000000..e0e91a0b2 --- /dev/null +++ b/backend/operate/data/contracts/service_staking_token/contract.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2023 Valory AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ + +"""This module contains the class to connect to the `ServiceStakingTokenMechUsage` contract.""" + +from aea.common import JSONLike +from aea.configurations.base import PublicId +from aea.contracts.base import Contract +from aea.crypto.base import LedgerApi + + +class ServiceStakingTokenContract(Contract): + """The Service Staking contract.""" + + contract_id = PublicId.from_str("valory/service_staking_token:0.1.0") + + @classmethod + def is_service_staked( + cls, + ledger_api: LedgerApi, + contract_address: str, + service_id: int, + ) -> 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) + + @classmethod + def build_stake_tx( + cls, + ledger_api: LedgerApi, + contract_address: str, + service_id: int, + ) -> JSONLike: + """Build stake tx.""" + contract_instance = cls.get_instance(ledger_api, contract_address) + data = contract_instance.encodeABI("stake", args=[service_id]) + return dict(data=bytes.fromhex(data[2:])) + + @classmethod + def build_checkpoint_tx( + cls, + ledger_api: LedgerApi, + contract_address: str, + ) -> JSONLike: + """Build checkpoint tx.""" + contract_instance = cls.get_instance(ledger_api, contract_address) + data = contract_instance.encodeABI("checkpoint") + return dict(data=bytes.fromhex(data[2:])) + + @classmethod + def build_unstake_tx( + cls, + ledger_api: LedgerApi, + contract_address: str, + service_id: int, + ) -> JSONLike: + """Build unstake tx.""" + contract_instance = cls.get_instance(ledger_api, contract_address) + data = contract_instance.encodeABI("unstake", args=[service_id]) + return dict(data=bytes.fromhex(data[2:])) + + @classmethod + def available_rewards( + cls, + ledger_api: LedgerApi, + contract_address: str, + ) -> JSONLike: + """Get the available rewards.""" + contract_instance = cls.get_instance(ledger_api, contract_address) + res = contract_instance.functions.availableRewards().call() + return dict(data=res) + + @classmethod + def get_staking_rewards( + cls, + ledger_api: LedgerApi, + contract_address: str, + service_id: int, + ) -> JSONLike: + """Get the service's staking rewards.""" + contract = cls.get_instance(ledger_api, contract_address) + reward = contract.functions.calculateServiceStakingReward(service_id).call() + return dict(data=reward) + + @classmethod + def get_next_checkpoint_ts( + cls, + ledger_api: LedgerApi, + contract_address: str, + ) -> JSONLike: + """Get the next checkpoint's timestamp.""" + contract = cls.get_instance(ledger_api, contract_address) + ts = contract.functions.getNextRewardCheckpointTimestamp().call() + return dict(data=ts) + + @classmethod + def get_liveness_period( + cls, + ledger_api: LedgerApi, + contract_address: str, + ) -> JSONLike: + """Retrieve the liveness period.""" + contract = cls.get_instance(ledger_api, contract_address) + liveness_period = contract.functions.livenessPeriod().call() + return dict(data=liveness_period) + + @classmethod + def get_service_info( + cls, + ledger_api: LedgerApi, + contract_address: str, + service_id: int, + ) -> JSONLike: + """Retrieve the service info for a service.""" + contract = cls.get_instance(ledger_api, contract_address) + info = contract.functions.mapServiceInfo(service_id).call() + return dict(data=info) diff --git a/backend/operate/data/contracts/service_staking_token/contract.yaml b/backend/operate/data/contracts/service_staking_token/contract.yaml new file mode 100644 index 000000000..7a9c886a3 --- /dev/null +++ b/backend/operate/data/contracts/service_staking_token/contract.yaml @@ -0,0 +1,23 @@ +name: service_staking_token +author: valory +version: 0.1.0 +type: contract +description: Service staking token contract +license: Apache-2.0 +aea_version: '>=1.0.0, <2.0.0' +fingerprint: + __init__.py: bafybeid3wfzglolebuo6jrrsopswzu4lk77bm76mvw3euizlsjtnt3wmgu + build/ServiceStakingToken.json: bafybeie2xbccvzmjuptqfqumctv6gtyyeoxe7fkx3t7fgbto7wbdugbqxm + contract.py: bafybeihhdg5mvd3jwc7q445ntdahaiyjpt2ne6ipkiaymycbrw5iwzuble +fingerprint_ignore_patterns: [] +contracts: [] +class_name: ServiceStakingTokenContract +contract_interface_paths: + ethereum: build/ServiceStakingToken.json +dependencies: + open-aea-ledger-ethereum: + version: ==1.42.0 + open-aea-test-autonomy: + version: ==0.13.6 + web3: + version: <7,>=6.0.0 From 339868a37724f824dcf52fb6a1091a336fff9c68 Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Fri, 16 Feb 2024 13:03:46 +0530 Subject: [PATCH 5/9] feat: add staking contract profile --- backend/operate/ledger/profiles.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/operate/ledger/profiles.py b/backend/operate/ledger/profiles.py index db2c1215d..3f95407c8 100644 --- a/backend/operate/ledger/profiles.py +++ b/backend/operate/ledger/profiles.py @@ -33,3 +33,11 @@ } ) } + +STAKING = { + ChainType.GNOSIS: "0x2Ef503950Be67a98746F484DA0bBAdA339DF3326", +} + +OLAS = { + ChainType.GNOSIS: "0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f", +} From bb5b9eda40568a56688c4f1055eda1a616303e14 Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Fri, 16 Feb 2024 13:04:25 +0530 Subject: [PATCH 6/9] feat: port support for staking --- backend/operate/services/protocol.py | 229 +++++++++++++++++++++++++-- 1 file changed, 213 insertions(+), 16 deletions(-) diff --git a/backend/operate/services/protocol.py b/backend/operate/services/protocol.py index 1452abcea..62a6325b3 100644 --- a/backend/operate/services/protocol.py +++ b/backend/operate/services/protocol.py @@ -31,18 +31,36 @@ from typing import Optional, Union from aea.configurations.data_types import PackageType +from aea.crypto.base import Crypto, LedgerApi from aea.helpers.base import IPFSHash, cd from aea_ledger_ethereum.ethereum import EthereumCrypto from autonomy.chain.base import registry_contracts from autonomy.chain.config import ChainConfigs, ChainType, ContractConfigs from autonomy.chain.service import get_agent_instances, get_service_info +from autonomy.chain.tx import TxSettler from autonomy.cli.helpers.chain import MintHelper as MintManager from autonomy.cli.helpers.chain import OnChainHelper from autonomy.cli.helpers.chain import ServiceHelper as ServiceManager from hexbytes import HexBytes +from operate.data import DATA_DIR +from operate.data.contracts.service_staking_token.contract import ( + ServiceStakingTokenContract, +) +from operate.ledger.profiles import CONTRACTS from ._subgraph import SubgraphClient +ZERO_ETH = 0 + + +class StakingState(Enum): + """Staking state enumeration for the staking.""" + + UNSTAKED = 0 + STAKED = 1 + EVICTED = 2 + + NULL_ADDRESS: str = "0x" + "0" * 40 MAX_UINT256 = 2**256 - 1 @@ -154,15 +172,142 @@ def skill_input_hex_to_payload(payload: str) -> dict: return tx_params -class OnChainManager: - """On chain service management.""" +class StakingManager(OnChainHelper): + """Helper class for staking a service.""" - def __init__( + def __init__(self, key: Path, chain_type: ChainType = ChainType.CUSTOM) -> None: + """Initialize object.""" + super().__init__(key=key, chain_type=chain_type) + self.staking_ctr = t.cast( + ServiceStakingTokenContract, + ServiceStakingTokenContract.from_dir( + directory=str(DATA_DIR / "contracts" / "service_staking_token") + ), + ) + + def status(self, service_id: int, staking_contract: str) -> StakingState: + """Is the service staked?""" + return StakingState( + self.staking_ctr.get_instance( + ledger_api=self.ledger_api, + contract_address=staking_contract, + ) + .getServiceStakingState(service_id) + .call() + ) + + def slots_available(self, staking_contract: str) -> bool: + """Check if there are available slots on the staking contract""" + instance = self.staking_ctr.get_instance( + ledger_api=self.ledger_api, + contract_address=staking_contract, + ) + return instance.maxNumServices().call() - len(instance.getServiceIds().call()) + + def stake( self, - rpc: str, - key: Path, - contracts: t.Dict, + service_id: int, + service_registry: str, + staking_contract: str, ) -> None: + """Stake the service""" + status = self.status(service_id) + if status == StakingState.STAKED: + raise ValueError("Service already stacked") + + if status == StakingState.EVICTED: + raise ValueError("Service is evicted") + + if not self.slots_available(): + raise ValueError("No sataking slots available.") + + tx_settler = TxSettler( + ledger_api=self.ledger_api, + crypto=self.crypto, + chain_type=self.chain_type, + timeout=self.timeout, + retries=self.retries, + sleep=self.sleep, + ) + + # we make use of the ERC20 contract to build the approval transaction + # since it has the same interface as ERC721 we might want to create + # a ERC721 contract package + + def _build_approval_tx(*args, **kargs) -> t.Dict: + return registry_contracts.erc20.get_approve_tx( + ledger_api=self.ledger_api, + contract_address=service_registry, + spender=staking_contract, + amount=service_id, + ) + + setattr(tx_settler, "build", _build_approval_tx) + tx_settler.transact( + method=lambda: {}, + contract="", + kwargs={}, + dry_run=False, + ) + + def _build_staking_tx(*args, **kargs) -> t.Dict: + return { + "data": self.staking_ctr.build_stake_tx( + ledger_api=self.ledger_api, + contract_address=staking_contract, + service_id=service_id, + ).pop("data"), + "to": staking_contract, + "value": ZERO_ETH, + } + + setattr(tx_settler, "build", _build_staking_tx) + tx_settler.transact( + method=lambda: {}, + contract="", + kwargs={}, + dry_run=False, + ) + + def unstake(self, service_id: int, staking_contract: str) -> None: + """Unstake the service""" + if self.status(service_id=service_id) != StakingState.STAKED: + raise ValueError("Service not staked.") + + tx_settler = TxSettler( + ledger_api=self.ledger_api, + crypto=self.crypto, + chain_type=self.chain_type, + timeout=self.timeout, + retries=self.retries, + 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 + ) + 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( + method=lambda: {}, + contract="", + kwargs={}, + dry_run=False, + ) + + +class OnChainManager: + """On chain service management.""" + + def __init__(self, rpc: str, key: Path, contracts: t.Dict) -> None: """On chain manager.""" self.rpc = rpc self.key = key @@ -178,6 +323,26 @@ def _patch(self) -> None: for name, address in self.contracts.items(): ContractConfigs.get(name=name).contracts[self.chain_type] = address + @property + def crypto(self) -> Crypto: + """Load crypto object.""" + self._patch() + _, crypto = OnChainHelper.get_ledger_and_crypto_objects( + chain_type=self.chain_type, + key=self.key, + ) + return crypto + + @property + def ledger_api(self) -> LedgerApi: + """Load ledger api object.""" + self._patch() + ledger_api, _ = OnChainHelper.get_ledger_and_crypto_objects( + chain_type=self.chain_type, + key=self.key, + ) + return ledger_api + def info(self, token_id: int) -> t.Dict: """Get service info.""" self._patch() @@ -224,6 +389,7 @@ def mint( threshold: int, nft: Optional[Union[Path, IPFSHash]], update_token: t.Optional[int] = None, + token: t.Optional[str] = None, ): "Mint service." # TODO: Support for update @@ -259,6 +425,7 @@ def mint( number_of_slots=number_of_slots, cost_of_bond=cost_of_bond, threshold=threshold, + token=token, ) (metadata,) = Path(temp).glob("*.json") published = { @@ -333,6 +500,7 @@ def swap( ) -> None: """Swap safe owner.""" logging.info(f"Swapping safe for service {service_id} [{multisig}]...") + self._patch() manager = ServiceManager( service_id=service_id, chain_type=self.chain_type, @@ -416,13 +584,10 @@ def swap( if receipt["status"] != 1: raise RuntimeError("Error swapping owners") - def terminate( - self, - service_id: int, - token: t.Optional[str] = None, - ) -> None: + def terminate(self, service_id: int, token: t.Optional[str] = None) -> None: """Terminate service.""" logging.info(f"Terminating service {service_id}...") + self._patch() with contextlib.redirect_stdout(io.StringIO()): ServiceManager( service_id=service_id, @@ -432,13 +597,10 @@ def terminate( token=token, ).terminate_service() - def unbond( - self, - service_id: int, - token: t.Optional[str] = None, - ) -> None: + def unbond(self, service_id: int, token: t.Optional[str] = None) -> None: """Unbond service.""" logging.info(f"Unbonding service {service_id}...") + self._patch() with contextlib.redirect_stdout(io.StringIO()): ServiceManager( service_id=service_id, @@ -447,3 +609,38 @@ def unbond( ).check_is_service_token_secured( token=token, ).unbond_service() + + def staking_slots_available(self, staking_contract: str) -> None: + """Stake service.""" + StakingManager( + key=self.key, + chain_type=self.chain_type, + ).slots_available( + staking_contract=staking_contract, + ) + + def stake( + self, + service_id: int, + service_registry: str, + staking_contract: str, + ) -> None: + """Stake service.""" + StakingManager( + key=self.key, + chain_type=self.chain_type, + ).stake( + service_id=service_id, + service_registry=service_registry, + staking_contract=staking_contract, + ) + + def unstake(self, service_id: int, staking_contract: str) -> None: + """Unstake service.""" + StakingManager( + key=self.key, + chain_type=self.chain_type, + ).unstake( + service_id=service_id, + staking_contract=staking_contract, + ) From 1ac6592fef1037fac19011c0310da12b5ce632eb Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Fri, 16 Feb 2024 13:07:50 +0530 Subject: [PATCH 7/9] feat: update service template and support for staking --- backend/operate/ledger/ethereum.py | 208 +--------------------------- backend/operate/services/manage.py | 172 ++++++++++++----------- backend/operate/services/service.py | 5 +- backend/operate/types.py | 33 +++-- client.tsx | 19 ++- templates/trader.yaml | 16 ++- 6 files changed, 152 insertions(+), 301 deletions(-) diff --git a/backend/operate/ledger/ethereum.py b/backend/operate/ledger/ethereum.py index 417c764d9..8d9d4ad77 100644 --- a/backend/operate/ledger/ethereum.py +++ b/backend/operate/ledger/ethereum.py @@ -20,63 +20,20 @@ """Ethereum ledger helpers.""" import typing as t -from datetime import datetime -from aea_ledger_ethereum import EthereumCrypto, EthereumApi + +from aea_ledger_ethereum import EthereumApi, EthereumCrypto from operate.ledger.base import LedgerHelper from operate.types import LedgerType -from web3 import HTTPProvider, Web3 -from operate.ledger.profiles import CONTRACTS -from operate.types import ChainType -import json -from pathlib import Path -from requests.exceptions import ConnectionError as RequestsConnectionError -from autonomy.chain.exceptions import ( - ChainInteractionError, - ChainTimeoutError, - RPCError, -) -from eth_typing import HexStr -from autonomy.chain.tx import ( - TxSettler, - should_retry, - should_reprice, -) -import time -from enum import Enum - - -DEFAULT_ON_CHAIN_INTERACT_TIMEOUT = 120.0 -DEFAULT_ON_CHAIN_INTERACT_RETRIES = 10 -DEFAULT_ON_CHAIN_INTERACT_SLEEP = 6.0 -ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" -ZERO_ETH = 0 - -GAS_PARAMS = { - "maxFeePerGas": 30_000_000_000, - "maxPriorityFeePerGas": 3_000_000_000, - "gas": 500_000, -} - - -class StakingState(Enum): - """Staking state enumeration for the staking.""" - - UNSTAKED = 0 - STAKED = 1 - EVICTED = 2 class Ethereum(LedgerHelper): """Ethereum ledger helper.""" - api: Web3 + api: EthereumApi def __init__(self, rpc: str) -> None: super().__init__(rpc) - self.ledger_api = EthereumApi(address=self.rpc) - self.api = self.ledger_api.api - self.contracts = {chain_type: {} for chain_type in ChainType} - self.load_contracts() + self.api = EthereumApi(address=self.rpc) def create_key(self) -> t.Dict: """Create key.""" @@ -87,160 +44,3 @@ def create_key(self) -> t.Dict: "encrypted": False, "ledger": LedgerType.ETHEREUM, } - - def load_contracts(self) -> None: - """Load all contracts""" - - for abi_path in Path("operate", "ledger", "abis").iterdir(): - for chain_type in ChainType: - if chain_type not in CONTRACTS: - continue - if abi_path.stem not in CONTRACTS[chain_type]: - continue - with open(abi_path, "r") as abi_file: - abi = json.load(abi_file)["abi"] - self.contracts[chain_type][abi_path.stem] = self.api.eth.contract( - address=CONTRACTS[chain_type][abi_path.stem], - abi=abi - ) - - - def get_staking_status(self, service_id) -> StakingState: - """Is the service staked?""" - staking_contract = self.contracts[ChainType.GNOSIS]["ServiceStakingToken"] - a = staking_contract.functions.getServiceStakingState(service_id).call() - return StakingState(a) - - - def is_available_slots(self) -> bool: - """Check if there are available slots on the staking contract""" - staking_contract = self.contracts[ChainType.GNOSIS]["ServiceStakingToken"] - max_num_services = staking_contract.functions.maxNumServices().call() - service_ids = staking_contract.functions.getServiceIds().call() - return max_num_services - len(service_ids) - - - def stake(self, service_id, crypto) -> bool: - """Stake the service""" - - if self.get_staking_status(service_id) != StakingState.UNSTAKED: - return False - - staking_contract = self.contracts[ChainType.GNOSIS]["ServiceStakingToken"] - erc20_contract = self.contracts[ChainType.GNOSIS]["ERC20"] - - # Approval tx: approve the service token to be spent - # We make use of the ERC20 contract to build the approval transaction - # since it has the same interface as ERC721 - # We use the ZERO_ADDRESS as the contract address since we don't do any contract interaction here, - # we are simply encoding - spender = staking_contract.address - amount = service_id - data = erc20_contract.encodeABI("approve", args=(spender, amount)) - - approval_tx = { - "data": bytes.fromhex(data[2:]), - "to": CONTRACTS[ChainType.GNOSIS]["service_registry"], - "value": ZERO_ETH, - } - - # Stake tx - stake_tx = staking_contract.encodeABI("stake", args=[service_id]) - - # Send txs - for tx in (approval_tx, stake_tx): - self.send_tx_and_wait_for_receipt(crypto, tx) - - return True - - - def unstake(self, service_id, crypto) -> bool: - """Unstake the service""" - - if self.get_staking_status(service_id) != StakingState.STAKED: - return False - - # TODO: check unstaking availability for EVICTED services - - staking_contract = self.contracts[ChainType.GNOSIS]["ServiceStakingToken"] - data = staking_contract.encodeABI("unstake", args=[service_id]) - - unstake_tx = { - "data": bytes.fromhex(data[2:]), - "to": CONTRACTS[ChainType.GNOSIS]["ServiceStakingToken"], - "value": ZERO_ETH, - } - - self.send_tx_and_wait_for_receipt(crypto, unstake_tx) - - return True - - - def send_tx_and_wait_for_receipt( - self, - crypto: EthereumCrypto, - raw_tx: t.Dict[str, t.Any], - ) -> t.Dict[str, t.Any]: - """Send transaction and wait for receipt.""" - receipt = HexStr(self.send_tx(crypto, raw_tx)) - if receipt["status"] != 1: - raise ValueError("Transaction failed. Receipt:", receipt) - return receipt - - - def send_tx( - self, - crypto: EthereumCrypto, - raw_tx: t.Dict[str, t.Any], - timeout: float = DEFAULT_ON_CHAIN_INTERACT_TIMEOUT, - max_retries: int = DEFAULT_ON_CHAIN_INTERACT_RETRIES, - sleep: float = DEFAULT_ON_CHAIN_INTERACT_SLEEP, - ) -> str: - """Send transaction.""" - tx_dict = { - **raw_tx, - **GAS_PARAMS, - "from": crypto.address, - "nonce": self.api.eth.get_transaction_count(crypto.address), - "chainId": self.api.eth.chain_id, - } - gas_params = self.ledger_api.try_get_gas_pricing() - if gas_params is not None: - tx_dict.update(gas_params) - - tx_settler = TxSettler(self.api, crypto, ChainType.CUSTOM) - retries = 0 - tx_digest = None - already_known = False - deadline = datetime.now().timestamp() + timeout - while retries < max_retries and deadline >= datetime.now().timestamp(): - retries += 1 - try: - if not already_known: - tx_signed = crypto.sign_transaction(transaction=tx_dict) - tx_digest = self.ledger_api.send_signed_transaction( - tx_signed=tx_signed, - raise_on_try=True, - ) - tx_receipt = self.api.eth.get_transaction_receipt( - t.cast(str, tx_digest) - ) - if tx_receipt is not None: - return tx_receipt - except RequestsConnectionError as e: - raise RPCError("Cannot connect to the given RPC") from e - except Exception as e: # pylint: disable=broad-except - error = str(e) - if tx_settler._already_known(error): - already_known = True - continue # pragma: nocover - if not should_retry(error): - raise ChainInteractionError(error) from e - if should_reprice(error): - print("Repricing the transaction...") - tx_dict = tx_settler._repice(t.cast(t.Dict, tx_dict)) - continue - print(f"Error occurred when interacting with chain: {e}; ") - print(f"will retry in {sleep}...") - time.sleep(sleep) - raise ChainTimeoutError("Timed out when waiting for transaction to go through") \ No newline at end of file diff --git a/backend/operate/services/manage.py b/backend/operate/services/manage.py index 91d159848..fa5fef3fa 100644 --- a/backend/operate/services/manage.py +++ b/backend/operate/services/manage.py @@ -26,6 +26,7 @@ from pathlib import Path from aea.helpers.base import IPFSHash +from autonomy.chain.base import registry_contracts from autonomy.deploy.constants import ( AGENT_KEYS_DIR, BENCHMARKS_DIR, @@ -35,11 +36,18 @@ VENVS_DIR, ) from operate.http import Resource +from operate.http.exceptions import BadRequest from operate.keys import Keys -from operate.ledger.profiles import CONTRACTS +from operate.ledger.profiles import CONTRACTS, OLAS, STAKING from operate.services.protocol import OnChainManager from operate.services.service import Service -from operate.types import ChainData, ServicesType, ServiceTemplate, ServiceType +from operate.types import ( + ChainData, + ConfigurationTemplate, + ServicesType, + ServiceTemplate, + ServiceType, +) from starlette.types import Receive, Scope, Send from typing_extensions import TypedDict @@ -140,9 +148,18 @@ def json(self) -> GetServices: data.append(Service.load(path=service).json) return data - def create(self, data: PostServices) -> PostServices: - """Create a service.""" - phash = data["hash"] + def _stake(self) -> None: + """Stake a service.""" + + def _create( + self, + phash: str, + configuration: ConfigurationTemplate, + instances: t.Optional[t.List[str]] = None, + update_token: t.Optional[int] = None, + reuse_multisig: bool = False, + ) -> Service: + """Create a new service.""" if (self.path / phash).exists(): # For testing only shutil.rmtree(self.path / phash) @@ -156,42 +173,79 @@ def create(self, data: PostServices) -> PostServices: ) ledger = service.helper.ledger_config() - deployment = service.helper.deployment_config() - instances = [ + instances = instances or [ self.keys.create() for _ in range(service.helper.config.number_of_agents) ] ocm = OnChainManager( - rpc=data["rpc"], + rpc=configuration["rpc"], key=self.key, contracts=CONTRACTS[ledger["chain"]], ) + if configuration["use_staking"] and not ocm.staking_slots_available( + staking_address=STAKING[ledger["chain"]], + ): + raise ValueError("No staking slots available") + # Update to user provided RPC - ledger["rpc"] = data["rpc"] + ledger["rpc"] = configuration["rpc"] logging.info(f"Minting service {phash}") service_id = t.cast( int, ocm.mint( package_path=service.service_path, - agent_id=deployment["chain"]["agent_id"], + agent_id=configuration["agent_id"], number_of_slots=service.helper.config.number_of_agents, - cost_of_bond=deployment["chain"]["cost_of_bond"], - threshold=deployment["chain"]["threshold"], - nft=IPFSHash(deployment["chain"]["nft"]), + cost_of_bond=( + configuration["olas_required_to_bond"] + if configuration["use_staking"] + else configuration["cost_of_bond"] + ), + threshold=configuration["threshold"], + nft=IPFSHash(configuration["nft"]), + update_token=update_token, + token=OLAS[ledger["chain"]] if configuration["use_staking"] else None, ).get("token"), ) logging.info(f"Activating service {phash}") - ocm.activate(service_id=service_id) + 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, + ) ocm.register( service_id=service_id, instances=instances, - agents=[deployment["chain"]["agent_id"] for _ in instances], + agents=[configuration["agent_id"] for _ in instances], + token=OLAS[ledger["chain"]] if configuration["use_staking"] else None, ) logging.info(f"Deploying service {phash}") - ocm.deploy(service_id=service_id) + ocm.deploy( + service_id=service_id, + reuse_multisig=reuse_multisig, + token=OLAS[ledger["chain"]] if configuration["use_staking"] else None, + ) logging.info(f"Updating service {phash}") info = ocm.info(token_id=service_id) @@ -206,26 +260,38 @@ def create(self, data: PostServices) -> PostServices: ) service.store() + if configuration["use_staking"]: + ocm.stake( + service_id=service_id, + service_registry=CONTRACTS[ledger["chain"]]["service_registry"], + staking_contract=STAKING[ledger["chain"]], + ) + logging.info(f"Building deployment for service {phash}") deployment = service.deployment() deployment.create({}) deployment.store() + return service + + def create(self, data: PostServices) -> PostServices: + """Create a service.""" + service = self._create( + phash=data["hash"], + configuration=data["configuration"], + ) return service.json def update(self, data: PutServices) -> ServiceType: """Update service using a template.""" # NOTE: This method contains a lot of repetative code - - # Load old service - old = Service.load(path=self.path / data["old"]) - - rpc = data["new"]["rpc"] - phash = data["new"]["hash"] - + rpc = data["new"]["configuration"]["rpc"] + phash = data["new"]["configuration"]["hash"] if (self.path / phash).exists(): # For testing only shutil.rmtree(self.path / phash) + # Load old service + old = Service.load(path=self.path / data["old"]) instances = old.chain_data["instances"] ocm = OnChainManager( rpc=rpc, @@ -251,68 +317,14 @@ def update(self, data: PutServices) -> ServiceType: multisig=old.chain_data["multisig"], owner_key=owner_key, ) - - logging.info(f"Fetching service {phash}") - service = Service.new( - path=self.path, + service = self._create( phash=phash, - keys=[], - chain_data=ChainData(), - ledger={}, - ) - - ledger = service.helper.ledger_config() - deployment = service.helper.deployment_config() - - # Update to user provided RPC - ledger["rpc"] = data["new"]["rpc"] - - logging.info(f"Minting service {phash}") - service_id = t.cast( - int, - ocm.mint( - package_path=service.service_path, - agent_id=deployment["chain"]["agent_id"], - number_of_slots=service.helper.config.number_of_agents, - cost_of_bond=deployment["chain"]["cost_of_bond"], - threshold=deployment["chain"]["threshold"], - nft=IPFSHash(deployment["chain"]["nft"]), - update_token=old.chain_data["token"], - ).get("token"), - ) - - logging.info(f"Activating service {phash}") - ocm.activate(service_id=service_id) - ocm.register( - service_id=service_id, + rpc=rpc, instances=instances, - agents=[deployment["chain"]["agent_id"] for _ in instances], - ) - - logging.info(f"Deploying service {phash}") - ocm.deploy( - service_id=service_id, reuse_multisig=True, + update_token=old.chain_data["token"], ) - logging.info(f"Updating service {phash}") - info = ocm.info(token_id=service_id) - service.ledger = ledger - service.keys = [self.keys.get(key=key) for key in instances] - service.chain_data = ChainData( - { - "token": service_id, - "instances": info["instances"], - "multisig": info["multisig"], - } - ) - service.store() - - # Build docker-compose deployment - deployment = service.deployment() - deployment.create({}) - deployment.store() - # try: # shutil.rmtree(old.path) # except Exception as e: diff --git a/backend/operate/services/service.py b/backend/operate/services/service.py index ab9c40590..39273aad5 100644 --- a/backend/operate/services/service.py +++ b/backend/operate/services/service.py @@ -239,10 +239,7 @@ def create(self, data: t.Dict) -> DeploymentType: _volumes = [] for volume, mount in ( - service.helper.deployment_config() - .get("local", {}) - .get("volumes", {}) - .items() + service.helper.deployment_config().get("volumes", {}).items() ): (build / volume).mkdir(exist_ok=True) _volumes.append(f"./{volume}:{mount}:Z") diff --git a/backend/operate/types.py b/backend/operate/types.py index 09918db86..1a8a82c97 100644 --- a/backend/operate/types.py +++ b/backend/operate/types.py @@ -157,18 +157,10 @@ class ChainDeployment(TypedDict): required_funds: float -class LocalDeployment(TypedDict): - """Local deployment template.""" - - ports: t.Dict - volumes: t.Dict[str, str] - - class DeploymentConfig(TypedDict): """Deployments template.""" - chain: ChainDeployment - local: LocalDeployment + volumes: t.Dict[str, str] class ServiceType(TypedDict): @@ -185,14 +177,35 @@ class ServiceType(TypedDict): ServicesType = t.List[ServiceType] +class FundRequirementsTemplate(TypedDict): + """Fund requirement template.""" + + agent: float + safe: float + + +class ConfigurationTemplate(TypedDict): + """Configuration template.""" + + nft: str + rpc: str + agent_id: int + threshold: int + use_staking: bool + cost_of_bond: int + olas_required_to_bond: int + olas_required_to_stake: int + fund_requirements: FundRequirementsTemplate + + class ServiceTemplate(TypedDict): """Service template.""" - rpc: str name: str hash: str image: str description: str + configuration: ConfigurationTemplate class Action(enum.IntEnum): diff --git a/client.tsx b/client.tsx index 34bc86b50..8c69c6038 100644 --- a/client.tsx +++ b/client.tsx @@ -50,12 +50,29 @@ type ServiceType = { type ServicesType = ServiceType[]; -type ServiceTemplate = { +type FundRequirementsTemplate = { + agent: number; + safe: number; +}; + +type ConfigurationTemplate = { + nft: string; rpc: string; + agent_id: number; + threshold: number; + use_staking: number; + cost_of_bond: number; + olas_required_to_bond: number; + olas_required_to_stake: number; + fund_requirements: FundRequirementsTemplate; +}; + +type ServiceTemplate = { name: string; hash: string; image: string; description: string; + configuration: ConfigurationTemplate; }; enum Status { diff --git a/templates/trader.yaml b/templates/trader.yaml index 0021ac01f..3c255671c 100644 --- a/templates/trader.yaml +++ b/templates/trader.yaml @@ -1,5 +1,17 @@ name: "Trader Agent" description: "Trader agent for omen prediction markets" -hash: bafybeifpttju2bwc4w5btg2ijdpoajvr3axjnxr3pivb7dt7okfrrse3iu +hash: bafybeieagxzdbmea3nttlve3yxjne5z7tt7mp26tfpgepm7p2ezovtdx4a image: https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75 -rpc: http://localhost:8545 # User provided \ No newline at end of file +configuration: + nft: bafybeig64atqaladigoc3ds4arltdu63wkdrk3gesjfvnfdmz35amv7faq + rpc: http://localhost:8545 # User provided + agent_id: 14 + 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 + fund_requirements: + agent: 0.1 + safe: 0.5 From 877baaa84235318813140b425854cedec028695d Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Fri, 16 Feb 2024 13:08:31 +0530 Subject: [PATCH 8/9] feat: testing scripts --- .../{endpoint_e2e_test.py => test_e2e.py} | 22 +++-- backend/scripts/test_staking_e2e.py | 90 +++++++++++++++++++ 2 files changed, 100 insertions(+), 12 deletions(-) rename backend/scripts/{endpoint_e2e_test.py => test_e2e.py} (83%) create mode 100644 backend/scripts/test_staking_e2e.py diff --git a/backend/scripts/endpoint_e2e_test.py b/backend/scripts/test_e2e.py similarity index 83% rename from backend/scripts/endpoint_e2e_test.py rename to backend/scripts/test_e2e.py index 259e35e1c..acc74e60b 100644 --- a/backend/scripts/endpoint_e2e_test.py +++ b/backend/scripts/test_e2e.py @@ -19,25 +19,23 @@ # ------------------------------------------------------------------------------ """This module contains e2e tests.""" +from pathlib import Path + import requests +from aea.helpers.yaml_utils import yaml_load from aea_ledger_ethereum.ethereum import EthereumApi, EthereumCrypto -TRADER_TEMPLATE = { - "name": "Trader Agent", - "description": "Trader agent for omen prediction markets", - "hash": "bafybeigiwlvm6ey4dmlztg3z4xyvpol23n444vliivx2ybuki7xo4f3pae", - "image": "https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75", - "rpc": "http://localhost:8545", # User provided -} - BASE_URL = "http://localhost:8000/api" def test_endpoint_e2e(): + with Path("templates/trader.yaml").open("r", encoding="utf-8") as stream: + trader_template = yaml_load(stream=stream) + print("Creating service using template") response = requests.post( url=f"{BASE_URL}/services", - json=TRADER_TEMPLATE, + json=trader_template, ).json() print(response) @@ -72,8 +70,8 @@ def test_endpoint_e2e(): digest = ledger_api.send_signed_transaction(stx) ledger_api.get_transaction_receipt(tx_digest=digest) - old = TRADER_TEMPLATE["hash"] - TRADER_TEMPLATE["hash"] = ( + old = trader_template["hash"] + trader_template["hash"] = ( "bafybeicxdpkuk5z5zfbkso7v5pywf4v7chxvluyht7dtgalg6dnhl7ejoe" ) print( @@ -81,7 +79,7 @@ def test_endpoint_e2e(): url=f"{BASE_URL}/services", json={ "old": old, - "new": TRADER_TEMPLATE, + "new": trader_template, }, ).content.decode() ) diff --git a/backend/scripts/test_staking_e2e.py b/backend/scripts/test_staking_e2e.py new file mode 100644 index 000000000..1e3d8d779 --- /dev/null +++ b/backend/scripts/test_staking_e2e.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2021-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. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ +"""This module contains e2e tests.""" + +from pathlib import Path + +import requests +from aea.helpers.yaml_utils import yaml_load +from aea_ledger_ethereum.ethereum import EthereumApi, EthereumCrypto + +BASE_URL = "http://localhost:8000/api" + + +def test_endpoint_e2e(): + with Path("templates/trader.yaml").open("r", encoding="utf-8") as stream: + trader_template = yaml_load(stream=stream) + trader_template["configuration"]["use_staking"] = True + + print("Creating service using template") + response = requests.post( + url=f"{BASE_URL}/services", + json=trader_template, + ).json() + print(response) + + input("> Press enter to start") + print( + requests.get( + url=f"{BASE_URL}/services/bafybeigiwlvm6ey4dmlztg3z4xyvpol23n444vliivx2ybuki7xo4f3pae/deploy/", + ).content.decode() + ) + + input("> Press enter to stop") + print( + requests.get( + url=f"{BASE_URL}/services/bafybeigiwlvm6ey4dmlztg3z4xyvpol23n444vliivx2ybuki7xo4f3pae/stop/", + ).content.decode() + ) + + input("> Press enter to update") + # Fund agent instance for swapping + ledger_api = EthereumApi(address="http://localhost:8545") + crypto = EthereumCrypto(".operate/key") + (owner,) = response["chain_data"]["instances"] + tx = ledger_api.get_transfer_transaction( + sender_address=crypto.address, + destination_address=owner, + amount=1000000000000000, + tx_fee=50000, + tx_nonce="0x", + chain_id=100, + ) + stx = crypto.sign_transaction(transaction=tx) + digest = ledger_api.send_signed_transaction(stx) + ledger_api.get_transaction_receipt(tx_digest=digest) + + old = trader_template["hash"] + trader_template["hash"] = ( + "bafybeicxdpkuk5z5zfbkso7v5pywf4v7chxvluyht7dtgalg6dnhl7ejoe" + ) + print( + requests.put( + url=f"{BASE_URL}/services", + json={ + "old": old, + "new": trader_template, + }, + ).content.decode() + ) + + +if __name__ == "__main__": + test_endpoint_e2e() From 6683069d7423001a5e3a2fa3df38acc3b268dc2f Mon Sep 17 00:00:00 2001 From: angrybayblade Date: Fri, 16 Feb 2024 13:08:43 +0530 Subject: [PATCH 9/9] chore: update .gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 61a193911..56d9e33af 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,6 @@ backend/scripts/__pycache__/ data/ __pycache__/ tmp/ -temp/ \ No newline at end of file +temp/ + +!backend/operate/data \ No newline at end of file