Skip to content

Commit

Permalink
V2 autocompounder (velodrome-finance#28)
Browse files Browse the repository at this point in the history
* add RelaySugar

* Account deposits() function, add inactive field

* Relay struct flattened (#20)

* Relay struct flattened

* Add account veNFT ids to Relay struct

* Remove VeSugar dependency

* Remove Deposit struct and function

* Vyper range bound check

* byId() -> byAddress()

* feat: use RelayFactory, add latest epoch compounded rewards (velodrome-finance#22)

* feat: use RelayFactory, add latest epoch compounded rewards

* refactor: rename rewards_compounded

* refactor: fetch Relays from Registry (velodrome-finance#24)

* refactor: fetch all Relays from Registry's factories (velodrome-finance#26)

* feat: add run_at to Relay struct output (velodrome-finance#27)

* Add Relay to readme

* Add Relay tests
  • Loading branch information
ethzoomer committed Apr 19, 2024
1 parent b485fea commit fffdfb3
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 84 deletions.
84 changes: 21 additions & 63 deletions contracts/RelaySugar.vy
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: BUSL-1.1
# @version ^0.3.6
# @version >=0.3.6 <0.4.0

# @title Velodrome Finance Relay Sugar v2
# @author stas, ZoomerAnon
Expand All @@ -8,39 +8,27 @@
MAX_RELAYS: constant(uint256) = 50
MAX_RESULTS: constant(uint256) = 1000
MAX_PAIRS: constant(uint256) = 30
MAX_REGISTRIES: constant(uint256) = 20
WEEK: constant(uint256) = 7 * 24 * 60 * 60

struct LpVotes:
lp: address
weight: uint256

struct ManagedVenft:
id: uint256
amount: uint256
earned: uint256

struct Relay:
venft_id: uint256
decimals: uint8
amount: uint128
voting_amount: uint256
used_voting_amount: uint256
voted_at: uint256
votes: DynArray[LpVotes, MAX_PAIRS]
token: address
compounded: uint256
withdrawable: uint256
run_at: uint256
manager: address
relay: address
inactive: bool
name: String[100]
account_venfts: DynArray[ManagedVenft, MAX_RESULTS]


interface IERC20:
def balanceOf(_account: address) -> uint256: view
account_venft_ids: DynArray[uint256, MAX_RESULTS]

interface IVoter:
def ve() -> address: view
Expand All @@ -59,11 +47,6 @@ interface IVotingEscrow:
def locked(_venft_id: uint256) -> (uint128, uint256, bool): view
def ownerToNFTokenIdList(_account: address, _index: uint256) -> uint256: view
def voted(_venft_id: uint256) -> bool: view
def managedToLocked(_managed_venft_id: uint256) -> address: view
def weights(_venft_id: uint256, _managed_venft_id: uint256) -> uint256: view

interface IReward:
def earned(_token: address, _venft_id: uint256) -> uint256: view

interface IRelayRegistry:
def getAll() -> DynArray[address, MAX_RELAYS]: view
Expand All @@ -78,21 +61,19 @@ interface IRelay:
def keeperLastRun() -> uint256: view
# Latest epoch rewards
def amountTokenEarned(_epoch_ts: uint256) -> uint256: view
def DEFAULT_ADMIN_ROLE() -> bytes32: view
def getRoleMember(_role: bytes32, _index: uint256) -> address: view

# Vars
registries: public(DynArray[address, MAX_REGISTRIES])
registry: public(IRelayRegistry)
voter: public(IVoter)
ve: public(IVotingEscrow)
token: public(address)

@external
def __init__(_registries: DynArray[address, MAX_REGISTRIES], _voter: address):
def __init__(_registry: address, _voter: address):
"""
@dev Set up our external registry and voter contracts
"""
self.registries = _registries
self.registry = IRelayRegistry(_registry)
self.voter = IVoter(_voter)
self.ve = IVotingEscrow(self.voter.ve())
self.token = self.ve.token()
Expand All @@ -114,26 +95,21 @@ def _relays(_account: address) -> DynArray[Relay, MAX_RELAYS]:
@return Array of Relay structs
"""
relays: DynArray[Relay, MAX_RELAYS] = empty(DynArray[Relay, MAX_RELAYS])
for registry_index in range(0, MAX_REGISTRIES):
if registry_index == len(self.registries):
factories: DynArray[address, MAX_RELAYS] = self.registry.getAll()

for factory_index in range(0, MAX_RELAYS):
if factory_index == len(factories):
break

relay_registry: IRelayRegistry = IRelayRegistry(self.registries[registry_index])
factories: DynArray[address, MAX_RELAYS] = relay_registry.getAll()
relay_factory: IRelayFactory = IRelayFactory(factories[factory_index])
addresses: DynArray[address, MAX_RELAYS] = relay_factory.relays()

for factory_index in range(0, MAX_RELAYS):
if factory_index == len(factories):
for index in range(0, MAX_RELAYS):
if index == len(addresses):
break

relay_factory: IRelayFactory = IRelayFactory(factories[factory_index])
addresses: DynArray[address, MAX_RELAYS] = relay_factory.relays()

for index in range(0, MAX_RELAYS):
if index == len(addresses):
break

relay: Relay = self._byAddress(addresses[index], _account)
relays.append(relay)
relay: Relay = self._byAddress(addresses[index], _account)
relays.append(relay)

return relays

Expand All @@ -146,44 +122,28 @@ def _byAddress(_relay: address, _account: address) -> Relay:
@param _account The account address to lookup deposits
@return Relay struct
"""

relay: IRelay = IRelay(_relay)
managed_id: uint256 = relay.mTokenId()

account_venfts: DynArray[ManagedVenft, MAX_RESULTS] = empty(DynArray[ManagedVenft, MAX_RESULTS])
account_venft_ids: DynArray[uint256, MAX_RESULTS] = empty(DynArray[uint256, MAX_RESULTS])

for venft_index in range(MAX_RESULTS):
account_venft_id: uint256 = self.ve.ownerToNFTokenIdList(_account, venft_index)

if account_venft_id == 0:
break

account_venft_manager_id: uint256 = self.ve.idToManaged(account_venft_id)
if account_venft_manager_id == managed_id:
locked_reward: IReward = IReward(self.ve.managedToLocked(account_venft_manager_id))
venft_weight: uint256 = self.ve.weights(account_venft_id, account_venft_manager_id)
earned: uint256 = locked_reward.earned(self.token, account_venft_id)

account_venfts.append(ManagedVenft({
id: account_venft_id,
amount: venft_weight,
earned: earned
}))
account_venft_ids.append(account_venft_id)

votes: DynArray[LpVotes, MAX_PAIRS] = []
amount: uint128 = self.ve.locked(managed_id)[0]
last_voted: uint256 = 0
withdrawable: uint256 = 0
manager: address = self.ve.ownerOf(managed_id)
inactive: bool = self.ve.deactivated(managed_id)

admin_role: bytes32 = relay.DEFAULT_ADMIN_ROLE()
manager: address = relay.getRoleMember(admin_role, 0)

# If the Relay is an AutoConverter, fetch withdrawable amount
if self.token != relay.token():
token: IERC20 = IERC20(relay.token())
withdrawable = token.balanceOf(_relay)

epoch_start_ts: uint256 = block.timestamp / WEEK * WEEK

# Rewards claimed this epoch
Expand Down Expand Up @@ -220,16 +180,14 @@ def _byAddress(_relay: address, _account: address) -> Relay:
decimals: self.ve.decimals(),
amount: amount,
voting_amount: self.ve.balanceOfNFT(managed_id),
used_voting_amount: vote_weight,
voted_at: last_voted,
votes: votes,
token: relay.token(),
compounded: rewards_compounded,
withdrawable: withdrawable,
run_at: relay.keeperLastRun(),
manager: manager,
relay: _relay,
inactive: inactive,
name: relay.name(),
account_venfts: account_venfts
account_venft_ids: account_venft_ids
})
11 changes: 4 additions & 7 deletions env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ VOTER_ADDRESS=0x41C914ee0c7E1A5edCD0295623e6dC557B5aBf3C
REGISTRY_ADDRESS=0xF4c67CdEAaB8360370F41514d06e32CcD8aA1d7B
DIST_ADDRESS=0x9D4736EC60715e71aFe72973f7885DCBC21EA99b
CONVERTOR_ADDRESS=0x585Af0b397AC42dbeF7f18395426BF878634f18D
RELAY_REGISTRY_ADDRESSES=0xe9F00f2e61CB0c6fb00A2e457546aCbF0fC303C2,0x6b1253B116B5919932399295C75116d33F8EfF96
NFPM_ADDRESS=0xbB5DFE1380333CEE4c2EeBd7202c80dE2256AdF4
SLIPSTREAM_HELPER_ADDRESS=0x5Bd7E2221C2d59c99e6A9Cd18D80A5F4257D0f32
GOVERNOR_ADDRESS=0x0000000000000000000000000000000000000000
LP_SUGAR_ADDRESS=0xc734656F0112CA18cdcaD424ddd8949F3D4c1DdD
VE_SUGAR_ADDRESS=0x37403dBd6f1b583ea244F7956fF9e37EF45c63eB
RELAY_SUGAR_ADDRESS=0x062185EEF2726EFc11880856CD356FA2Ac2B38Ff
LP_SUGAR_ADDRESS=0xD2B1D1B75a0f226722b3A174dAE54e6dD14af1a1
VE_SUGAR_ADDRESS=0x0eCc2593E3a6A9be3628940Fa4D928CC257B588B
RELAY_SUGAR_ADDRESS=0x7f609cf1a99318652859aED5B00C7F5F187E0077
RELAY_REGISTRY_ADDRESS=0xBC3dc970f891ffdd3049FA3a649985CC6626d486
11 changes: 2 additions & 9 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,7 @@ The available methods are:

### Relay Data

> [!NOTE]
> `RelaySugar.vy` is deployed at `0x062185EEF2726EFc11880856CD356FA2Ac2B38Ff`
`RelaySugar.vy` is deployed at `0x7f609cf1a99318652859aED5B00C7F5F187E0077`

It allows fetching Relay autocompounder/autoconverter data.
The returned data/struct of type `Relay` values represent:
Expand All @@ -202,7 +201,6 @@ The returned data/struct of type `Relay` values represent:
* `decimals` - Relay veNFT token decimals
* `amount` - Relay veNFT locked amount
* `voting_amount` - Relay veNFT voting power
* `used_voting_amount` - Relay veNFT voting power used for last vote
* `voted_at` - Relay veNFT last vote timestamp
* `votes` - Relay veNFT list of pools with vote weights casted in the form of
`LpVotes`
Expand All @@ -213,12 +211,7 @@ The returned data/struct of type `Relay` values represent:
* `relay` - Relay address
* `inactive` - Relay active/inactive status
* `name` - Relay name
* `account_venfts` - List of veNFTs deposited into this Relay by the account in the form of `ManagedVenft`

The managed veNFT deposit struct values represent:
* `id` - the token ID of the veNFT
* `amount` - the weight of the veNFT
* `earned` - earned emissions of the veNFT
* `account_venft_ids` - token IDs of the account's deposits into this Relay

---

Expand Down
8 changes: 3 additions & 5 deletions tests/test_relay_sugar.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ def RelayStruct(sugar_contract):

def test_initial_state(sugar_contract):
assert sugar_contract.voter() == os.getenv('VOTER_ADDRESS')
assert sugar_contract.registries(0) == \
os.getenv('RELAY_REGISTRY_ADDRESSES').split(',')[0]
assert sugar_contract.ve() is not None
assert sugar_contract.token() is not None
assert sugar_contract.registry() == \
os.getenv('RELAY_REGISTRY_ADDRESS')


def test_all(sugar_contract, RelayStruct):
Expand All @@ -35,4 +33,4 @@ def test_all(sugar_contract, RelayStruct):
sugar_contract.all(ADDRESS_ZERO)
))

assert len(relays) > 5
assert relays is not None

0 comments on commit fffdfb3

Please sign in to comment.