diff --git a/.api_keys.json.example b/.api_keys.json.example new file mode 100644 index 0000000..3670e44 --- /dev/null +++ b/.api_keys.json.example @@ -0,0 +1,10 @@ +{ + "openai": [ + "Your #1 OpenAI API key here", + "Your #2 OpenAI API key here" + ], + "google_api_key": [ + "Your #1 Google API key here", + "Your #2 Google API key here" + ] +} \ No newline at end of file diff --git a/.env.example b/.env.example deleted file mode 100644 index f6a8837..0000000 --- a/.env.example +++ /dev/null @@ -1,5 +0,0 @@ -FORK_URL= -NODE_ENV= -DEV_RPC= -STAKING_TEST_KEYS_PATH= -IS_STAGING= diff --git a/.gitignore b/.gitignore index 7a1e292..214c561 100644 --- a/.gitignore +++ b/.gitignore @@ -36,13 +36,11 @@ temp/ electron/.next dist/ -build/ cache leak_report *.dist -*.build /electron/bins/ # logs @@ -55,3 +53,4 @@ local_config.json mech.db +/.api_keys.json diff --git a/contracts/MechAgentFactory.json b/contracts/MechAgentFactory.json new file mode 100644 index 0000000..bfbc437 --- /dev/null +++ b/contracts/MechAgentFactory.json @@ -0,0 +1,539 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "MechMarketplace", + "sourceName": "contracts/MechMarketplace.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_agentRegistry", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "AgentInstanceRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "AgentInstancesSlotsFilled", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "agentId", + "type": "uint256" + } + ], + "name": "AgentNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "agentId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "AgentNotInService", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "componentId", + "type": "uint256" + } + ], + "name": "ComponentNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "HashExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "IncorrectAgentBondingValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "sent", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "IncorrectRegistrationDepositValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "manager", + "type": "address" + } + ], + "name": "ManagerOnly", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "provided", + "type": "address" + }, + { + "internalType": "address", + "name": "expected", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "OnlyOwnServiceMultisig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "OperatorHasNoInstances", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "provided", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "Overflow", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnerOnly", + "type": "error" + }, + { + "inputs": [], + "name": "Paused", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuard", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "ServiceMustBeInactive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "multisig", + "type": "address" + } + ], + "name": "UnauthorizedMultisig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "agentId", + "type": "uint256" + } + ], + "name": "WrongAgentId", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numValues1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numValues2", + "type": "uint256" + } + ], + "name": "WrongArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "WrongOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "state", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "WrongServiceState", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxThreshold", + "type": "uint256" + } + ], + "name": "WrongThreshold", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValue", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "mech", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "agentId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "price", + "type": "uint256" + } + ], + "name": "CreateMech", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "Pause", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "Unpause", + "type": "event" + }, + { + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "agentRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "changeOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "agentOwner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "agentHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "price", + "type": "uint256" + }, + { + "internalType": "address", + "name": "mechMarketplace", + "type": "address" + } + ], + "name": "create", + "outputs": [ + { + "internalType": "uint256", + "name": "agentId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "mech", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/contracts/MechMarketplace.json b/contracts/MechMarketplace.json new file mode 100644 index 0000000..63cc2ef --- /dev/null +++ b/contracts/MechMarketplace.json @@ -0,0 +1,837 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "MechMarketplace", + "sourceName": "contracts/MechMarketplace.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_stakingFactory", + "type": "address" + }, + { + "internalType": "address", + "name": "_karmaProxy", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_minResponseTimeout", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxResponseTimeout", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "name": "AlreadyDelivered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "provided", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "min", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "max", + "type": "uint256" + } + ], + "name": "OutOfBounds", + "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": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "current", + "type": "uint256" + } + ], + "name": "PriorityMechResponseTimeout", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuard", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "stakingInstance", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "ServiceNotStaked", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "UnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValue", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "factory", + "type": "address" + } + ], + "name": "FactoryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "priorityMech", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "actualMech", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "requester", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "MarketplaceDeliver", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "requester", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "requestedMech", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "MarketplaceRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "mech", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "status", + "type": "bool" + } + ], + "name": "MechRegistrationStatusChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "minResponseTimeout", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maxResponseTimeout", + "type": "uint256" + } + ], + "name": "MinMaxResponseTimeoutUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnerUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR_TYPE_HASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "chainId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "mech", + "type": "address" + }, + { + "internalType": "address", + "name": "mechStakingInstance", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mechServiceId", + "type": "uint256" + } + ], + "name": "checkMech", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "requester", + "type": "address" + }, + { + "internalType": "address", + "name": "requesterStakingInstance", + "type": "address" + }, + { + "internalType": "uint256", + "name": "requesterServiceId", + "type": "uint256" + } + ], + "name": "checkRequester", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "stakingInstance", + "type": "address" + }, + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "checkStakingInstance", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "requestData", + "type": "bytes" + }, + { + "internalType": "address", + "name": "deliveryMechStakingInstance", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deliveryMechServiceId", + "type": "uint256" + } + ], + "name": "deliverMarketplace", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "domainSeparator", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getDeliveriesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDomainSeparator", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "name": "getMechDeliveryInfo", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "priorityMech", + "type": "address" + }, + { + "internalType": "address", + "name": "deliveryMech", + "type": "address" + }, + { + "internalType": "address", + "name": "requester", + "type": "address" + }, + { + "internalType": "uint32", + "name": "responseTimeout", + "type": "uint32" + } + ], + "internalType": "struct MechDelivery", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "mechService", + "type": "address" + } + ], + "name": "getMechServiceDeliveriesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "name": "getRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "name": "getRequestStatus", + "outputs": [ + { + "internalType": "enum MechMarketplace.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getRequestsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "karmaProxy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mapDeliveryCounts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mapMechServiceDeliveryCounts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mapNonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mapRequestCounts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "mapRequestIdDeliveries", + "outputs": [ + { + "internalType": "address", + "name": "priorityMech", + "type": "address" + }, + { + "internalType": "address", + "name": "deliveryMech", + "type": "address" + }, + { + "internalType": "address", + "name": "requester", + "type": "address" + }, + { + "internalType": "uint32", + "name": "responseTimeout", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxResponseTimeout", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minResponseTimeout", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numTotalRequests", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numUndeliveredRequests", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "address", + "name": "priorityMech", + "type": "address" + }, + { + "internalType": "address", + "name": "priorityMechStakingInstance", + "type": "address" + }, + { + "internalType": "uint256", + "name": "priorityMechServiceId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "requesterStakingInstance", + "type": "address" + }, + { + "internalType": "uint256", + "name": "requesterServiceId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "responseTimeout", + "type": "uint256" + } + ], + "name": "request", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "stakingFactory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json b/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json new file mode 100644 index 0000000..fe98dab --- /dev/null +++ b/operate/data/contracts/service_staking_token/build/ServiceStakingToken.json @@ -0,0 +1,1273 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "ServiceStakingToken", + "sourceName": "contracts/staking/ServiceStakingToken.sol", + "abi": [ + { + "inputs": [], + "name": "AlreadyInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "activityChecker", + "type": "address" + } + ], + "name": "ContractOnly", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "provided", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "LowerThan", + "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": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnerOnly", + "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": "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": "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": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroTokenAddress", + "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[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epochLength", + "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[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "RewardClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "serviceInactivity", + "type": "uint256" + } + ], + "name": "ServiceInactivityWarning", + "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": [], + "name": "activityChecker", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "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": "calculateStakingLastReward", + "outputs": [ + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "calculateStakingReward", + "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": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "checkpointAndClaim", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "serviceId", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "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": "emissionsAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "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": "getStakingState", + "outputs": [ + { + "internalType": "enum StakingBase.StakingState", + "name": "stakingState", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "metadataHash", + "type": "bytes32" + }, + { + "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": "timeForEmissions", + "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": "bytes32", + "name": "proxyHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "serviceRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "activityChecker", + "type": "address" + } + ], + "internalType": "struct StakingBase.StakingParams", + "name": "_stakingParams", + "type": "tuple" + }, + { + "internalType": "address", + "name": "_serviceRegistryTokenUtility", + "type": "address" + }, + { + "internalType": "address", + "name": "_stakingToken", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "livenessPeriod", + "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": "metadataHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "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": "timeForEmissions", + "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": [ + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "6080604052348015600e575f80fd5b506135e88061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106102c2575f3560e01c80638f9e0a621161017c578063c5a1d7f0116100dd578063eb338c9611610093578063f86ad2b61161006e578063f86ad2b6146105be578063fd0bba8c146105c7578063ffa1ad74146105e7575f80fd5b8063eb338c961461059b578063f189e85a146105ae578063f4dce714146105b6575f80fd5b8063e1f1176d116100c3578063e1f1176d14610580578063e77cdcc914610589578063eacdaabc14610592575f80fd5b8063c5a1d7f014610565578063cbcf252a1461056d575f80fd5b8063b150876011610132578063b69ef8a811610118578063b69ef8a814610530578063b6b55f2514610539578063c2c4c5c11461054c575f80fd5b8063b150876014610508578063b267c67b1461051d575f80fd5b8063a0ed60e011610162578063a0ed60e01461046f578063a694fc3a14610478578063a74466ad1461048d575f80fd5b80638f9e0a62146104535780639573236114610466575f80fd5b806352c824f5116102265780637fbe2833116101dc57806382a8ea58116101c257806382a8ea581461041757806383f9eb2214610437578063879d90901461044a575f80fd5b80637fbe2833146103fb578063809cee2f1461040e575f80fd5b806356e760581161020c57806356e76058146103cc5780635829c5ec146103df57806372f702f3146103e8575f80fd5b806352c824f5146103b0578063546af2e0146103b9575f80fd5b8063287140511161027b578063379607f511610261578063379607f51461038b5780633e7329971461039e57806342cde4e8146103a7575f80fd5b8063287140511461034d5780632e17de7814610378575f80fd5b8063150b7a02116102ab578063150b7a02146102eb57806316a751721461033b5780631f77940814610344575f80fd5b806308ae7e54146102c657806314b19c5a146102e2575b5f80fd5b6102cf600d5481565b6040519081526020015b60405180910390f35b6102cf600f5481565b61030a6102f9366004612bdb565b630a85bd0160e11b95945050505050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016102d9565b6102cf60015481565b6102cf60065481565b601754610360906001600160a01b031681565b6040516001600160a01b0390911681526020016102d9565b6102cf610386366004612c72565b610618565b6102cf610399366004612c72565b610991565b6102cf60135481565b6102cf60085481565b6102cf60055481565b6102cf6103c7366004612c72565b6109a2565b6102cf6103da366004612c72565b6109ae565b6102cf60075481565b601854610360906001600160a01b031681565b6102cf610409366004612c72565b6109cd565b6102cf600a5481565b61042a610425366004612c72565b610a94565b6040516102d99190612cc3565b6102cf610445366004612c72565b610b83565b6102cf60115481565b600c54610360906001600160a01b031681565b6102cf60125481565b6102cf60045481565b61048b610486366004612c72565b610c3b565b005b6104d561049b366004612c72565b60156020525f9081526040902080546001820154600383015460048401546005909401546001600160a01b03938416949390921692909185565b604080516001600160a01b039687168152959094166020860152928401919091526060830152608082015260a0016102d9565b61051061111a565b6040516102d99190612d29565b61048b61052b366004612e5d565b611170565b6102cf60105481565b61048b610547366004612c72565b6111e6565b610554611273565b6040516102d9959493929190612f91565b6102cf5f5481565b600b54610360906001600160a01b031681565b6102cf60095481565b6102cf60035481565b6102cf60025481565b6102cf6105a9366004612c72565b6118df565b6105106118ee565b6102cf611942565b6102cf600e5481565b6105da6105d5366004612c72565b611958565b6040516102d99190613052565b61060b604051806040016040528060058152602001640302e322e360dc1b81525081565b6040516102d99190613078565b5f81815260156020526040812060018101546001600160a01b0316331461066e57600181015460405163521eb56d60e11b81523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b60038101545f61067e82426130c1565b9050600d54811115801561069357505f601154115b156106c657600d5460405163ba2bbc6b60e01b815260048101879052602481018390526044810191909152606401610665565b5f806106d0611273565b9450505050915081515f03610730576106e76118ee565b9150815167ffffffffffffffff81111561070357610703612d3b565b60405190808252806020026020018201604052801561072c578160200160208202803683370190505b5090505b5f805b8351821015610790578883838151811061074f5761074f6130d4565b602002602001015103156107905788848381518110610770576107706130d4565b60200260200101510361078557506001610790565b816001019150610733565b866004015497505f876002018054806020026020016040519081016040528092919081815260200182805480156107e457602002820191905f5260205f20905b8154815260200190600101908083116107d0575b50508b545f8f815260156020526040812080546001600160a01b0319908116825560018201805490911690559596506001600160a01b03909116949350915061083290506002830182612b3c565b505f600382018190556004820181905560059091015582156108ba576016805461085e906001906130c1565b8154811061086e5761086e6130d4565b905f5260205f2001546016858154811061088a5761088a6130d4565b5f9182526020909120015560168054806108a6576108a66130e8565b600190038181905f5260205f20015f905590555b600b54604051632142170760e11b8152306004820152336024820152604481018d90526001600160a01b03909116906342842e0e906064015f604051808303815f87803b158015610909575f80fd5b505af115801561091b573d5f803e3d5ffd5b505050505f8a111561093157610931818b611a2a565b806001600160a01b0316336001600160a01b03168c7f950733f4c0bf951b8e770f3cc619a4288e7b59b1236d59aeaf2c238488e8ae81600f54868f60405161097b939291906130fc565b60405180910390a4505050505050505050919050565b5f61099c825f611a9e565b92915050565b5f61099c826001611a9e565b601481815481106109bd575f80fd5b5f91825260209091200154905081565b5f818152601560209081526040808320815160c08101835281546001600160a01b0390811682526001830154168185015260028201805484518187028101870186528181528796939586019390929190830182828015610a4a57602002820191905f5260205f20905b815481526020019060010190808311610a36575b505050505081526020016003820154815260200160048201548152602001600582015481525050905080608001519150610a8383610b83565b610a8d9083613124565b9392505050565b610ada6040518060c001604052805f6001600160a01b031681526020015f6001600160a01b03168152602001606081526020015f81526020015f81526020015f81525090565b5f82815260156020908152604091829020825160c08101845281546001600160a01b0390811682526001830154168184015260028201805485518186028101860187528181529295939493860193830182828015610b5557602002820191905f5260205f20905b815481526020019060010190808311610b41575b5050505050815260200160038201548152602001600482015481526020016005820154815250509050919050565b5f805f805f80610b91611ba2565b505050945094509450945094505f5b84811015610c305787838281518110610bbb57610bbb6130d4565b602002602001015103610c285785841115610c07578386838381518110610be457610be46130d4565b6020026020010151610bf69190613137565b610c009190613162565b9650610c30565b818181518110610c1957610c196130d4565b60200260200101519650610c30565b600101610ba0565b505050505050919050565b6011545f03610c5d5760405163afb0be3360e01b815260040160405180910390fd5b5f818152601560205260409020600381015415610c905760405163b4817ce760e01b815260048101839052602401610665565b6016546001548103610cbb5760015460405163fd20861560e01b815260040161066591815260200190565b600b5460405163ef0e239b60e01b8152600481018590525f916001600160a01b03169063ef0e239b906024015f60405180830381865afa158015610d01573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d28919081019061321f565b9050806080015163ffffffff1660075414610d5957604051637ad404bf60e11b815260048101859052602401610665565b60095415801590610d705750806040015160095414155b15610d9157604051637ad404bf60e11b815260048101859052602401610665565b5f600854118015610dae5750806060015163ffffffff1660085414155b15610dcf57604051637ad404bf60e11b815260048101859052602401610665565b60048160c001516005811115610de757610de761303e565b14610e26578060c001516005811115610e0257610e0261303e565b604051633c053f9d60e21b8152600481019190915260248101859052604401610665565b5f81602001516001600160a01b0316803b806020016040519081016040528181525f908060200190933c80519060200120905080600a5414610e8b57602082015160405162a2307960e51b81526001600160a01b039091166004820152602401610665565b6014548015610f4f5760e083015151818114610ebd57604051637ad404bf60e11b815260048101889052602401610665565b5f5b81811015610f4c578460e001518181518110610edd57610edd6130d4565b602002602001015163ffffffff1660148281548110610efe57610efe6130d4565b905f5260205f20015414610f445760148181548110610f1f57610f1f6130d4565b905f5260205f200154604051632ab10b0b60e21b815260040161066591815260200190565b600101610ebf565b50505b610f6f86845f01516bffffffffffffffffffffffff168560e00151611f38565b602083015185546001600160a01b039182166001600160a01b0319918216811788556001880180549092163317909155600c5460405163d564c4bf60e01b815260048101929092525f92169063d564c4bf906024015f60405180830381865afa158015610fde573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261100591908101906132f8565b805190915061101d9060028801906020840190612b5a565b50426003870155601680546001810182555f919091527fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428901879055600b54604051632142170760e11b8152336004820152306024820152604481018990526001600160a01b03909116906342842e0e906064015f604051808303815f87803b1580156110a7575f80fd5b505af11580156110b9573d5f803e3d5ffd5b5050505083602001516001600160a01b0316336001600160a01b0316887faa6b005b4958114a0c90492461c24af6525ae0178db7fbf44125ae9217c69ccb600f5485604051611109929190613384565b60405180910390a450505050505050565b6060601480548060200260200160405190810160405280929190818152602001828054801561116657602002820191905f5260205f20905b815481526020019060010190808311611152575b5050505050905090565b61117983612121565b6001600160a01b038116158061119657506001600160a01b038216155b156111b457604051636b093aad60e01b815260040160405180910390fd5b601880546001600160a01b039283166001600160a01b0319918216179091556017805493909216921691909117905550565b5f816010546111f59190613124565b90505f826011546112069190613124565b6010839055601181905560185490915061122b906001600160a01b031633308661249f565b604080518481526020810184905290810182905233907f36af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1e9060600160405180910390a2505050565b60608060608060605f805f805f805f8061128b611ba2565b97509750975097509750975097509750606080845167ffffffffffffffff8111156112b8576112b8612d3b565b6040519080825280602002602001820160405280156112e1578160200160208202803683370190505b509a505f8915611662578967ffffffffffffffff81111561130457611304612d3b565b60405190808252806020026020018201604052801561132d578160200160208202803683370190505b5092508967ffffffffffffffff81111561134957611349612d3b565b604051908082528060200260200182016040528015611372578160200160208202803683370190505b5091508a89111561156f575f8060015b8c81101561146b578b8e8b838151811061139e5761139e6130d4565b60200260200101516113b09190613137565b6113ba9190613162565b92506113c68383613124565b91508a81815181106113da576113da6130d4565b602002602001015193508a81815181106113f6576113f66130d4565b6020026020010151868281518110611410576114106130d4565b6020026020010181815250508285828151811061142f5761142f6130d4565b6020026020010181815250508260155f8681526020019081526020015f206004015f82825461145e9190613124565b9091555050600101611382565b508a8d8a5f81518110611480576114806130d4565b60200260200101516114929190613137565b61149c9190613162565b91506114a88282613124565b9050895f815181106114bc576114bc6130d4565b60200260200101519250895f815181106114d8576114d86130d4565b6020026020010151855f815181106114f2576114f26130d4565b602002602001018181525050808d111561151d57611510818e6130c1565b61151a9083613124565b91505b81845f81518110611530576115306130d4565b6020026020010181815250508160155f8581526020019081526020015f206004015f82825461155f9190613124565b909155505f9d5061165c92505050565b5f5b8a81101561164e5788818151811061158b5761158b6130d4565b602002602001015191508881815181106115a7576115a76130d4565b60200260200101518482815181106115c1576115c16130d4565b6020026020010181815250508781815181106115df576115df6130d4565b60200260200101518382815181106115f9576115f96130d4565b602002602001018181525050878181518110611617576116176130d4565b602002602001015160155f8481526020019081526020015f206004015f8282546116419190613124565b9091555050600101611571565b50611659898c6130c1565b9a505b60118b90555b8551156118c957600f545f9a508a5b87518110156118505787818151811061168c5761168c6130d4565b602002602001015192508681815181106116a8576116a86130d4565b602002602001015160155f8581526020019081526020015f2060020190805190602001906116d7929190612b5a565b505f8682815181106116eb576116eb6130d4565b602002602001015111156118365785818151811061170b5761170b6130d4565b602002602001015160155f8581526020019081526020015f20600501546117329190613124565b868281518110611744576117446130d4565b602002602001018181525050858181518110611762576117626130d4565b602002602001015160155f8581526020019081526020015f2060050181905550600e54868281518110611797576117976130d4565b602002602001015111156117d557828e82815181106117b8576117b86130d4565b60209081029190910101528b6117cd816133a4565b9c5050611848565b827f33dc5cdf1e035de8a7fe16ad7a30a441d30ee51719d3f07703ee35d4348f07798388848151811061180a5761180a6130d4565b6020026020010151604051611829929190918252602082015260400190565b60405180910390a2611848565b5f838152601560205260408120600501555b600101611671565b508a15611862576118628d868d612523565b5f6013544261187191906130c1565b426013559050611882826001613124565b600f81905550817f48b735a18ed32318d316214e41387be29c52e29df4598f2b8e40fa843be3f9408e8787856040516118be94939291906133bc565b60405180910390a250505b50939e929d509b50919950969750505050505050565b601681815481106109bd575f80fd5b6060601680548060200260200160405190810160405280929190818152602001828054801561116657602002820191905f5260205f2090815481526020019060010190808311611152575050505050905090565b5f6005546013546119539190613124565b905090565b5f818152601560209081526040808320815160c08101835281546001600160a01b03908116825260018301541681850152600282018054845181870281018701865281815287969395860193909291908301828280156119d557602002820191905f5260205f20905b8154815260200190600101908083116119c1575b5050505050815260200160038201548152602001600482015481526020016005820154815250509050600e548160a001511115611a155760029150611a24565b606081015115611a2457600191505b50919050565b8060105f828254611a3b91906130c1565b9091555050601854611a57906001600160a01b031683836128d8565b816001600160a01b03167f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436482604051611a9291815260200190565b60405180910390a25050565b5f82815260156020526040812060018101546001600160a01b03163314611aef57600181015460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610665565b8215611b0357611afd611273565b50505050505b80600401549150815f03611b2a57604051637c946ed760e01b815260040160405180910390fd5b5f600482015580546001600160a01b0316611b458184611a2a565b806001600160a01b0316336001600160a01b0316867f31add0166dae59ea66bbc180e4fae85b72fc9b7b5fc7b0f7257e4721a840c96e600f548660020188604051611b92939291906133f8565b60405180910390a4505092915050565b5f805f60608060608060605f601354905060115498506005548142611bc791906130c1565b10158015611bd457505f89115b15611f2d576016548067ffffffffffffffff811115611bf557611bf5612d3b565b604051908082528060200260200182016040528015611c1e578160200160208202803683370190505b5094508067ffffffffffffffff811115611c3a57611c3a612d3b565b604051908082528060200260200182016040528015611c63578160200160208202803683370190505b5096508067ffffffffffffffff811115611c7f57611c7f612d3b565b604051908082528060200260200182016040528015611ca8578160200160208202803683370190505b5095508067ffffffffffffffff811115611cc457611cc4612d3b565b604051908082528060200260200182016040528015611cf757816020015b6060815260200190600190039081611ce25790505b5093508067ffffffffffffffff811115611d1357611d13612d3b565b604051908082528060200260200182016040528015611d3c578160200160208202803683370190505b5092505f5b81811015611f2a5760168181548110611d5c57611d5c6130d4565b905f5260205f200154868281518110611d7757611d776130d4565b6020026020010181815250505f60155f888481518110611d9957611d996130d4565b602002602001015181526020019081526020015f2090505f8490505f8260030154905081811115611dc8578091505b611dd282426130c1565b8354600285018054604080516020808402820181019092528281529495505f94611e3c946001600160a01b03169390929091830182828015611e3157602002820191905f5260205f20905b815481526020019060010190808311611e1d575b505050505084612955565b8a8781518110611e4e57611e4e6130d4565b602090810291909101015290508015611efb5781600254611e6f9190613137565b8b8f81518110611e8157611e816130d4565b6020026020010181815250508a8e81518110611e9f57611e9f6130d4565b60200260200101518d611eb29190613124565b9c50898581518110611ec657611ec66130d4565b60200260200101518c8f81518110611ee057611ee06130d4565b6020908102919091010152611ef48e6133a4565b9d50611f1b565b81888681518110611f0e57611f0e6130d4565b6020026020010181815250505b50505050806001019050611d41565b50505b509091929394959697565b601754604051633cebfa4f60e01b8152600481018590525f9182916001600160a01b0390911690633cebfa4f906024016040805180830381865afa158015611f82573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fa69190613452565b60185491935091506001600160a01b03808416911614611ff057601854604051630b80380d60e31b81526001600160a01b0391821660048201529083166024820152604401610665565b6003546bffffffffffffffffffffffff821681111561203957604051632b30b24760e21b81526bffffffffffffffffffffffff8316600482015260248101829052604401610665565b5f5b84518110156121185760175485515f916001600160a01b0316906375c1f934908a9089908690811061206f5761206f6130d4565b60200260200101516040518363ffffffff1660e01b81526004016120a392919091825263ffffffff16602082015260400190565b602060405180830381865afa1580156120be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120e29190613485565b90508281101561210f57604051632b30b24760e21b81526004810182905260248101849052604401610665565b5060010161203b565b50505050505050565b600b546001600160a01b03161561214a5760405162dc149f60e41b815260040160405180910390fd5b8051158061215a57506020810151155b8061216757506040810151155b80612174575060c0810151155b806121825750610100810151155b8061218f575060e0810151155b8061219c57506080810151155b806121a9575060a0810151155b156121c757604051637c946ed760e01b815260040160405180910390fd5b8060a001518160800151101561220357608081015160a082015160405163491a2bb160e01b815260048101929092526024820152604401610665565b60028160600151101561223957606081015160405163491a2bb160e01b8152600481019190915260026024820152604401610665565b6101a08101516001600160a01b0316158061226057506101c08101516001600160a01b0316155b1561227e5760405163d92e233d60e01b815260040160405180910390fd5b806101c001516001600160a01b03163b5f036122bf576101c081015160405163601c0c2160e01b81526001600160a01b039091166004820152602401610665565b80515f90815560208201516001556040820151600255606082015160035560a082015160045560c082015160055560e08201516006556101008201516007556101a0820151600b80546001600160a01b039283166001600160a01b0319918216179091556101c0840151600c8054919093169116179055610140820151600855610160820151600955805b8261012001515181101561241857818361012001518281518110612370576123706130d4565b6020026020010151116123b8578261012001518181518110612394576123946130d4565b6020026020010151604051632ab10b0b60e21b815260040161066591815260200190565b82610120015181815181106123cf576123cf6130d4565b602090810291909101015160148054600181810183555f929092527fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec018290559092500161234a565b506101808201515f0361243e57604051637c946ed760e01b815260040160405180910390fd5b610180820151600a5560055460808301516124599190613137565b600d5560055460a083015161246e9190613137565b600e5560e08201516020830151604084015161248a9190613137565b6124949190613137565b601255505042601355565b5f6040516323b872dd60e01b5f5284600452836024528260445260205f60645f808a5af13d15601f3d1160015f511416171691505f60605280604052508061251c5760405163abae3d6d60e01b81526001600160a01b03808716600483015280861660248301528416604482015260648101839052608401610665565b5050505050565b82515f8267ffffffffffffffff81111561253f5761253f612d3b565b604051908082528060200260200182016040528015612568578160200160208202803683370190505b5090505f8367ffffffffffffffff81111561258557612585612d3b565b6040519080825280602002602001820160405280156125ae578160200160208202803683370190505b5090505f8467ffffffffffffffff8111156125cb576125cb612d3b565b6040519080825280602002602001820160405280156125f4578160200160208202803683370190505b5090505f8567ffffffffffffffff81111561261157612611612d3b565b60405190808252806020026020018201604052801561263a578160200160208202803683370190505b5090505f8667ffffffffffffffff81111561265757612657612d3b565b604051908082528060200260200182016040528015612680578160200160208202803683370190505b5090505f805f5b888110156127dc575f8c82815181106126a2576126a26130d4565b602002602001015111156127d4578b81815181106126c2576126c26130d4565b60200260200101519150818884815181106126df576126df6130d4565b6020908102919091018101919091525f838152601590915260409020600181015488516001600160a01b0390911690899086908110612720576127206130d4565b6001600160a01b0392831660209182029290920101528154885191169088908690811061274f5761274f6130d4565b60200260200101906001600160a01b031690816001600160a01b0316815250508b8281518110612781576127816130d4565b602002602001015186858151811061279b5761279b6130d4565b602002602001018181525050818585815181106127ba576127ba6130d4565b6020908102919091010152836127cf816133a4565b945050505b600101612687565b50885b801561288a57886127ef8161349c565b99505f9050846128006001846130c1565b81518110612810576128106130d4565b6020026020010151905060168a8154811061282d5761282d6130d4565b905f5260205f20015460168281548110612849576128496130d4565b5f918252602090912001556016805480612865576128656130e8565b600190038181905f5260205f20015f9055905550806128839061349c565b90506127df565b50600f547fd19a3d42ed383465e4058c322d9411aeac76ddb8454d22e139fc99808bd56952888888886040516128c394939291906134e9565b60405180910390a25050505050505050505050565b5f60405163a9059cbb60e01b5f52836004528260245260205f60445f80895af13d15601f3d1160015f511416171691505f60605280604052508061294f5760405163abae3d6d60e01b81526001600160a01b0380861660048301523060248301528416604482015260648101839052608401610665565b50505050565b6040516001600160a01b03841660248201525f90606090829060440160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663d564c4bf60e01b179052600c5490519192505f9182916001600160a01b0316906129d1908590613535565b5f60405180830381855afa9150503d805f8114612a09576040519150601f19603f3d011682016040523d82523d5f602084013e612a0e565b606091505b5091509150818015612a215750603f8151115b8015612a38575060208151612a36919061354b565b155b15612b315780806020019051810190612a5191906132f8565b9350838787604051602401612a689392919061355e565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663184023a560e01b179052600c5490519194506001600160a01b031690612ac4908590613535565b5f60405180830381855afa9150503d805f8114612afc576040519150601f19603f3d011682016040523d82523d5f602084013e612b01565b606091505b509092509050818015612b15575080516020145b15612b315780806020019051810190612b2e9190613593565b94505b505050935093915050565b5080545f8255905f5260205f2090810190612b579190612ba3565b50565b828054828255905f5260205f20908101928215612b93579160200282015b82811115612b93578251825591602001919060010190612b78565b50612b9f929150612ba3565b5090565b5b80821115612b9f575f8155600101612ba4565b6001600160a01b0381168114612b57575f80fd5b8035612bd681612bb7565b919050565b5f805f805f60808688031215612bef575f80fd5b8535612bfa81612bb7565b94506020860135612c0a81612bb7565b935060408601359250606086013567ffffffffffffffff80821115612c2d575f80fd5b818801915088601f830112612c40575f80fd5b813581811115612c4e575f80fd5b896020828501011115612c5f575f80fd5b9699959850939650602001949392505050565b5f60208284031215612c82575f80fd5b5035919050565b5f815180845260208085019450602084015f5b83811015612cb857815187529582019590820190600101612c9c565b509495945050505050565b602081525f6001600160a01b0380845116602084015280602085015116604084015250604083015160c06060840152612cff60e0840182612c89565b905060608401516080840152608084015160a084015260a084015160c08401528091505092915050565b602081525f610a8d6020830184612c89565b634e487b7160e01b5f52604160045260245ffd5b6040516101e0810167ffffffffffffffff81118282101715612d7357612d73612d3b565b60405290565b604051610100810167ffffffffffffffff81118282101715612d7357612d73612d3b565b604051601f8201601f1916810167ffffffffffffffff81118282101715612dc657612dc6612d3b565b604052919050565b5f67ffffffffffffffff821115612de757612de7612d3b565b5060051b60200190565b5f82601f830112612e00575f80fd5b81356020612e15612e1083612dce565b612d9d565b8083825260208201915060208460051b870101935086841115612e36575f80fd5b602086015b84811015612e525780358352918301918301612e3b565b509695505050505050565b5f805f60608486031215612e6f575f80fd5b833567ffffffffffffffff80821115612e86575f80fd5b908501906101e08288031215612e9a575f80fd5b612ea2612d4f565b823581526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c083013560c082015260e083013560e08201526101008084013581830152506101208084013583811115612f0b575f80fd5b612f178a828701612df1565b91830191909152506101408381013590820152610160808401359082015261018080840135908201526101a09150612f50828401612bcb565b828201526101c09150612f64828401612bcb565b82820152809550505050612f7a60208501612bcb565b9150612f8860408501612bcb565b90509250925092565b60a081525f612fa360a0830188612c89565b6020838203818501528188518084528284019150828160051b850101838b015f5b83811015612ff257601f19878403018552612fe0838351612c89565b94860194925090850190600101612fc4565b50508681036040880152613006818b612c89565b945050505050828103606084015261301e8186612c89565b905082810360808401526130328185612c89565b98975050505050505050565b634e487b7160e01b5f52602160045260245ffd5b602081016003831061307257634e487b7160e01b5f52602160045260245ffd5b91905290565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561099c5761099c6130ad565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b838152606060208201525f6131146060830185612c89565b9050826040830152949350505050565b8082018082111561099c5761099c6130ad565b808202811582820484141761099c5761099c6130ad565b634e487b7160e01b5f52601260045260245ffd5b5f826131705761317061314e565b500490565b80516bffffffffffffffffffffffff81168114612bd6575f80fd5b8051612bd681612bb7565b805163ffffffff81168114612bd6575f80fd5b805160068110612bd6575f80fd5b5f82601f8301126131cb575f80fd5b815160206131db612e1083612dce565b8083825260208201915060208460051b8701019350868411156131fc575f80fd5b602086015b84811015612e52576132128161319b565b8352918301918301613201565b5f6020828403121561322f575f80fd5b815167ffffffffffffffff80821115613246575f80fd5b90830190610100828603121561325a575f80fd5b613262612d79565b61326b83613175565b815261327960208401613190565b6020820152604083015160408201526132946060840161319b565b60608201526132a56080840161319b565b60808201526132b660a0840161319b565b60a08201526132c760c084016131ae565b60c082015260e0830151828111156132dd575f80fd5b6132e9878286016131bc565b60e08301525095945050505050565b5f6020808385031215613309575f80fd5b825167ffffffffffffffff81111561331f575f80fd5b8301601f8101851361332f575f80fd5b805161333d612e1082612dce565b81815260059190911b8201830190838101908783111561335b575f80fd5b928401925b8284101561337957835182529284019290840190613360565b979650505050505050565b828152604060208201525f61339c6040830184612c89565b949350505050565b5f600182016133b5576133b56130ad565b5060010190565b848152608060208201525f6133d46080830186612c89565b82810360408401526133e68186612c89565b91505082606083015295945050505050565b5f60608201858352602060606020850152818654808452608086019150875f5260205f2093505f5b8181101561343c57845483526001948501949284019201613420565b5050809350505050826040830152949350505050565b5f8060408385031215613463575f80fd5b825161346e81612bb7565b915061347c60208401613175565b90509250929050565b5f60208284031215613495575f80fd5b5051919050565b5f816134aa576134aa6130ad565b505f190190565b5f815180845260208085019450602084015f5b83811015612cb85781516001600160a01b0316875295820195908201906001016134c4565b608081525f6134fb6080830187612c89565b828103602084015261350d81876134b1565b9050828103604084015261352181866134b1565b905082810360608401526133798185612c89565b5f82518060208501845e5f920191825250919050565b5f826135595761355961314e565b500690565b606081525f6135706060830186612c89565b82810360208401526135828186612c89565b915050826040830152949350505050565b5f602082840312156135a3575f80fd5b81518015158114610a8d575f80fdfea264697066735822122072ecd1722ad55173c3de0af850e7d10c36277b036879ee73341951b05ec8f40e64736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {} +} \ No newline at end of file diff --git a/operate/data/contracts/uniswap_v2_erc20/build/IUniswapV2ERC20.json b/operate/data/contracts/uniswap_v2_erc20/build/IUniswapV2ERC20.json new file mode 100644 index 0000000..01003d6 --- /dev/null +++ b/operate/data/contracts/uniswap_v2_erc20/build/IUniswapV2ERC20.json @@ -0,0 +1,693 @@ +{ + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "PERMIT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ], + "evm": { + "bytecode": { + "linkReferences": {}, + "object": "", + "opcodes": "", + "sourceMap": "" + }, + "deployedBytecode": { + "linkReferences": {}, + "object": "", + "opcodes": "", + "sourceMap": "" + } + }, + "interface": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "PERMIT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "" +} \ No newline at end of file diff --git a/operate/services/service.py b/operate/services/service.py index d465480..b5612dc 100644 --- a/operate/services/service.py +++ b/operate/services/service.py @@ -222,10 +222,11 @@ def try_update_runtime_params( skill_id=component_id.public_id, has_multiple_overrides=has_multiple_overrides, ) - if service_id is not None: - override[0]["models"]["params"]["args"][ - "on_chain_service_id" - ] = service_id + # this was causing issues + # if service_id is not None: + # override[0]["models"]["params"]["args"][ + # "on_chain_service_id" + # ] = service_id override["type"] = component_id.package_type.value override["public_id"] = str(component_id.public_id) diff --git a/pyproject.toml b/pyproject.toml index fc2433f..6b80a1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ name = "mech-quickstart" version = "0.1.0" description = "" -authors = [""] +authors = [] readme = "README.md" packages = [ { include = "operate" } diff --git a/run_service.py b/run_service.py index 53db95e..0a08591 100644 --- a/run_service.py +++ b/run_service.py @@ -24,23 +24,13 @@ import sys import time import typing as t -from dataclasses import dataclass -from pathlib import Path -import shutil -import requests -import yaml -from aea.crypto.base import LedgerApi -from aea_ledger_ethereum import EthereumApi + from dotenv import load_dotenv from halo import Halo -from termcolor import colored -from web3 import Web3 + from operate.account.user import UserAccount from operate.cli import OperateApp from operate.ledger.profiles import CONTRACTS, STAKING, OLAS -from operate.resource import LocalResource, deserialize -from operate.services.manage import ServiceManager -from operate.services.service import Service from operate.types import ( LedgerType, ServiceTemplate, @@ -49,34 +39,27 @@ ChainType, OnChainState, ) +from utils import print_title, print_section, get_local_config, get_service, ask_confirm_password, \ + handle_password_migration, print_box, wei_to_token, get_erc20_balance, CHAIN_TO_MARKETPLACE, apply_env_vars, \ + unit_to_wei, MechQuickstartConfig, OPERATE_HOME, load_api_keys, deploy_mech, generate_mech_config load_dotenv() - -def unit_to_wei(unit: float) -> int: - """Convert unit to Wei.""" - return int(unit * 1e18) - - -WALLET_TOPUP = unit_to_wei(0.005) -MASTER_SAFE_TOPUP = unit_to_wei(0.001) -SAFE_TOPUP = unit_to_wei(0.002) -AGENT_TOPUP = unit_to_wei(0.001) - +WALLET_TOPUP = unit_to_wei(0.5) +MASTER_SAFE_TOPUP = unit_to_wei(0) +SAFE_TOPUP = unit_to_wei(0) +AGENT_TOPUP = unit_to_wei(1.5) COST_OF_BOND = 1 COST_OF_STAKING = 10**20 # 100 OLAS COST_OF_BOND_STAKING = 5 * 10**19 # 50 OLAS -WARNING_ICON = colored("\u26A0", "yellow") -OPERATE_HOME = Path.cwd() / ".mech_quickstart" - CHAIN_ID_TO_METADATA = { 100: { "name": "Gnosis", "token": "xDAI", - "firstTimeTopUp": unit_to_wei(0.001), - "operationalFundReq": unit_to_wei(0.001), + "firstTimeTopUp": unit_to_wei(2), + "operationalFundReq": MASTER_SAFE_TOPUP, "usdcRequired": False, "gasParams": { # this means default values will be used @@ -86,261 +69,27 @@ def unit_to_wei(unit: float) -> int: }, } - -def estimate_priority_fee( - web3_object: Web3, - block_number: int, - default_priority_fee: t.Optional[int], - fee_history_blocks: int, - fee_history_percentile: int, - priority_fee_increase_boundary: int, -) -> t.Optional[int]: - """Estimate priority fee from base fee.""" - - if default_priority_fee is not None: - return default_priority_fee - - fee_history = web3_object.eth.fee_history( - fee_history_blocks, block_number, [fee_history_percentile] # type: ignore - ) - - # This is going to break if more percentiles are introduced in the future, - # i.e., `fee_history_percentile` param becomes a `List[int]`. - rewards = sorted( - [reward[0] for reward in fee_history.get("reward", []) if reward[0] > 0] - ) - if len(rewards) == 0: - return None - - # Calculate percentage increases from between ordered list of fees - percentage_increases = [ - ((j - i) / i) * 100 if i != 0 else 0 for i, j in zip(rewards[:-1], rewards[1:]) - ] - highest_increase = max(*percentage_increases) - highest_increase_index = percentage_increases.index(highest_increase) - - values = rewards.copy() - # If we have big increase in value, we could be considering "outliers" in our estimate - # Skip the low elements and take a new median - if ( - highest_increase > priority_fee_increase_boundary - and highest_increase_index >= len(values) // 2 - ): - values = values[highest_increase_index:] - - return values[len(values) // 2] - - -@dataclass -class MechQuickstartConfig(LocalResource): - """Local configuration.""" - - path: Path - gnosis_rpc: t.Optional[str] = None - password_migrated: t.Optional[bool] = None - use_staking: t.Optional[bool] = None - home_chain_id: t.Optional[int] = None - - @classmethod - def from_json(cls, obj: t.Dict) -> "LocalResource": - """Load LocalResource from json.""" - kwargs = {} - for pname, ptype in cls.__annotations__.items(): - if pname.startswith("_"): - continue - - # allow for optional types - is_optional_type = t.get_origin(ptype) is t.Union and type( - None - ) in t.get_args(ptype) - value = obj.get(pname, None) - if is_optional_type and value is None: - continue - - kwargs[pname] = deserialize(obj=obj[pname], otype=ptype) - return cls(**kwargs) - - -def print_box(text: str, margin: int = 1, character: str = "=") -> None: - """Print text centered within a box.""" - - lines = text.split("\n") - text_length = max(len(line) for line in lines) - length = text_length + 2 * margin - - border = character * length - margin_str = " " * margin - - print(border) - print(f"{margin_str}{text}{margin_str}") - print(border) - print() - - -def print_title(text: str) -> None: - """Print title.""" - print() - print_box(text, 4, "=") - - -def print_section(text: str) -> None: - """Print section.""" - print_box(text, 1, "-") - - -def wei_to_unit(wei: int) -> float: - """Convert Wei to unit.""" - return wei / 1e18 - - -def wei_to_token(wei: int, token: str = "xDAI") -> str: - """Convert Wei to token.""" - return f"{wei_to_unit(wei):.6f} {token}" - - -def ask_confirm_password() -> str: - password = getpass.getpass("Please enter a password: ") - confirm_password = getpass.getpass("Please confirm your password: ") - - if password == confirm_password: - return password - else: - print("Passwords do not match. Terminating.") - sys.exit(1) - - -def check_rpc(rpc_url: str) -> None: - spinner = Halo(text=f"Checking RPC...", spinner="dots") - spinner.start() - - rpc_data = { - "jsonrpc": "2.0", - "method": "eth_newFilter", - "params": ["invalid"], - "id": 1, - } - - try: - response = requests.post( - rpc_url, json=rpc_data, headers={"Content-Type": "application/json"} - ) - response.raise_for_status() - rpc_response = response.json() - except Exception as e: - print("Error: Failed to send RPC request:", e) - sys.exit(1) - - rpc_error_message = rpc_response.get("error", {}).get( - "message", "Exception processing RPC response" - ) - - if rpc_error_message == "Exception processing RPC response": - print( - "Error: The received RPC response is malformed. Please verify the RPC address and/or RPC behavior." - ) - print(" Received response:") - print(" ", rpc_response) - print("") - print("Terminating script.") - sys.exit(1) - elif rpc_error_message == "Out of requests": - print("Error: The provided RPC is out of requests.") - print("Terminating script.") - sys.exit(1) - elif ( - rpc_error_message == "The method eth_newFilter does not exist/is not available" - ): - print("Error: The provided RPC does not support 'eth_newFilter'.") - print("Terminating script.") - sys.exit(1) - elif rpc_error_message == "invalid params": - spinner.succeed("RPC checks passed.") - else: - print("Error: Unknown RPC error.") - print(" Received response:") - print(" ", rpc_response) - print("") - print("Terminating script.") - sys.exit(1) - - -def input_with_default_value(prompt: str, default_value: str) -> str: - user_input = input(f"{prompt} [{default_value}]: ") - return str(user_input) if user_input else default_value - - -def input_select_chain(options: t.List[ChainType]): - """Chose a single option from the offered ones""" - user_input = input( - f"Chose one of the following options {[option.name for option in options]}: " - ) - try: - return ChainType.from_string(user_input.upper()) - except ValueError: - print("Invalid option selected. Please try again.") - return input_select_chain(options) - - -def get_local_config() -> MechQuickstartConfig: - """Get local mech_quickstart configuration.""" - path = OPERATE_HOME / "local_config.json" - if path.exists(): - mech_quickstart_config = MechQuickstartConfig.load(path) - else: - mech_quickstart_config = MechQuickstartConfig(path) - - print_section("API Key Configuration") - - if mech_quickstart_config.home_chain_id is None: - print("Select the chain for you service") - mech_quickstart_config.home_chain_id = input_select_chain([ChainType.GNOSIS]).id - - if mech_quickstart_config.gnosis_rpc is None: - mech_quickstart_config.gnosis_rpc = input( - f"Please enter a {ChainType.from_id(mech_quickstart_config.home_chain_id).name} RPC URL: " - ) - - if mech_quickstart_config.password_migrated is None: - mech_quickstart_config.password_migrated = False - - mech_quickstart_config.store() - return mech_quickstart_config - - -def apply_env_vars(env_vars: t.Dict[str, str]) -> None: - """Apply environment variables.""" - for key, value in env_vars.items(): - if value is not None: - os.environ[key] = str(value) - - -def handle_password_migration( - operate: OperateApp, config: MechQuickstartConfig -) -> t.Optional[str]: - """Handle password migration.""" - if not config.password_migrated: - print("Add password...") - old_password, new_password = "12345", ask_confirm_password() - operate.user_account.update(old_password, new_password) - if operate.wallet_manager.exists(LedgerType.ETHEREUM): - operate.password = old_password - wallet = operate.wallet_manager.load(LedgerType.ETHEREUM) - wallet.crypto.dump(str(wallet.key_path), password=new_password) - wallet.password = new_password - wallet.store() - - config.password_migrated = True - config.store() - return new_password - return None - +# @note patching operate -> legder -> profiles.py -> staking dict for gnosis +STAKING[ChainType.GNOSIS]["mech_service"] = "0x998dEFafD094817EF329f6dc79c703f1CF18bC90" +FALLBACK_STAKING_PARAMS = { + ChainType.GNOSIS: dict( + agent_ids=[37], + service_registry=CONTRACTS[ChainType.GNOSIS]["service_registry"], # nosec + staking_token=STAKING[ChainType.GNOSIS]["mech_service"], # nosec + service_registry_token_utility=CONTRACTS[ChainType.GNOSIS][ + "service_registry_token_utility" + ], # nosec + min_staking_deposit=COST_OF_STAKING, + activity_checker="0x32B5A40B43C4eDb123c9cFa6ea97432380a38dDF", # nosec + ), +} def get_service_template(config: MechQuickstartConfig) -> ServiceTemplate: """Get the service template""" return ServiceTemplate( { "name": "mech_quickstart", - "hash": "bafybeiceat2qaz7bqrpgobj3qiubjqyzehydexku2qhe6ob4w2woaehunq", + "hash": "bafybeibx772eooap6m7cdjwfyt5pespe22i2mva24y255vw22cd5d7bfuq", "description": "The mech executes AI tasks requested on-chain and delivers the results to the requester.", "image": "https://gateway.autonolas.tech/ipfs/bafybeidzpenez565d7vp7jexfrwisa2wijzx6vwcffli57buznyyqkrceq", "service_version": "v0.1.0", @@ -350,7 +99,7 @@ def get_service_template(config: MechQuickstartConfig) -> ServiceTemplate: { "staking_program_id": "mech_service", "rpc": config.gnosis_rpc, - "nft": "", + "nft": "bafybeifgj3kackzfoq4fxjiuousm6epgwx7jbc3n2gjwzjgvtbbz7fc3su", "cost_of_bond": COST_OF_BOND, "threshold": 1, "use_staking": True, @@ -366,106 +115,6 @@ def get_service_template(config: MechQuickstartConfig) -> ServiceTemplate: } ) - -def get_erc20_balance(ledger_api: LedgerApi, token: str, account: str) -> int: - """Get ERC-20 token balance of an account.""" - web3 = t.cast(EthereumApi, ledger_api).api - - # ERC20 Token Standard Partial ABI - erc20_abi = [ - { - "constant": True, - "inputs": [{"name": "_owner", "type": "address"}], - "name": "balanceOf", - "outputs": [{"name": "balance", "type": "uint256"}], - "type": "function", - } - ] - - # Create contract instance - contract = web3.eth.contract(address=web3.to_checksum_address(token), abi=erc20_abi) - - # Get the balance of the account - balance = contract.functions.balanceOf(web3.to_checksum_address(account)).call() - - return balance - - -# @note patching operate -> legder -> profiles.py -> staking dict for gnosis -STAKING[ChainType.GNOSIS]["mech_service"] = "0x998dEFafD094817EF329f6dc79c703f1CF18bC90" -gnosis_staking_fallback = dict( - agent_ids=[43], - service_registry=CONTRACTS[ChainType.GNOSIS]["service_registry"], # nosec - staking_token=STAKING[ChainType.GNOSIS]["mech_service"], # nosec - service_registry_token_utility=CONTRACTS[ChainType.GNOSIS][ - "service_registry_token_utility" - ], # nosec - min_staking_deposit=COST_OF_STAKING, - activity_checker="0x32B5A40B43C4eDb123c9cFa6ea97432380a38dDF", # nosec -) - - -FALLBACK_STAKING_PARAMS = { - ChainType.GNOSIS: gnosis_staking_fallback, -} - - -def add_volumes(docker_compose_path: Path, host_path: str, container_path: str) -> None: - """Add volumes to the docker-compose.""" - with open(docker_compose_path, "r") as f: - docker_compose = yaml.safe_load(f) - - docker_compose["services"]["mech_quickstart_abci_0"]["volumes"].append( - f"{host_path}:{container_path}:Z" - ) - - with open(docker_compose_path, "w") as f: - yaml.dump(docker_compose, f) - - -def get_service(manager: ServiceManager, template: ServiceTemplate) -> Service: - if len(manager.json) > 0: - old_hash = manager.json[0]["hash"] - if old_hash == template["hash"]: - print(f'Loading service {template["hash"]}') - service = manager.load_or_create( - hash=template["hash"], - service_template=template, - ) - else: - print(f"Updating service from {old_hash} to " + template["hash"]) - service = manager.update_service( - old_hash=old_hash, - new_hash=template["hash"], - service_template=template, - ) - else: - print(f'Creating service {template["hash"]}') - service = manager.load_or_create( - hash=template["hash"], - service_template=template, - ) - - return service - - -def fetch_token_price(url: str, headers: dict) -> t.Optional[float]: - """Fetch the price of a token from a given URL.""" - try: - response = requests.get(url, headers=headers) - if response.status_code != 200: - print( - f"Error fetching info from url {url}. Failed with status code: {response.status_code}" - ) - return None - prices = response.json() - token = next(iter(prices)) - return prices[token].get("usd", None) - except Exception as e: - print(f"Error fetching token price: {e}") - return None - - def main() -> None: """Run service.""" @@ -650,42 +299,41 @@ def main() -> None: safe_fund_treshold=SAFE_TOPUP, safe_topup=SAFE_TOPUP, ) - - safes = { - ChainType.from_id(int(chain)).name.lower(): config.chain_data.multisig - for chain, config in service.chain_configs.items() - } home_chain_id = service.home_chain_id home_chain_type = ChainType.from_id(int(home_chain_id)) + + # deploy a mech if doesnt exist already + if not mech_quickstart_config.agent_id: + chain_config = service.chain_configs[home_chain_id] + ledger_config = chain_config.ledger_config + sftxb = manager.get_eth_safe_tx_builder(ledger_config) + # reload the service to get the latest version of it + service = get_service(manager, template) + deploy_mech(sftxb, mech_quickstart_config, service) + # Apply env cars + api_keys = load_api_keys(mech_quickstart_config) + mech_to_config = generate_mech_config(mech_quickstart_config) env_vars = { - "SAFE_CONTRACT_ADDRESSES": json.dumps(safes, separators=(",", ":")), - # "ON_CHAIN_SERVICE_ID": "34", - "RESET_PAUSE_DURATION": 10, - "MINIMUM_GAS_BALANCE": 0.02, - "DB_PATH": "/logs/mech.db", + "SERVICE_REGISTRY_ADDRESS": CONTRACTS[home_chain_type]["service_registry"], "STAKING_TOKEN_CONTRACT_ADDRESS": STAKING[home_chain_type]["mech_service"], + "MECH_MARKETPLACE_ADDRESS": CHAIN_TO_MARKETPLACE[home_chain_type], + # TODO: no way to update this atm after its provided, user is expected to update the file itself. + "API_KEYS": json.dumps(api_keys, separators=(',', ':')), + "AGENT_ID": str(mech_quickstart_config.agent_id), + # TODO this will be very unclear for the general user how to come up with + "METADATA_HASH": mech_quickstart_config.metadata_hash, + "MECH_TO_CONFIG": json.dumps(mech_to_config, separators=(',', ':')), + "ON_CHAIN_SERVICE_ID": service.chain_configs[home_chain_id].chain_data.token, } apply_env_vars(env_vars) # Build the deployment - print("Skipping local deployment") + del os.environ["MAX_FEE_PER_GAS"] + del os.environ["MAX_PRIORITY_FEE_PER_GAS"] service.deployment.build(use_docker=True, force=True, chain_id=home_chain_id) - # Add docker volumes - docker_compose_path = service.path / "deployment" / "docker-compose.yaml" - add_volumes(docker_compose_path, str(OPERATE_HOME), "/data") - - # Copy the database if they exist - database_source = Path.cwd() / "mech.db" - database_target = ( - service.path / "deployment" / "persistent_data" / "logs" / "mech.db" - ) - if database_source.is_file(): - print("Loaded a backup of the db") - shutil.copy(database_source, database_target) - # Run the deployment service.deployment.start(use_docker=True) print() diff --git a/run_service.sh b/run_service.sh old mode 100644 new mode 100755 diff --git a/stop_service.sh b/stop_service.sh old mode 100644 new mode 100755 diff --git a/utils.py b/utils.py index 5b3abe4..b0fa100 100644 --- a/utils.py +++ b/utils.py @@ -1,13 +1,32 @@ # utils.py +import getpass import json +import os +import sys +from dataclasses import dataclass from pathlib import Path from datetime import datetime from decimal import Decimal, getcontext import logging import docker +import requests +import web3.contract +from aea.crypto.base import LedgerApi +from aea_ledger_ethereum import EthereumApi +from halo import Halo +from termcolor import colored from web3 import Web3 from web3.middleware import geth_poa_middleware from enum import Enum +import typing as t + +from operate.cli import OperateApp +from operate.resource import LocalResource, deserialize +from operate.services.manage import ServiceManager +from operate.services.protocol import EthSafeTxBuilder +from operate.services.service import Service +from operate.types import ChainType, ServiceTemplate, LedgerType, ConfigurationTemplate +from operate.utils.gnosis import SafeOperation # Set decimal precision getcontext().prec = 18 @@ -15,6 +34,44 @@ # Configure logging logging.basicConfig(level=logging.INFO, format='%(message)s') + +WARNING_ICON = colored("\u26A0", "yellow") +OPERATE_HOME = Path.cwd() / ".mech_quickstart" + +@dataclass +class MechQuickstartConfig(LocalResource): + """Local configuration.""" + + path: Path + gnosis_rpc: t.Optional[str] = None + password_migrated: t.Optional[bool] = None + use_staking: t.Optional[bool] = None + api_keys_path: t.Optional[str] = None + metadata_hash: t.Optional[str] = None + agent_id: t.Optional[int] = None + mech_address: t.Optional[str] = None + home_chain_id: t.Optional[int] = None + + @classmethod + def from_json(cls, obj: t.Dict) -> "LocalResource": + """Load LocalResource from json.""" + kwargs = {} + for pname, ptype in cls.__annotations__.items(): + if pname.startswith("_"): + continue + + # allow for optional types + is_optional_type = t.get_origin(ptype) is t.Union and type( + None + ) in t.get_args(ptype) + value = obj.get(pname, None) + if is_optional_type and value is None: + continue + + kwargs[pname] = deserialize(obj=obj[pname], otype=ptype) + return cls(**kwargs) + + # Terminal color codes class ColorCode: GREEN = "\033[92m" @@ -59,14 +116,6 @@ def _print_status(key: str, value: str, message: str = "") -> None: line += f"{message}" print(line) -def wei_to_unit(wei: int) -> Decimal: - """Convert Wei to unit.""" - return Decimal(wei) / Decimal(1e18) - -def wei_to_token(wei: int, token: str = "xDAI") -> str: - """Convert Wei to token.""" - return f"{wei_to_unit(wei):.2f} {token}" - def wei_to_olas(wei: int) -> str: """Converts and formats wei to OLAS.""" return "{:.2f} OLAS".format(wei_to_unit(wei)) @@ -113,3 +162,328 @@ def _get_agent_status() -> str: except docker.errors.DockerException as e: print(f"Error: Docker exception occurred - {str(e)}") return _color_string("Error", ColorCode.RED) + +def print_box(text: str, margin: int = 1, character: str = "=") -> None: + """Print text centered within a box.""" + + lines = text.split("\n") + text_length = max(len(line) for line in lines) + length = text_length + 2 * margin + + border = character * length + margin_str = " " * margin + + print(border) + print(f"{margin_str}{text}{margin_str}") + print(border) + print() + + +def print_title(text: str) -> None: + """Print title.""" + print() + print_box(text, 4, "=") + + +def print_section(text: str) -> None: + """Print section.""" + print_box(text, 1, "-") + + +def wei_to_unit(wei: int) -> float: + """Convert Wei to unit.""" + return wei / 1e18 + + +def wei_to_token(wei: int, token: str = "xDAI") -> str: + """Convert Wei to token.""" + return f"{wei_to_unit(wei):.6f} {token}" + + +def ask_confirm_password() -> str: + password = getpass.getpass("Please enter a password: ") + confirm_password = getpass.getpass("Please confirm your password: ") + + if password == confirm_password: + return password + else: + print("Passwords do not match. Terminating.") + sys.exit(1) + + +def check_rpc(rpc_url: str) -> None: + spinner = Halo(text=f"Checking RPC...", spinner="dots") + spinner.start() + + rpc_data = { + "jsonrpc": "2.0", + "method": "eth_newFilter", + "params": ["invalid"], + "id": 1, + } + + try: + response = requests.post( + rpc_url, json=rpc_data, headers={"Content-Type": "application/json"} + ) + response.raise_for_status() + rpc_response = response.json() + except Exception as e: + print("Error: Failed to send RPC request:", e) + sys.exit(1) + + rpc_error_message = rpc_response.get("error", {}).get( + "message", "Exception processing RPC response" + ) + + if rpc_error_message == "Exception processing RPC response": + print( + "Error: The received RPC response is malformed. Please verify the RPC address and/or RPC behavior." + ) + print(" Received response:") + print(" ", rpc_response) + print("") + print("Terminating script.") + sys.exit(1) + elif rpc_error_message == "Out of requests": + print("Error: The provided RPC is out of requests.") + print("Terminating script.") + sys.exit(1) + elif ( + rpc_error_message == "The method eth_newFilter does not exist/is not available" + ): + print("Error: The provided RPC does not support 'eth_newFilter'.") + print("Terminating script.") + sys.exit(1) + elif rpc_error_message == "invalid params": + spinner.succeed("RPC checks passed.") + else: + print("Error: Unknown RPC error.") + print(" Received response:") + print(" ", rpc_response) + print("") + print("Terminating script.") + sys.exit(1) + + +def input_with_default_value(prompt: str, default_value: str) -> str: + user_input = input(f"{prompt} [{default_value}]: ") + return str(user_input) if user_input else default_value + + +def input_select_chain(options: t.List[ChainType]): + """Chose a single option from the offered ones""" + user_input = input( + f"Chose one of the following options {[option.name for option in options]}: " + ) + try: + return ChainType.from_string(user_input.upper()) + except ValueError: + print("Invalid option selected. Please try again.") + return input_select_chain(options) + + +def load_api_keys(local_config: MechQuickstartConfig) -> t.Dict[str, t.List[str]]: + """Load API keys from a file.""" + try: + path = OPERATE_HOME / local_config.api_keys_path + with open(path, "r") as f: + api_keys = json.load(f) + except FileNotFoundError: + print(f"Error: API keys file not found at {local_config.api_keys_path}") + sys.exit(1) + except json.JSONDecodeError: + print("Error: API keys file contains invalid JSON.") + sys.exit(1) + return api_keys + + +def get_local_config() -> MechQuickstartConfig: + """Get local mech_quickstart configuration.""" + path = OPERATE_HOME / "local_config.json" + if path.exists(): + mech_quickstart_config = MechQuickstartConfig.load(path) + else: + mech_quickstart_config = MechQuickstartConfig(path) + + print_section("API Key Configuration") + + if mech_quickstart_config.home_chain_id is None: + print("Select the chain for you service") + mech_quickstart_config.home_chain_id = input_select_chain([ChainType.GNOSIS]).id + + if mech_quickstart_config.gnosis_rpc is None: + mech_quickstart_config.gnosis_rpc = input( + f"Please enter a {ChainType.from_id(mech_quickstart_config.home_chain_id).name} RPC URL: " + ) + + if mech_quickstart_config.password_migrated is None: + mech_quickstart_config.password_migrated = False + + if mech_quickstart_config.api_keys_path is None: + mech_quickstart_config.api_keys_path = input_with_default_value("Please provide the path to your api_keys.json file", "../.api_keys.json") + + # test that api key path exists and is valid json + load_api_keys(mech_quickstart_config) + + if mech_quickstart_config.metadata_hash is None: + # TODO: default value is not a good idea here, we need to think of better ways to do this. + mech_quickstart_config.metadata_hash = input_with_default_value("Please provide the metadata hash", "f01701220caa53607238e340da63b296acab232c18a48e954f0af6ff2b835b2d93f1962f0") + + mech_quickstart_config.store() + return mech_quickstart_config + + +def apply_env_vars(env_vars: t.Dict[str, str]) -> None: + """Apply environment variables.""" + for key, value in env_vars.items(): + if value is not None: + os.environ[key] = str(value) + + +def handle_password_migration( + operate: OperateApp, config: MechQuickstartConfig +) -> t.Optional[str]: + """Handle password migration.""" + if not config.password_migrated: + print("Add password...") + old_password, new_password = "12345", ask_confirm_password() + operate.user_account.update(old_password, new_password) + if operate.wallet_manager.exists(LedgerType.ETHEREUM): + operate.password = old_password + wallet = operate.wallet_manager.load(LedgerType.ETHEREUM) + wallet.crypto.dump(str(wallet.key_path), password=new_password) + wallet.password = new_password + wallet.store() + + config.password_migrated = True + config.store() + return new_password + return None + + +def get_erc20_balance(ledger_api: LedgerApi, token: str, account: str) -> int: + """Get ERC-20 token balance of an account.""" + web3 = t.cast(EthereumApi, ledger_api).api + + # ERC20 Token Standard Partial ABI + erc20_abi = [ + { + "constant": True, + "inputs": [{"name": "_owner", "type": "address"}], + "name": "balanceOf", + "outputs": [{"name": "balance", "type": "uint256"}], + "type": "function", + } + ] + + # Create contract instance + contract = web3.eth.contract(address=web3.to_checksum_address(token), abi=erc20_abi) + + # Get the balance of the account + balance = contract.functions.balanceOf(web3.to_checksum_address(account)).call() + + return balance + + + +def get_service(manager: ServiceManager, template: ServiceTemplate) -> Service: + if len(manager.json) > 0: + old_hash = manager.json[0]["hash"] + if old_hash == template["hash"]: + print(f'Loading service {template["hash"]}') + service = manager.load_or_create( + hash=template["hash"], + service_template=template, + ) + else: + print(f"Updating service from {old_hash} to " + template["hash"]) + service = manager.update_service( + old_hash=old_hash, + new_hash=template["hash"], + service_template=template, + ) + else: + print(f'Creating service {template["hash"]}') + service = manager.load_or_create( + hash=template["hash"], + service_template=template, + ) + + return service + + +def unit_to_wei(unit: float) -> int: + """Convert unit to Wei.""" + return int(unit * 1e18) + + +CHAIN_TO_MARKETPLACE = { + ChainType.GNOSIS: "0x4554fE75c1f5576c1d7F765B2A036c199Adae329", +} + +CHAIN_TO_AGENT_FACTORY = { + ChainType.GNOSIS: "0x6D8CbEbCAD7397c63347D44448147Db05E7d17B0", +} + +def fetch_token_price(url: str, headers: dict) -> t.Optional[float]: + """Fetch the price of a token from a given URL.""" + try: + response = requests.get(url, headers=headers) + if response.status_code != 200: + print( + f"Error fetching info from url {url}. Failed with status code: {response.status_code}" + ) + return None + prices = response.json() + token = next(iter(prices)) + return prices[token].get("usd", None) + except Exception as e: + print(f"Error fetching token price: {e}") + return None + +def deploy_mech(sftxb: EthSafeTxBuilder, local_config: MechQuickstartConfig, service: Service) -> None: + """Deploy the Mech service.""" + print_section("Creating a new Mech On Chain") + chain_type = ChainType.from_id(int(local_config.home_chain_id)) + path = OPERATE_HOME / Path("../contracts/MechAgentFactory.json") + abi = json.loads(path.read_text())["abi"] + instance = web3.Web3() + + mech_marketplace_address = CHAIN_TO_MARKETPLACE[chain_type] + # 0.01xDAI hardcoded for price + # better to be configurable and part of local config + mech_request_price = unit_to_wei(0.01) + contract = instance.eth.contract(address=Web3.to_checksum_address(mech_marketplace_address), abi=abi) + data = contract.encodeABI("create", args=[ + service.chain_configs[service.home_chain_id].chain_data.multisig, + bytes.fromhex(local_config.metadata_hash.lstrip("f01701220")), + mech_request_price, + mech_marketplace_address + ]) + tx_dict = { + "to": CHAIN_TO_AGENT_FACTORY[chain_type], + "data": data, + "value": 0, + "operation": SafeOperation.CALL, + } + receipt = sftxb.new_tx().add(tx_dict).settle() + event = contract.events.CreateMech().process_receipt(receipt)[0] + mech_address, agent_id = event["args"]["mech"], event["args"]["agentId"] + print(f"Mech address: {mech_address}") + print(f"Agent ID: {agent_id}") + + local_config.mech_address = mech_address + local_config.agent_id = agent_id + local_config.store() + +def generate_mech_config(local_config: MechQuickstartConfig) -> dict: + """Generate the Mech configuration.""" + mech_to_config = { + local_config.mech_address: { + "use_dynamic_pricing": False, + "is_marketplace_mech": True, + } + } + return mech_to_config +