Skip to content

Commit

Permalink
OCT-2262: Align time threshold for sablier on UAT (#593)
Browse files Browse the repository at this point in the history
## Description

## Definition of Done

1. [ ] If required, the desciption of your change is added to the [QA
changelog](https://www.notion.so/octantapp/Changelog-for-the-QA-d96fa3b411cf488bb1d8d9a598d88281)
2. [ ] Acceptance criteria are met.
3. [ ] PR is manually tested before the merge by developer(s).
    - [ ] Happy path is manually checked.
4. [ ] PR is manually tested by QA when their assistance is required
(1).
- [ ] Octant Areas & Test Cases are checked for impact and updated if
required (2).
5. [ ] Unit tests are added unless there is a reason to omit them.
6. [ ] Automated tests are added when required.
7. [ ] The code is merged.
8. [ ] Tech documentation is added / updated, reviewed and approved
(including mandatory approval by a code owner, should such exist for
changed files).
    - [ ] BE: Swagger documentation is updated.
9. [ ] When required by QA:
    - [ ] Deployed to the relevant environment.
    - [ ] Passed system tests.

---

(1) Developer(s) in coordination with QA decide whether it's required.
For small tickets introducing small changes QA assistance is most
probably not required.

(2) [Octant Areas & Test
Cases](https://docs.google.com/spreadsheets/d/1cRe6dxuKJV3a4ZskAwWEPvrFkQm6rEfyUCYwLTYw_Cc).
  • Loading branch information
kgarbacinski authored Dec 28, 2024
1 parent 8e2df16 commit d6a67b3
Show file tree
Hide file tree
Showing 13 changed files with 130 additions and 30 deletions.
3 changes: 3 additions & 0 deletions backend/app/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -1002,3 +1002,6 @@

SABLIER_SENDER_ADDRESS_SEPOLIA = "0xf86fD85672683c220709B9ED80bAD7a51800206a"
SABLIER_TOKEN_ADDRESS_SEPOLIA = "0x71432dd1ae7db41706ee6a22148446087bdd0906"

SABLIER_UNLOCK_GRACE_PERIOD_24_HRS = 24 * 60 * 60
TEST_SABLIER_UNLOCK_GRACE_PERIOD_15_MIN = 15 * 60
1 change: 1 addition & 0 deletions backend/app/engine/user/effective_deposit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class UserEffectiveDepositPayload:
epoch_start: int = None
epoch_end: int = None
lock_events_by_addr: LockEventsByAddr = None
sablier_unlock_grace_period: int = None


@dataclass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,17 @@ def calculate_users_effective_deposits(
self, payload: UserEffectiveDepositPayload
) -> Tuple[List[UserDeposit], int]:
payload.lock_events_by_addr = self._remove_unlock_and_lock_within_24_hours(
payload.lock_events_by_addr
payload.lock_events_by_addr, payload.sablier_unlock_grace_period
)

return super().calculate_users_effective_deposits(payload)

def _remove_unlock_and_lock_within_24_hours(
self, events: LockEventsByAddr
self, events: LockEventsByAddr, sablier_unlock_grace_period: int
) -> LockEventsByAddr:
"""
Removes the unlock event from Sablier if it is followed by a lock event in Octant within 24 hours.
"""
TWENTY_FOUR_HOURS_PERIOD = 24 * 60 * 60

for address, user_events in events.items():
if not user_events:
continue
Expand All @@ -51,7 +49,7 @@ def _remove_unlock_and_lock_within_24_hours(
and next_event.source == DepositSource.OCTANT
and next_event.type == EventType.LOCK
and next_event.timestamp - prev_event.timestamp
< TWENTY_FOUR_HOURS_PERIOD
< sablier_unlock_grace_period
):
# Skip both the unlock and the following lock.
skip_next = True
Expand Down
6 changes: 5 additions & 1 deletion backend/app/modules/common/effective_deposits.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ def calculate_effective_deposits(
epoch_details: EpochDetails,
epoch_settings: EpochSettings,
events: Dict[str, List[DepositEvent]],
sablier_unlock_grace_period: int = None,
) -> Tuple[List[UserDeposit], int]:
start = epoch_details.start_sec
end = epoch_details.end_sec
effective_deposit_calculator = epoch_settings.user.effective_deposit

return effective_deposit_calculator.calculate_users_effective_deposits(
UserEffectiveDepositPayload(
epoch_start=start, epoch_end=end, lock_events_by_addr=events
epoch_start=start,
epoch_end=end,
lock_events_by_addr=events,
sablier_unlock_grace_period=sablier_unlock_grace_period,
)
)
11 changes: 8 additions & 3 deletions backend/app/modules/modules_factory/current.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
UQ_THRESHOLD_NOT_MAINNET,
TIMEOUT_LIST_NOT_MAINNET,
TIMEOUT_LIST,
SABLIER_UNLOCK_GRACE_PERIOD_24_HRS,
TEST_SABLIER_UNLOCK_GRACE_PERIOD_15_MIN,
)
from app.modules.projects.details.service.projects_details import (
StaticProjectsDetailsService,
Expand Down Expand Up @@ -95,12 +97,15 @@ def _prepare_simulation_data(

@staticmethod
def create(chain_id: int) -> "CurrentServices":
is_mainnet = compare_blockchain_types(chain_id, ChainTypes.MAINNET)

user_deposits = CalculatedUserDeposits(
events_generator=DbAndGraphEventsGenerator()
events_generator=DbAndGraphEventsGenerator(),
sablier_unlock_grace_period=SABLIER_UNLOCK_GRACE_PERIOD_24_HRS
if is_mainnet
else TEST_SABLIER_UNLOCK_GRACE_PERIOD_15_MIN,
)

is_mainnet = compare_blockchain_types(chain_id, ChainTypes.MAINNET)

octant_rewards = CurrentServices._prepare_simulation_data(
is_mainnet, user_deposits
)
Expand Down
9 changes: 8 additions & 1 deletion backend/app/modules/modules_factory/pre_pending.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import app.modules.staking.proceeds.service.aggregated as aggregated
import app.modules.staking.proceeds.service.contract_balance as contract_balance
from app.constants import (
SABLIER_UNLOCK_GRACE_PERIOD_24_HRS,
TEST_SABLIER_UNLOCK_GRACE_PERIOD_15_MIN,
)
from app.modules.modules_factory.protocols import (
AllUserEffectiveDeposits,
OctantRewards,
Expand Down Expand Up @@ -50,7 +54,10 @@ def create(chain_id: int) -> "PrePendingServices":
is_mainnet = compare_blockchain_types(chain_id, ChainTypes.MAINNET)

user_deposits = CalculatedUserDeposits(
events_generator=DbAndGraphEventsGenerator()
events_generator=DbAndGraphEventsGenerator(),
sablier_unlock_grace_period=SABLIER_UNLOCK_GRACE_PERIOD_24_HRS
if is_mainnet
else TEST_SABLIER_UNLOCK_GRACE_PERIOD_15_MIN,
)
octant_rewards = CalculatedOctantRewards(
staking_proceeds=(
Expand Down
25 changes: 24 additions & 1 deletion backend/app/modules/user/budgets/controller.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from typing import List

from app.constants import (
SABLIER_UNLOCK_GRACE_PERIOD_24_HRS,
TEST_SABLIER_UNLOCK_GRACE_PERIOD_15_MIN,
)
from app.context.epoch_state import EpochState
from app.context.manager import state_context, epoch_context
from app.exceptions import NotImplementedForGivenEpochState
Expand All @@ -12,6 +16,8 @@
from app.modules.modules_factory.protocols import UserBudgets, UpcomingUserBudgets
from app.modules.registry import get_services
from app.modules.user.budgets import core
from app.shared.blockchain_types import compare_blockchain_types, ChainTypes
from flask import current_app as app


def get_budgets(epoch_num: int) -> List[AccountFundsDTO]:
Expand Down Expand Up @@ -47,13 +53,20 @@ def estimate_budget(lock_duration_sec: int, glm_amount: int) -> int:
future_rewards_service = get_services(EpochState.FUTURE).octant_rewards_service
future_rewards = future_rewards_service.get_octant_rewards(future_context)

sablier_unlock_grace_period = (
SABLIER_UNLOCK_GRACE_PERIOD_24_HRS
if compare_blockchain_types(app.config["CHAIN_ID"], ChainTypes.MAINNET)
else TEST_SABLIER_UNLOCK_GRACE_PERIOD_15_MIN
)

return core.estimate_budget(
current_context,
future_context,
current_rewards,
future_rewards,
lock_duration_sec,
glm_amount,
sablier_unlock_grace_period,
)


Expand All @@ -73,8 +86,18 @@ def estimate_epochs_budget(no_epochs: int, glm_amount: int) -> int:

epoch_duration = future_context.epoch_details.duration_sec

sablier_unlock_grace_period = (
SABLIER_UNLOCK_GRACE_PERIOD_24_HRS
if compare_blockchain_types(app.config["CHAIN_ID"], ChainTypes.MAINNET)
else TEST_SABLIER_UNLOCK_GRACE_PERIOD_15_MIN
)

return no_epochs * core.estimate_epoch_budget(
future_context, future_rewards, epoch_duration, glm_amount
future_context,
future_rewards,
epoch_duration,
glm_amount,
sablier_unlock_grace_period,
)


Expand Down
10 changes: 9 additions & 1 deletion backend/app/modules/user/budgets/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,18 @@ def estimate_epoch_budget(
rewards: OctantRewardsDTO,
lock_duration: int,
glm_amount: int,
sablier_unlock_grace_period: int = None,
) -> int:
epoch_details = context.epoch_details
epoch_settings = context.epoch_settings
events = {
ZERO_ADDRESS: simulate_user_events(epoch_details, lock_duration, glm_amount)
}
user_effective_deposits, _ = calculate_effective_deposits(
epoch_details, epoch_settings, events
epoch_details,
epoch_settings,
events,
sablier_unlock_grace_period=sablier_unlock_grace_period,
)
effective_deposit = (
user_effective_deposits[0].effective_deposit if user_effective_deposits else 0
Expand All @@ -72,13 +76,15 @@ def estimate_budget(
future_rewards: OctantRewardsDTO,
lock_duration_sec: int,
glm_amount: int,
sablier_unlock_grace_period: int = None,
) -> int:
remaining_lock_duration = lock_duration_sec
budget = estimate_epoch_budget(
current_context,
current_rewards,
remaining_lock_duration,
glm_amount,
sablier_unlock_grace_period,
)
remaining_lock_duration -= current_context.epoch_details.remaining_sec

Expand All @@ -92,6 +98,7 @@ def estimate_budget(
future_rewards,
epoch_duration,
glm_amount,
sablier_unlock_grace_period,
)
remaining_lock_duration = remaining_future_epoch_sec

Expand All @@ -101,6 +108,7 @@ def estimate_budget(
future_rewards,
remaining_lock_duration,
glm_amount,
sablier_unlock_grace_period,
)

return budget
Expand Down
17 changes: 14 additions & 3 deletions backend/app/modules/user/deposits/service/calculated.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,39 @@ def get_all_users_events(self, context: Context) -> Dict[str, List[DepositEvent]

class CalculatedUserDeposits(Model):
events_generator: EventsGenerator
sablier_unlock_grace_period: int

def get_all_effective_deposits(
self, context: Context
) -> Tuple[List[UserDeposit], int]:
events = self.events_generator.get_all_users_events(context)
return calculate_effective_deposits(
context.epoch_details, context.epoch_settings, events
context.epoch_details,
context.epoch_settings,
events,
self.sablier_unlock_grace_period,
)

def get_total_effective_deposit(self, context: Context) -> int:
events = self.events_generator.get_all_users_events(context)
_, total = calculate_effective_deposits(
context.epoch_details, context.epoch_settings, events
context.epoch_details,
context.epoch_settings,
events,
self.sablier_unlock_grace_period,
)
return total

def get_user_effective_deposit(self, context: Context, user_address: str) -> int:
events = {
user_address: self.events_generator.get_user_events(context, user_address)
}
print("events", events)
deposits, _ = calculate_effective_deposits(
context.epoch_details, context.epoch_settings, events
context.epoch_details,
context.epoch_settings,
events,
self.sablier_unlock_grace_period,
)
return deposits[0].effective_deposit

Expand Down
1 change: 1 addition & 0 deletions backend/tests/helpers/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,4 @@
BOB_SABLIER_LOCKING_ADDRESS = "0x7fc77B5C761F3FaE3BE3F2FA3F6fA3FA3fA3Fa3f"

TWENTY_FOUR_HOURS_PERIOD = 24 * 60 * 60
FIFTEEN_MINUTES_PERIOD = 15 * 60
22 changes: 16 additions & 6 deletions backend/tests/modules/modules_factory/test_modules_factory.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from app.constants import UQ_THRESHOLD_MAINNET, TIMEOUT_LIST
from app.modules.dto import SignatureOpType
from app.modules.history.service.full import FullHistory
from app.modules.modules_factory.current import CurrentServices
Expand All @@ -21,6 +22,7 @@
SimulatedFinalizedSnapshots,
)
from app.modules.snapshots.pending.service.pre_pending import PrePendingSnapshots
from app.modules.snapshots.pending.service.simulated import SimulatedPendingSnapshots
from app.modules.staking.proceeds.service.aggregated import AggregatedStakingProceeds
from app.modules.staking.proceeds.service.contract_balance import (
ContractBalanceStakingProceeds,
Expand All @@ -35,6 +37,7 @@
from app.modules.user.allocations.service.saved import SavedUserAllocations
from app.modules.user.antisybil.service.initial import GitcoinPassportAntisybil
from app.modules.user.budgets.service.saved import SavedUserBudgets
from app.modules.user.budgets.service.upcoming import UpcomingUserBudgets
from app.modules.user.deposits.service.calculated import CalculatedUserDeposits
from app.modules.user.deposits.service.contract_balance import (
ContractBalanceUserDeposits,
Expand All @@ -50,9 +53,7 @@
from app.modules.withdrawals.service.finalized import FinalizedWithdrawals
from app.modules.withdrawals.service.pending import PendingWithdrawals
from app.shared.blockchain_types import ChainTypes
from app.modules.user.budgets.service.upcoming import UpcomingUserBudgets
from app.modules.snapshots.pending.service.simulated import SimulatedPendingSnapshots
from app.constants import UQ_THRESHOLD_MAINNET, TIMEOUT_LIST
from tests.helpers.constants import TWENTY_FOUR_HOURS_PERIOD, FIFTEEN_MINUTES_PERIOD


def test_future_services_factory():
Expand All @@ -67,7 +68,10 @@ def test_future_services_factory():
def test_current_services_factory():
result = CurrentServices.create(ChainTypes.MAINNET)

user_deposits = CalculatedUserDeposits(events_generator=DbAndGraphEventsGenerator())
user_deposits = CalculatedUserDeposits(
events_generator=DbAndGraphEventsGenerator(),
sablier_unlock_grace_period=TWENTY_FOUR_HOURS_PERIOD,
)
user_allocations = SavedUserAllocations()
user_withdrawals = FinalizedWithdrawals()
tos_verifier = InitialUserTosVerifier()
Expand Down Expand Up @@ -102,7 +106,10 @@ def test_current_services_factory():
def test_pre_pending_services_factory_when_mainnet():
result = PrePendingServices.create(ChainTypes.MAINNET)

user_deposits = CalculatedUserDeposits(events_generator=DbAndGraphEventsGenerator())
user_deposits = CalculatedUserDeposits(
events_generator=DbAndGraphEventsGenerator(),
sablier_unlock_grace_period=TWENTY_FOUR_HOURS_PERIOD,
)
octant_rewards = CalculatedOctantRewards(
staking_proceeds=AggregatedStakingProceeds(),
effective_deposits=user_deposits,
Expand All @@ -119,7 +126,10 @@ def test_pre_pending_services_factory_when_mainnet():
def test_pre_pending_services_factory_when_not_mainnet():
result = PrePendingServices.create(ChainTypes.LOCAL)

user_deposits = CalculatedUserDeposits(events_generator=DbAndGraphEventsGenerator())
user_deposits = CalculatedUserDeposits(
events_generator=DbAndGraphEventsGenerator(),
sablier_unlock_grace_period=FIFTEEN_MINUTES_PERIOD,
)
octant_rewards = CalculatedOctantRewards(
staking_proceeds=ContractBalanceStakingProceeds(),
effective_deposits=user_deposits,
Expand Down
21 changes: 17 additions & 4 deletions backend/tests/modules/score_delegation/test_simple_obfuscation.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
USER2_ADDRESS,
USER3_ADDRESS,
TIMEOUT_LIST,
TWENTY_FOUR_HOURS_PERIOD,
)


Expand All @@ -41,7 +42,10 @@ def test_delegation(
context, mock_empty_events_generator, payload, tos_users, patch_is_contract
):
verifier = SimpleObfuscationDelegationVerifier()
user_deposits = CalculatedUserDeposits(events_generator=mock_empty_events_generator)
user_deposits = CalculatedUserDeposits(
events_generator=mock_empty_events_generator,
sablier_unlock_grace_period=TWENTY_FOUR_HOURS_PERIOD,
)
antisybil = Mock()
antisybil.fetch_antisybil_status.return_value = (
20,
Expand All @@ -64,7 +68,10 @@ def test_delegation_disabled_when_secondary_is_locking(
context, mock_events_generator, tos_users, patch_is_contract
):
verifier = SimpleObfuscationDelegationVerifier()
user_deposits = CalculatedUserDeposits(events_generator=mock_events_generator)
user_deposits = CalculatedUserDeposits(
events_generator=mock_events_generator,
sablier_unlock_grace_period=TWENTY_FOUR_HOURS_PERIOD,
)
antisybil = Mock()
antisybil.fetch_antisybil_status.return_value = (
20,
Expand All @@ -91,7 +98,10 @@ def test_disable_recalculation_when_secondary_address_is_used(
context, mock_empty_events_generator, payload, patch_is_contract
):
verifier = SimpleObfuscationDelegationVerifier()
user_deposits = CalculatedUserDeposits(events_generator=mock_empty_events_generator)
user_deposits = CalculatedUserDeposits(
events_generator=mock_empty_events_generator,
sablier_unlock_grace_period=TWENTY_FOUR_HOURS_PERIOD,
)
antisybil = Mock()
antisybil.fetch_antisybil_status.return_value = (
20,
Expand Down Expand Up @@ -126,7 +136,10 @@ def test_recalculation_when_delegation_is_not_done(
context, mock_empty_events_generator, payload, patch_is_contract
):
verifier = SimpleObfuscationDelegationVerifier()
user_deposits = CalculatedUserDeposits(events_generator=mock_empty_events_generator)
user_deposits = CalculatedUserDeposits(
events_generator=mock_empty_events_generator,
sablier_unlock_grace_period=TWENTY_FOUR_HOURS_PERIOD,
)
antisybil = Mock()
antisybil.fetch_antisybil_status.return_value = (
20,
Expand Down
Loading

0 comments on commit d6a67b3

Please sign in to comment.