From 56d95402eaf89b8a5a18a4ef23b55c567ee0c195 Mon Sep 17 00:00:00 2001 From: Alexander Sysoev Date: Mon, 16 Dec 2024 17:12:17 +0300 Subject: [PATCH] Update operator rewards (#164) * Update operator rewards calc Signed-off-by: cyc60 * Remove partner rewards Signed-off-by: cyc60 * Update operator addresses Signed-off-by: cyc60 --------- Signed-off-by: cyc60 --- oracle/networks.py | 26 ++-- oracle/oracle/common/graphql_queries.py | 28 ---- oracle/oracle/distributor/common/eth1.py | 166 ++--------------------- oracle/oracle/distributor/controller.py | 16 +-- oracle/settings.py | 2 +- pyproject.toml | 2 +- 6 files changed, 25 insertions(+), 215 deletions(-) diff --git a/oracle/networks.py b/oracle/networks.py index 8bd8452..17153dc 100644 --- a/oracle/networks.py +++ b/oracle/networks.py @@ -53,8 +53,8 @@ "0x144a98cb1CdBb23610501fE6108858D9B7D24934" ), ORACLE_PRIVATE_KEY=config("ORACLE_PRIVATE_KEY", default=""), - ORACLE_STAKEWISE_OPERATOR=Web3.toChecksumAddress( - "0x5fc60576b92c5ce5c341c43e3b2866eb9e0cddd1" + OPERATOR_ADDRESS=Web3.toChecksumAddress( + "0xf330b5fE72E91d1a3782E65eED876CF3624c7802" ), WITHDRAWALS_GENESIS_EPOCH=194048, AWS_BUCKET_NAME=config("AWS_BUCKET_NAME", default="oracle-votes-mainnet"), @@ -75,11 +75,6 @@ SYNC_PERIOD=timedelta(days=1), IS_POA=False, DEPOSIT_TOKEN_SYMBOL="ETH", - VALIDATORS_SPLIT={ - Web3.toChecksumAddress("0xfe26832d3580e0ade4813f9e60e7c17b45e92cba"): 64, - Web3.toChecksumAddress("0x59ecf48345a221e0731e785ed79ed40d0a94e2a5"): 63, - Web3.toChecksumAddress("0x01f26d7f195a37d368cb772ed75ef70dd29700f5"): 64, - }, ), HARBOUR_MAINNET: dict( STAKEWISE_SUBGRAPH_URLS=config( @@ -117,7 +112,7 @@ "0x6C7692dB59FDC7A659208EEE57C2c876aE54a448" ), ORACLE_PRIVATE_KEY=config("ORACLE_PRIVATE_KEY", default=""), - ORACLE_STAKEWISE_OPERATOR=EMPTY_ADDR_HEX, + OPERATOR_ADDRESS=EMPTY_ADDR_HEX, WITHDRAWALS_GENESIS_EPOCH=194048, AWS_BUCKET_NAME=config( "AWS_BUCKET_NAME", @@ -140,7 +135,6 @@ SYNC_PERIOD=timedelta(days=1), IS_POA=False, DEPOSIT_TOKEN_SYMBOL="ETH", - VALIDATORS_SPLIT={}, ), GOERLI: dict( STAKEWISE_SUBGRAPH_URLS=config( @@ -178,7 +172,7 @@ "0x1867c96601bc5fE24F685d112314B8F3Fe228D5A" ), ORACLE_PRIVATE_KEY=config("ORACLE_PRIVATE_KEY", default=""), - ORACLE_STAKEWISE_OPERATOR=EMPTY_ADDR_HEX, + OPERATOR_ADDRESS=EMPTY_ADDR_HEX, WITHDRAWALS_GENESIS_EPOCH=162304, AWS_BUCKET_NAME=config("AWS_BUCKET_NAME", default="oracle-votes-goerli"), AWS_REGION=config("AWS_REGION", default="eu-central-1"), @@ -198,7 +192,6 @@ SYNC_PERIOD=timedelta(hours=1), IS_POA=True, DEPOSIT_TOKEN_SYMBOL="ETH", - VALIDATORS_SPLIT={}, ), HARBOUR_GOERLI: dict( STAKEWISE_SUBGRAPH_URLS=config( @@ -236,7 +229,7 @@ "0x66D6c253084d8d51c7CFfDb3C188A0b53D998a3d" ), ORACLE_PRIVATE_KEY=config("ORACLE_PRIVATE_KEY", default=""), - ORACLE_STAKEWISE_OPERATOR=EMPTY_ADDR_HEX, + OPERATOR_ADDRESS=EMPTY_ADDR_HEX, WITHDRAWALS_GENESIS_EPOCH=162304, AWS_BUCKET_NAME=config( "AWS_BUCKET_NAME", @@ -259,7 +252,6 @@ SYNC_PERIOD=timedelta(days=1), IS_POA=True, DEPOSIT_TOKEN_SYMBOL="ETH", - VALIDATORS_SPLIT={}, ), GNOSIS_CHAIN: dict( STAKEWISE_SUBGRAPH_URLS=config( @@ -297,7 +289,9 @@ "0x8737f638E9af54e89ed9E1234dbC68B115CD169e" ), ORACLE_PRIVATE_KEY=config("ORACLE_PRIVATE_KEY", default=""), - ORACLE_STAKEWISE_OPERATOR=EMPTY_ADDR_HEX, + OPERATOR_ADDRESS=Web3.toChecksumAddress( + "0x6Da6B1EfCCb7216078B9004535941b71EeD30b0F" + ), WITHDRAWALS_GENESIS_EPOCH=648704, AWS_BUCKET_NAME=config("AWS_BUCKET_NAME", default="oracle-votes-gnosis"), AWS_REGION=config("AWS_REGION", default="eu-north-1"), @@ -317,9 +311,5 @@ SYNC_PERIOD=timedelta(days=1), IS_POA=True, DEPOSIT_TOKEN_SYMBOL="GNO", - VALIDATORS_SPLIT={ - Web3.toChecksumAddress("0x59ecf48345a221e0731e785ed79ed40d0a94e2a5"): 4971, - Web3.toChecksumAddress("0xf37c8f35fc820354b402054699610c098559ae44"): 4971, - }, ), } diff --git a/oracle/oracle/common/graphql_queries.py b/oracle/oracle/common/graphql_queries.py index 7c13e11..80eadba 100644 --- a/oracle/oracle/common/graphql_queries.py +++ b/oracle/oracle/common/graphql_queries.py @@ -341,31 +341,3 @@ } """ ) - -OPERATORS_REWARDS_QUERY = gql( - """ - query getOperatorsRewards($block_number: Int) { - operators(block: { number: $block_number }) { - id - validatorsCount - revenueShare - distributorPoints - updatedAtBlock - } - } -""" -) - -PARTNERS_QUERY = gql( - """ - query getPartners($block_number: Int) { - partners(block: { number: $block_number }) { - id - contributedAmount - revenueShare - distributorPoints - updatedAtBlock - } - } -""" -) diff --git a/oracle/oracle/distributor/common/eth1.py b/oracle/oracle/distributor/common/eth1.py index 3576cc2..b2df673 100644 --- a/oracle/oracle/distributor/common/eth1.py +++ b/oracle/oracle/distributor/common/eth1.py @@ -14,8 +14,6 @@ DISABLED_STAKER_ACCOUNTS_QUERY, DISTRIBUTOR_CLAIMED_ACCOUNTS_QUERY, ONE_TIME_DISTRIBUTIONS_QUERY, - OPERATORS_REWARDS_QUERY, - PARTNERS_QUERY, PERIODIC_DISTRIBUTIONS_QUERY, ) from oracle.oracle.distributor.common.ipfs import get_one_time_rewards_allocations @@ -162,171 +160,31 @@ async def get_distributor_claimed_accounts( async def get_operators_rewards( - network: str, - from_block: BlockNumber, - to_block: BlockNumber, total_reward: Wei, + operator_address: ChecksumAddress, reward_token_address: ChecksumAddress, - validators_split: dict, ) -> Tuple[Rewards, Wei]: - """Fetches operators rewards.""" - result: Dict = await execute_sw_gql_query( - network=network, - query=OPERATORS_REWARDS_QUERY, - variables=dict( - block_number=to_block, - ), - ) - operators = result["operators"] - - # process operators - points: Dict[ChecksumAddress, int] = {} - total_points = 0 - total_validators = 0 - for operator in operators: - account = Web3.toChecksumAddress(operator["id"]) - if account == EMPTY_ADDR_HEX: - continue - - validators_count = int(operator["validatorsCount"]) + validators_split.get( - account, 0 - ) - total_validators += validators_count - - revenue_share = int(operator["revenueShare"]) - prev_account_points = int(operator["distributorPoints"]) - updated_at_block = BlockNumber(int(operator["updatedAtBlock"])) - if from_block > updated_at_block: - updated_at_block = from_block - prev_account_points = 0 - - account_points = prev_account_points + ( - validators_count * revenue_share * (to_block - updated_at_block) - ) - if account_points <= 0: - continue - - points[account] = points.get(account, 0) + account_points - total_points += account_points - - if total_validators <= 0: + """Send half of rewards to a single operator address.""" + if operator_address == EMPTY_ADDR_HEX: + logger.error("Invalid operator address") return {}, total_reward - operators_reward = Wei( - (total_reward * total_points) - // (total_validators * 10000 * (to_block - from_block)) - ) + operators_reward = Wei(total_reward // 2) + if operators_reward <= 0: return {}, total_reward operators_reward = min(total_reward, operators_reward) - rewards = calculate_points_based_rewards( - total_reward=operators_reward, - points=points, - total_points=total_points, - reward_token=reward_token_address, - ) - - return rewards, Wei(total_reward - operators_reward) - - -async def get_partners_rewards( - network: str, - from_block: BlockNumber, - to_block: BlockNumber, - total_reward: Wei, - reward_token_address: ChecksumAddress, -) -> Tuple[Rewards, Wei]: - """Fetches partners rewards.""" - result: Dict = await execute_sw_gql_query( - network=network, - query=PARTNERS_QUERY, - variables=dict( - block_number=to_block, - ), - ) - partners = result["partners"] - - # process partners - points: Dict[ChecksumAddress, int] = {} - total_points = 0 - total_contributed = 0 - for partner in partners: - account = Web3.toChecksumAddress(partner["id"]) - if account == EMPTY_ADDR_HEX: - continue - - contributed_amount = Wei(int(partner["contributedAmount"])) - total_contributed += contributed_amount - - revenue_share = int(partner["revenueShare"]) - prev_account_points = int(partner["distributorPoints"]) - updated_at_block = BlockNumber(int(partner["updatedAtBlock"])) - if from_block > updated_at_block: - updated_at_block = from_block - prev_account_points = 0 - - account_points = prev_account_points + ( - contributed_amount * revenue_share * (to_block - updated_at_block) - ) - if account_points <= 0: - continue - - points[account] = account_points - total_points += account_points - - if total_contributed <= 0: - return {}, total_reward - - partners_reward = Wei( - (total_reward * total_points) - // (total_contributed * 10000 * (to_block - from_block)) - ) - if partners_reward <= 0: - return {}, total_reward - partners_reward = min(total_reward, partners_reward) - rewards = calculate_points_based_rewards( - total_reward=partners_reward, - points=points, - total_points=total_points, + rewards: Rewards = {} + DistributorRewards.add_value( + rewards=rewards, + to=operator_address, reward_token=reward_token_address, + amount=operators_reward, ) - return rewards, Wei(total_reward - partners_reward) - - -def calculate_points_based_rewards( - total_reward: int, - points: Dict[ChecksumAddress, int], - total_points: int, - reward_token: ChecksumAddress, -) -> Rewards: - """Calculates points based rewards.""" - if total_reward <= 0 or total_points <= 0: - return {} - - rewards: Rewards = {} - last_account_index = len(points) - 1 - distributed = 0 - for i, account in enumerate(points): - if i == last_account_index: - reward = total_reward - distributed - else: - reward = (total_reward * points[account]) // total_points - - if reward <= 0: - continue - - DistributorRewards.add_value( - rewards=rewards, - to=account, - reward_token=reward_token, - amount=reward, - ) - distributed += reward - - return rewards + return rewards, Wei(total_reward - operators_reward) async def get_one_time_rewards( diff --git a/oracle/oracle/distributor/controller.py b/oracle/oracle/distributor/controller.py index 3629c3b..0d78ade 100644 --- a/oracle/oracle/distributor/controller.py +++ b/oracle/oracle/distributor/controller.py @@ -14,7 +14,6 @@ get_distributor_claimed_accounts, get_one_time_rewards, get_operators_rewards, - get_partners_rewards, get_periodic_allocations, ) from oracle.oracle.distributor.common.merkle_tree import calculate_merkle_root @@ -163,20 +162,11 @@ async def process(self, voting_params: DistributorVotingParameters) -> None: protocol_reward = voting_params["protocol_reward"] operators_rewards, left_reward = await get_operators_rewards( - network=NETWORK, - from_block=from_block, - to_block=to_block, total_reward=protocol_reward, reward_token_address=NETWORK_CONFIG["REWARD_TOKEN_CONTRACT_ADDRESS"], - validators_split=NETWORK_CONFIG["VALIDATORS_SPLIT"], - ) - partners_rewards, left_reward = await get_partners_rewards( - network=NETWORK, - from_block=from_block, - to_block=to_block, - total_reward=left_reward, - reward_token_address=NETWORK_CONFIG["REWARD_TOKEN_CONTRACT_ADDRESS"], + operator_address=NETWORK_CONFIG["OPERATOR_ADDRESS"], ) + if left_reward > 0: fallback_rewards: Rewards = { self.distributor_fallback_address: { @@ -188,7 +178,7 @@ async def process(self, voting_params: DistributorVotingParameters) -> None: rewards2=fallback_rewards, ) - for rewards in [operators_rewards, partners_rewards]: + for rewards in [operators_rewards]: final_rewards = DistributorRewards.merge_rewards(final_rewards, rewards) # merge final rewards with unclaimed rewards diff --git a/oracle/settings.py b/oracle/settings.py index 95ac118..76f125e 100644 --- a/oracle/settings.py +++ b/oracle/settings.py @@ -34,7 +34,7 @@ IPFS_FETCH_ENDPOINTS = config( "IPFS_FETCH_ENDPOINTS", cast=Csv(), - default="http://cloudflare-ipfs.com,https://ipfs.io,https://gateway.pinata.cloud", + default="https://ipfs.io,https://gateway.pinata.cloud", ) LOCAL_IPFS_CLIENT_ENDPOINT = config("LOCAL_IPFS_CLIENT_ENDPOINT", default="") diff --git a/pyproject.toml b/pyproject.toml index ca8d29c..2cd5d48 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "oracle" -version = "3.3.1" +version = "3.4.0" description = "StakeWise Oracles are responsible for submitting off-chain data." authors = ["Dmitri Tsumak "] license = "AGPL-3.0-only"