Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OCT-1837 & OCT-1838: Upgrade metrics pie chart for unused MR #383

Merged
merged 8 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions backend/app/engine/octant_rewards/leftover/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ class Leftover(ABC):
@abstractmethod
def calculate_leftover(self, payload: LeftoverPayload) -> int:
pass

def extract_unused_matched_rewards(self, *args, **kwargs) -> int:
return 0
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,14 @@ def calculate_leftover(self, payload: LeftoverPayload) -> int:
- payload.total_withdrawals
+ unused_matched_rewards
)

def extract_unused_matched_rewards(self, leftover, payload) -> int:
extra_individual_rewards = int(payload.ppf / 2)
return (
leftover
- payload.staking_proceeds
+ payload.operational_cost
+ payload.community_fund
+ extra_individual_rewards
+ payload.total_withdrawals
)
4 changes: 4 additions & 0 deletions backend/app/infrastructure/routes/epochs.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ def get(self):
required=False,
description="Community fund for the given epoch. It's calculated from staking proceeds directly.",
),
"donatedToProjects": fields.String(
required=False,
description="The amount of funds donated to projects. Includes MR and allocations.",
),
},
)

Expand Down
2 changes: 2 additions & 0 deletions backend/app/modules/dto.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class OctantRewardsDTO(JSONWizard):
# Data available starting from Epoch 3
ppf: Optional[int] = None
community_fund: Optional[int] = None
# Added after moving metrics from FE to BE
donated_to_projects: Optional[int] = None


@dataclass(frozen=True)
Expand Down
23 changes: 23 additions & 0 deletions backend/app/modules/octant_rewards/general/service/finalized.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from app.infrastructure import database
from app.modules.dto import OctantRewardsDTO
from app.pydantic import Model
from app.engine.octant_rewards.leftover import LeftoverPayload


class FinalizedOctantRewards(Model):
Expand All @@ -15,6 +16,27 @@ def get_octant_rewards(self, context: Context) -> OctantRewardsDTO:
context.epoch_details.epoch_num
)

leftover_payload = LeftoverPayload(
staking_proceeds=int(pending_snapshot.eth_proceeds),
operational_cost=int(pending_snapshot.operational_cost),
community_fund=pending_snapshot.validated_community_fund,
ppf=pending_snapshot.validated_ppf,
total_withdrawals=int(finalized_snapshot.total_withdrawals),
)

unused_matched_rewards = context.epoch_settings.octant_rewards.leftover.extract_unused_matched_rewards(
int(finalized_snapshot.leftover), leftover_payload
)

allocations_sum = database.allocations.get_alloc_sum_by_epoch(
context.epoch_details.epoch_num
)
donated_to_projects = (
int(finalized_snapshot.matched_rewards)
- unused_matched_rewards
+ allocations_sum
aziolek marked this conversation as resolved.
Show resolved Hide resolved
)

return OctantRewardsDTO(
staking_proceeds=int(pending_snapshot.eth_proceeds),
locked_ratio=Decimal(pending_snapshot.locked_ratio),
Expand All @@ -28,6 +50,7 @@ def get_octant_rewards(self, context: Context) -> OctantRewardsDTO:
total_withdrawals=int(finalized_snapshot.total_withdrawals),
ppf=pending_snapshot.validated_ppf,
community_fund=pending_snapshot.validated_community_fund,
donated_to_projects=donated_to_projects,
)

def get_leverage(self, context: Context) -> float:
Expand Down
35 changes: 25 additions & 10 deletions backend/app/modules/octant_rewards/general/service/pending.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ class ProjectRewards(Protocol):
def get_finalized_project_rewards(
self,
context: Context,
allocations: list[AllocationDTO],
all_projects: list[str],
allocations: List[AllocationDTO],
all_projects: List[str],
matched_rewards: int,
) -> FinalizedProjectRewards:
...
Expand All @@ -51,6 +51,7 @@ def get_octant_rewards(self, context: Context) -> OctantRewardsDTO:
context.epoch_details.epoch_num
)
matched_rewards = self.octant_matched_rewards.get_matched_rewards(context)
project_rewards = self._get_project_rewards(context, matched_rewards)

return OctantRewardsDTO(
staking_proceeds=int(pending_snapshot.eth_proceeds),
Expand All @@ -63,7 +64,10 @@ def get_octant_rewards(self, context: Context) -> OctantRewardsDTO:
ppf=pending_snapshot.validated_ppf,
matched_rewards=matched_rewards,
patrons_rewards=self.patrons_mode.get_patrons_rewards(context),
leftover=self.get_leftover(context, pending_snapshot, matched_rewards),
leftover=self._get_leftover(
context, pending_snapshot, matched_rewards, project_rewards
),
donated_to_projects=self._get_donated_to_projects(project_rewards),
)

def get_matched_rewards(self, context: Context) -> int:
Expand All @@ -79,19 +83,14 @@ def get_leverage(self, context: Context) -> float:
matched_rewards, allocations_sum
)

def get_leftover(
def _get_leftover(
self,
context: Context,
pending_snapshot: PendingEpochSnapshot,
matched_rewards: int,
project_rewards: FinalizedProjectRewards,
) -> int:
allocations = database.allocations.get_all_with_uqs(
context.epoch_details.epoch_num
)
_, user_rewards = self.user_rewards.get_claimed_rewards(context)
project_rewards = self.project_rewards.get_finalized_project_rewards(
context, allocations, context.projects_details.projects, matched_rewards
)

return context.epoch_settings.octant_rewards.leftover.calculate_leftover(
LeftoverPayload(
Expand All @@ -106,3 +105,19 @@ def get_leftover(
used_matched_rewards=sum(r.matched for r in project_rewards.rewards),
)
)

def _get_donated_to_projects(self, project_rewards: FinalizedProjectRewards) -> int:
total_user_donations_with_used_matched_rewards = sum(
r.amount for r in project_rewards.rewards
)

return total_user_donations_with_used_matched_rewards

def _get_project_rewards(self, context: Context, matched_rewards: int):
allocations = database.allocations.get_all_with_uqs(
context.epoch_details.epoch_num
)
project_rewards = self.project_rewards.get_finalized_project_rewards(
context, allocations, context.projects_details.projects, matched_rewards
)
return project_rewards
6 changes: 4 additions & 2 deletions backend/app/modules/projects/rewards/service/finalizing.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import List

from app.context.manager import Context
from app.modules.common.project_rewards import get_projects_rewards, AllocationsPayload
from app.modules.dto import AllocationDTO, ProjectAccountFundsDTO
Expand All @@ -9,8 +11,8 @@ class FinalizingProjectRewards(Model):
def get_finalized_project_rewards(
self,
context: Context,
allocations: list[AllocationDTO],
all_projects: list[str],
allocations: List[AllocationDTO],
all_projects: List[str],
matched_rewards: int,
) -> FinalizedProjectRewards:
allocations_payload = AllocationsPayload(
Expand Down
33 changes: 12 additions & 21 deletions backend/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@
import json
import os
import time
import urllib.request
import urllib.error
import urllib.request
from unittest.mock import MagicMock, Mock

import gql
from gql.transport.exceptions import TransportQueryError
import pytest
from flask import current_app
from flask import g as request_context
from flask.testing import FlaskClient
from gql.transport.exceptions import TransportQueryError
from requests import RequestException
from web3 import Web3

from app import create_app
from app.engine.user.effective_deposit import DepositEvent, EventType, UserDeposit
from app.exceptions import ExternalApiException
from app.extensions import db, deposits, glm, gql_factory, w3, vault, epochs
from app.infrastructure import database
from app.infrastructure import Client as GQLClient
from app.infrastructure import database
from app.infrastructure.contracts.epochs import Epochs
from app.infrastructure.contracts.erc20 import ERC20
from app.infrastructure.contracts.projects import Projects
Expand Down Expand Up @@ -1237,10 +1237,14 @@ def mock_users_db(app, user_accounts):

@pytest.fixture(scope="function")
def mock_pending_epoch_snapshot_db_since_epoch3(
app, mock_users_db, ppf=PPF, cf=COMMUNITY_FUND
app,
mock_users_db,
ppf=PPF,
cf=COMMUNITY_FUND,
epoch=MOCKED_EPOCH_NO_AFTER_OVERHAUL,
):
create_pending_snapshot(
epoch_nr=MOCKED_EPOCH_NO_AFTER_OVERHAUL,
epoch_nr=epoch,
mock_users_db=mock_users_db,
optional_ppf=ppf,
optional_cf=cf,
Expand Down Expand Up @@ -1268,22 +1272,9 @@ def mock_finalized_epoch_snapshot_db_since_epoch3(app, user_accounts):


@pytest.fixture(scope="function")
def mock_finalized_epoch_snapshot_db(app, user_accounts):
database.finalized_epoch_snapshot.save_snapshot(
MOCKED_FINALIZED_EPOCH_NO,
MATCHED_REWARDS,
NO_PATRONS_REWARDS,
LEFTOVER,
total_withdrawals=TOTAL_WITHDRAWALS,
)

db.session.commit()


@pytest.fixture(scope="function")
def mock_allocations_db(app, mock_users_db, project_accounts):
prev_epoch_context = get_context(MOCKED_PENDING_EPOCH_NO - 1)
pending_epoch_context = get_context(MOCKED_PENDING_EPOCH_NO)
def mock_allocations_db(mock_users_db, project_accounts, epoch=MOCKED_PENDING_EPOCH_NO):
prev_epoch_context = get_context(epoch - 1)
pending_epoch_context = get_context(epoch)
user1, user2, _ = mock_users_db

user1_allocations = [
Expand Down
8 changes: 8 additions & 0 deletions backend/tests/helpers/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
MOCKED_PENDING_EPOCH_NO = 1
MOCKED_FINALIZED_EPOCH_NO = 1
MOCKED_EPOCH_NO_AFTER_OVERHAUL = 3
MOCKED_EPOCH_NO_WITH_CAPPED_MR = 4
MOCKED_CURRENT_EPOCH_NO = 2
NO_PATRONS_REWARDS = 0
ETH_PROCEEDS = 402_410958904_110000000
Expand All @@ -31,6 +32,13 @@
ETH_PROCEEDS, LOCKED_RATIO, USER2_BUDGET
)
COMMUNITY_FUND = int(Decimal("0.05") * ETH_PROCEEDS)
LEFTOVER_WITH_PPF_UNUSED_MR = (
ETH_PROCEEDS
- OPERATIONAL_COST
- COMMUNITY_FUND
- int(0.5 * PPF)
- TOTAL_WITHDRAWALS
)

USER1_ADDRESS = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
USER2_ADDRESS = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
Expand Down
18 changes: 18 additions & 0 deletions backend/tests/helpers/finalized_snapshots.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from app.extensions import db
from app.infrastructure import database
from tests.helpers.constants import (
NO_PATRONS_REWARDS,
TOTAL_WITHDRAWALS,
)


def create_finalized_snapshot(epoch_nr: int, matched_rewards: int, leftover: int):
database.finalized_epoch_snapshot.save_snapshot(
epoch_nr,
matched_rewards,
NO_PATRONS_REWARDS,
leftover,
total_withdrawals=TOTAL_WITHDRAWALS,
)

db.session.commit()
42 changes: 42 additions & 0 deletions backend/tests/modules/octant_rewards/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import pytest

from tests.helpers.constants import (
MOCKED_EPOCH_NO_WITH_CAPPED_MR,
COMMUNITY_FUND,
PPF,
MOCKED_FINALIZED_EPOCH_NO,
MATCHED_REWARDS_AFTER_OVERHAUL,
MATCHED_REWARDS,
LEFTOVER,
LEFTOVER_WITH_PPF_UNUSED_MR,
)
from tests.helpers.finalized_snapshots import create_finalized_snapshot
from tests.helpers.pending_snapshot import create_pending_snapshot


@pytest.fixture(scope="function")
def mock_pending_epoch_snapshot_with_uq_scores(
mock_users_db_with_scores, ppf=PPF, cf=COMMUNITY_FUND
):
user1_, user2, user3 = mock_users_db_with_scores
create_pending_snapshot(
epoch_nr=MOCKED_EPOCH_NO_WITH_CAPPED_MR,
optional_ppf=ppf,
optional_cf=cf,
mock_users_db=mock_users_db_with_scores,
)
return user1_, user2, user3


@pytest.fixture(scope="function")
def mock_finalized_epoch_snapshot_db(app, user_accounts):
create_finalized_snapshot(MOCKED_FINALIZED_EPOCH_NO, MATCHED_REWARDS, LEFTOVER)


@pytest.fixture(scope="function")
def mock_finalized_epoch_snapshot_db_for_e4(app, user_accounts):
create_finalized_snapshot(
MOCKED_EPOCH_NO_WITH_CAPPED_MR,
MATCHED_REWARDS_AFTER_OVERHAUL,
LEFTOVER_WITH_PPF_UNUSED_MR,
)
2 changes: 2 additions & 0 deletions backend/tests/modules/octant_rewards/helpers/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def check_octant_rewards(
matched_rewards: int = None,
total_withdrawals: int = None,
patrons_rewards: int = None,
donated_to_projects: int = None,
):
assert rewards.staking_proceeds == ETH_PROCEEDS
assert rewards.locked_ratio == LOCKED_RATIO
Expand All @@ -29,3 +30,4 @@ def check_octant_rewards(
assert rewards.leftover == leftover
assert rewards.community_fund == community_fund
assert rewards.ppf == ppf
assert rewards.donated_to_projects == donated_to_projects
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def test_calculate_octant_rewards_before_overhaul(
assert result.total_rewards == expected_tr
assert result.vanilla_individual_rewards == expected_ir
assert result.operational_cost == expected_operational_cost
assert result.donated_to_projects is None


def test_calculate_octant_rewards_after_overhaul(
Expand Down Expand Up @@ -69,3 +70,4 @@ def test_calculate_octant_rewards_after_overhaul(
assert result.ppf == overhaul_formulas.ppf(
result.staking_proceeds, result.vanilla_individual_rewards, LOCKED_RATIO
)
assert result.donated_to_projects is None
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def test_finalized_octant_rewards_before_overhaul(
matched_rewards=MATCHED_REWARDS,
total_withdrawals=TOTAL_WITHDRAWALS,
patrons_rewards=NO_PATRONS_REWARDS,
donated_to_projects=MATCHED_REWARDS,
)


Expand All @@ -51,6 +52,7 @@ def test_finalized_octant_rewards_after_overhaul(
matched_rewards=MATCHED_REWARDS_AFTER_OVERHAUL,
total_withdrawals=TOTAL_WITHDRAWALS,
patrons_rewards=NO_PATRONS_REWARDS,
donated_to_projects=MATCHED_REWARDS_AFTER_OVERHAUL,
)


Expand All @@ -70,3 +72,13 @@ def test_finalized_get_leverage(
result = service.get_leverage(context)

assert result == 144160.63189897747


def test_donated_to_projects_in_octant_rewards_for_capped_mr(
mock_pending_epoch_snapshot_with_uq_scores, mock_finalized_epoch_snapshot_db_for_e4
):
context = get_context(epoch_num=4)
service = FinalizedOctantRewards()
result = service.get_octant_rewards(context)

assert result.donated_to_projects == 140849434135859019815
Loading
Loading