Skip to content

Commit

Permalink
Alter TWA snapshot parameters (#42)
Browse files Browse the repository at this point in the history
* chore: reorder var order

* fix: 1h min_snapshots_dt

* feat: no taking snapshots by default

* test: update FeeSplitter deployment

* test: fix tests, add gas measure example
  • Loading branch information
heswithme authored Oct 22, 2024
1 parent 11c78c4 commit 7008ce2
Show file tree
Hide file tree
Showing 10 changed files with 40 additions and 19 deletions.
4 changes: 2 additions & 2 deletions contracts/RewardsHandler.vy
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def __init__(

twa.__init__(
WEEK, # twa_window = 1 week
600, # min_snapshot_dt_seconds = 600 seconds
3_600, # min_snapshot_dt_seconds = 1 hour (3600 sec)
)

self._set_minimum_weight(minimum_weight)
Expand Down Expand Up @@ -209,7 +209,7 @@ def _take_snapshot():


@external
def process_rewards(take_snapshot: bool = True):
def process_rewards(take_snapshot: bool = False):
"""
@notice Permissionless function that let anyone distribute rewards (if any) to
the crvUSD vault.
Expand Down
2 changes: 1 addition & 1 deletion contracts/TWA.vy
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ MAX_SNAPSHOTS: constant(uint256) = 10**18 # 31.7 billion years if snapshot ever
################################################################


snapshots: public(DynArray[Snapshot, MAX_SNAPSHOTS])
min_snapshot_dt_seconds: public(uint256) # Minimum time between snapshots in seconds
twa_window: public(uint256) # Time window in seconds for TWA calculation
last_snapshot_timestamp: public(uint256) # Timestamp of the last snapshot
snapshots: public(DynArray[Snapshot, MAX_SNAPSHOTS])


struct Snapshot:
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/address_book.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
crvusd = "0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E"
crvusd_controller_factory = "0xC9332fdCB1C491Dcc683bAe86Fe3cb70360738BC"
crvusd_fee_collector = "0xa2Bcd1a4Efbd04B63cd03f5aFf2561106ebCCE00"
fee_splitter = "0x22556558419eed2d0a1af2e7fd60e63f3199aca3"
fee_splitter = "0x2dFd89449faff8a532790667baB21cF733C064f2"
dao_agent = "0x40907540d8a6C65c637785e8f8B742ae6b0b9968"

dev_multisig = "0xe286b81d16FC7e87eD9dc2a80dd93b1816F4Dcf2"
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def rpc_url():

@pytest.fixture(autouse=True)
def forked_env(rpc_url):
block_to_fork = 20928372
block_to_fork = 21020069
with boa.swap_env(boa.Env()):
if BOA_CACHE:
boa.fork(url=rpc_url, block_identifier=block_to_fork)
Expand Down
17 changes: 14 additions & 3 deletions tests/integration/test_dynamic_weight.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ def raw_weight() -> uint256:
def test_fee_splitter_cap(
fee_splitter, crvusd, vault, rewards_handler, active_controllers, new_depositor, stablecoin_lens
):
fee_collector_before = crvusd.balanceOf(ab.crvusd_fee_collector)
rewards_handler_before = crvusd.balanceOf(rewards_handler.address)

# test were we ask for so much that we hit the cap
fee_splitter_cap = fee_splitter.receivers(0)[1]

Expand Down Expand Up @@ -63,8 +66,10 @@ def test_fee_splitter_cap(
fee_collector_after = crvusd.balanceOf(ab.crvusd_fee_collector)
rewards_handler_after = crvusd.balanceOf(rewards_handler.address)

fee_collector_diff = fee_collector_after - fee_collector_before
rewards_handler_diff = rewards_handler_after - rewards_handler_before
# amount received by the rewards_handler was capped at the source
assert fee_collector_after / rewards_handler_after == 9_000 / 1_000
assert fee_collector_diff / rewards_handler_diff == 9_000 / 1_000


def test_minimum_weight(rewards_handler, minimum_weight, vault, crvusd, new_depositor):
Expand Down Expand Up @@ -118,10 +123,16 @@ def test_dynamic_weight_depositors(
# ================= WEIGHTS CHECKS ==================

with boa.env.anchor():
fee_collector_before = crvusd.balanceOf(ab.crvusd_fee_collector)
rewards_handler_before = crvusd.balanceOf(rewards_handler.address)

fee_splitter.dispatch_fees(active_controllers)
fee_collector_after = crvusd.balanceOf(ab.crvusd_fee_collector)
rewards_handler_after = crvusd.balanceOf(rewards_handler.address)

fee_collector_diff = fee_collector_after - fee_collector_before
rewards_handler_diff = rewards_handler_after - rewards_handler_before

if raw_weight < rewards_handler.minimum_weight():
assert rewards_handler.weight() >= raw_weight
assert rewards_handler.weight() == rewards_handler.minimum_weight() == minimum_weight
Expand All @@ -132,15 +143,15 @@ def test_dynamic_weight_depositors(
# if the weight is actually dynamic we want to make sure
# that the distribution is done according to the weight

balance_ratio = fee_collector_after * 10_000 // rewards_handler_after
balance_ratio = fee_collector_diff * 10_000 // rewards_handler_diff
excess = 1_000 - raw_weight
weight_ratio = (9_000 + excess) * 10_000 // raw_weight

assert balance_ratio == weight_ratio

elif raw_weight > fee_splitter_cap:
# amount received by the rewards_handler was capped at the source
assert fee_collector_after / rewards_handler_after == 9_000 / 1_000
assert fee_collector_diff / rewards_handler_diff == 9_000 / 1_000

else:
raise AssertionError("This should not happen")
Expand Down
3 changes: 0 additions & 3 deletions tests/integration/test_fee_splitter.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import boa

import address_book as ab


def test_fee_splitter(fee_splitter, rewards_handler, crvusd, vault, active_controllers):
assert crvusd.balanceOf(ab.crvusd_fee_collector) == 0
assert crvusd.balanceOf(rewards_handler.address) == 0

# ============== SOME DEPOSITS JOIN THE VAULT ==============
Expand Down
12 changes: 11 additions & 1 deletion tests/integration/test_stablecoin_lens.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
FORK_BLOCK_SUPPLY = 62182303636759107878108289
import pytest
import boa

FORK_BLOCK_SUPPLY = 62247189465433688283786326


def test_circulating_supply(stablecoin_lens):
# circ supply for block of fork
assert stablecoin_lens.circulating_supply() == FORK_BLOCK_SUPPLY


@pytest.mark.ignore_isolation
def test_gas_cost(stablecoin_lens):
boa.env.reset_gas_used()
_ = stablecoin_lens.circulating_supply()
print(f"Compute TWA gas: {stablecoin_lens.call_trace().gas_used}")
6 changes: 3 additions & 3 deletions tests/unitary/rewards_handler/test_process_rewards.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def test_snapshots_taking(rewards_handler, rate_manager, crvusd):
rewards_handler.set_distribution_time(1234, sender=rate_manager) # to enable process_rewards
assert rewards_handler.get_len_snapshots() == 0
boa.deal(crvusd, rewards_handler, 1)
rewards_handler.process_rewards()
rewards_handler.process_rewards(True) # True to take snapshot
assert crvusd.balanceOf(rewards_handler) == 0 # crvusd gone
assert rewards_handler.get_len_snapshots() == 1 # first snapshot taken

Expand All @@ -44,6 +44,6 @@ def test_snapshots_taking(rewards_handler, rate_manager, crvusd):

boa.env.time_travel(seconds=rewards_handler.min_snapshot_dt_seconds())
boa.deal(crvusd, rewards_handler, 1)
rewards_handler.process_rewards()
rewards_handler.process_rewards(False) # False to not take snapshot
assert crvusd.balanceOf(rewards_handler) == 0 # crvusd gone (they always go)
assert rewards_handler.get_len_snapshots() == 2 # changed since dt has passed
assert rewards_handler.get_len_snapshots() == 1 # not changed since dt has passed but False
2 changes: 1 addition & 1 deletion tests/unitary/rewards_handler/test_rh_constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ def test_default_behavior(
# eoa would be the deployer from which we revoke the role
assert not rewards_handler.hasRole(rewards_handler.DEFAULT_ADMIN_ROLE(), boa.env.eoa)
assert rewards_handler.eval("twa.twa_window") == 86_400 * 7
assert rewards_handler.eval("twa.min_snapshot_dt_seconds") == 600 # 10 minutes
assert rewards_handler.eval("twa.min_snapshot_dt_seconds") == 3600 # 1 hr
9 changes: 6 additions & 3 deletions tests/unitary/rewards_handler/test_take_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
import boa


@pytest.mark.gas_profile
def test_take_snapshot_compute(rewards_handler):
@pytest.mark.ignore_isolation
def test_take_snapshot_compute(vault, rewards_handler):
n_days = 7
dt = 600
dt = 3600
snaps_per_day = 86_400 // dt
for i_day in range(n_days):
for i_snap in range(snaps_per_day):
rewards_handler.take_snapshot()
boa.env.time_travel(seconds=dt)
boa.env.reset_gas_used()
twa = rewards_handler.compute_twa()
print(f"Compute TWA gas: {rewards_handler.call_trace().gas_used}")
# print(rewards_handler._computation.get_gas_used())
assert twa >= 0, f"Computed TWA is negative: {twa}"

0 comments on commit 7008ce2

Please sign in to comment.