Skip to content

Commit

Permalink
Update operator rewards (#164)
Browse files Browse the repository at this point in the history
* Update operator rewards calc

Signed-off-by: cyc60 <[email protected]>

* Remove partner rewards

Signed-off-by: cyc60 <[email protected]>

* Update operator addresses

Signed-off-by: cyc60 <[email protected]>

---------

Signed-off-by: cyc60 <[email protected]>
  • Loading branch information
cyc60 authored Dec 16, 2024
1 parent 8fed0dc commit 56d9540
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 215 deletions.
26 changes: 8 additions & 18 deletions oracle/networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand All @@ -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(
Expand Down Expand Up @@ -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",
Expand All @@ -140,7 +135,6 @@
SYNC_PERIOD=timedelta(days=1),
IS_POA=False,
DEPOSIT_TOKEN_SYMBOL="ETH",
VALIDATORS_SPLIT={},
),
GOERLI: dict(
STAKEWISE_SUBGRAPH_URLS=config(
Expand Down Expand Up @@ -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"),
Expand All @@ -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(
Expand Down Expand Up @@ -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",
Expand All @@ -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(
Expand Down Expand Up @@ -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"),
Expand All @@ -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,
},
),
}
28 changes: 0 additions & 28 deletions oracle/oracle/common/graphql_queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
"""
)
166 changes: 12 additions & 154 deletions oracle/oracle/distributor/common/eth1.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down
16 changes: 3 additions & 13 deletions oracle/oracle/distributor/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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: {
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion oracle/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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="")
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>"]
license = "AGPL-3.0-only"
Expand Down

0 comments on commit 56d9540

Please sign in to comment.