Skip to content

Commit

Permalink
Merge pull request #20 from wavey0x/wavey_edit
Browse files Browse the repository at this point in the history
feat: remove V1 migration logic and support checkpoints on balance_of…
  • Loading branch information
michwill authored Jul 10, 2024
2 parents db3dec4 + 52ba7c5 commit e03aba9
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 88 deletions.
4 changes: 2 additions & 2 deletions ape-config.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: curve-veboost

ethereum:
default_network: local
default_network: mainnet-fork
local:
default_provider: hardhat
default_provider: foundry

dependencies:
- name: curve-dao
Expand Down
61 changes: 20 additions & 41 deletions contracts/BoostV2.vy
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# @version 0.3.3
# @version 0.3.10
"""
@title Boost Delegation V2
@title Boost Delegation V3
@author CurveFi
"""


event Approval:
_owner: indexed(address)
_spender: indexed(address)
Expand All @@ -22,15 +21,6 @@ event Boost:
_slope: uint256
_start: uint256

event Migrate:
_token_id: indexed(uint256)


interface BoostV1:
def ownerOf(_token_id: uint256) -> address: view
def token_boost(_token_id: uint256) -> int256: view
def token_expiry(_token_id: uint256) -> uint256: view

interface VotingEscrow:
def balanceOf(_user: address) -> uint256: view
def totalSupply() -> uint256: view
Expand All @@ -45,15 +35,14 @@ struct Point:

NAME: constant(String[32]) = "Vote-Escrowed Boost"
SYMBOL: constant(String[8]) = "veBoost"
VERSION: constant(String[8]) = "v2.0.0"
VERSION: constant(String[8]) = "v3.0.0"

EIP712_TYPEHASH: constant(bytes32) = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)")
PERMIT_TYPEHASH: constant(bytes32) = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")

WEEK: constant(uint256) = 86400 * 7


BOOST_V1: immutable(address)
DOMAIN_SEPARATOR: immutable(bytes32)
VE: immutable(address)

Expand All @@ -67,12 +56,8 @@ delegated_slope_changes: public(HashMap[address, HashMap[uint256, uint256]])
received: public(HashMap[address, Point])
received_slope_changes: public(HashMap[address, HashMap[uint256, uint256]])

migrated: public(HashMap[uint256, bool])


@external
def __init__(_boost_v1: address, _ve: address):
BOOST_V1 = _boost_v1
def __init__(_ve: address):
DOMAIN_SEPARATOR = keccak256(_abi_encode(EIP712_TYPEHASH, keccak256(NAME), keccak256(VERSION), chain.id, self, block.prevhash))
VE = _ve

Expand Down Expand Up @@ -229,21 +214,6 @@ def boost(_to: address, _amount: uint256, _endtime: uint256, _from: address = ms
self._boost(_from, _to, _amount, _endtime)


@external
def migrate(_token_id: uint256):
assert not self.migrated[_token_id]

self._boost(
convert(shift(_token_id, -96), address), # from
BoostV1(BOOST_V1).ownerOf(_token_id), # to
convert(BoostV1(BOOST_V1).token_boost(_token_id), uint256), # amount
BoostV1(BOOST_V1).token_expiry(_token_id), # expiry
)

self.migrated[_token_id] = True
log Migrate(_token_id)


@external
def checkpoint_user(_user: address):
self.delegated[_user] = self._checkpoint_write(_user, True)
Expand Down Expand Up @@ -311,6 +281,21 @@ def adjusted_balance_of(_user: address) -> uint256:
return self._balance_of(_user)


@external
def adjusted_balance_of_write(_user: address) -> uint256:
amount: uint256 = VotingEscrow(VE).balanceOf(_user)

point: Point = self._checkpoint_write(_user, True)
self.delegated[_user] = point
amount -= (point.bias - point.slope * (block.timestamp - point.ts))

point = self._checkpoint_write(_user, False)
self.received[_user] = point
amount += (point.bias - point.slope * (block.timestamp - point.ts))

return amount


@view
@external
def totalSupply() -> uint256:
Expand Down Expand Up @@ -356,12 +341,6 @@ def decimals() -> uint8:
return 18


@pure
@external
def BOOST_V1() -> address:
return BOOST_V1


@pure
@external
def DOMAIN_SEPARATOR() -> bytes32:
Expand All @@ -371,4 +350,4 @@ def DOMAIN_SEPARATOR() -> bytes32:
@pure
@external
def VE() -> address:
return VE
return VE
5 changes: 2 additions & 3 deletions scripts/deploy.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from ape import accounts, project
from ape import accounts, project, Contract

primary = accounts.load("primary")


def main():
project.BoostV2.deploy(
"0xd30DD0B919cB4012b3AdD78f6Dcb6eb7ef225Ac8",
"0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2",
sender=primary,
)
)
4 changes: 2 additions & 2 deletions tests/fixtures/deployments.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ def veboost_v1(alice, project, ve):


@pytest.fixture(scope="session")
def veboost(alice, project, ve, veboost_v1):
yield project.BoostV2.deploy(veboost_v1, ve, sender=alice)
def veboost(alice, project, ve):
yield project.BoostV2.deploy(ve, sender=alice)
43 changes: 42 additions & 1 deletion tests/test_boost.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import ape
from ape import chain
import pytest

AMOUNT = 10**21

DAY = 86400
WEEK = DAY * 7
YEAR = DAY * 365

@pytest.mark.parametrize("idx", range(5))
def test_initial_state(accounts, veboost, ve, idx):
Expand Down Expand Up @@ -69,3 +72,41 @@ def test_boost_fails_with_invalid_amount_greater_than_delegable_balance(
def test_boost_fails_with_invalid_allowance(alice, bob, veboost, lock_unlock_time):
with ape.reverts():
veboost.boost(bob, AMOUNT, lock_unlock_time, alice, sender=bob)

def test_adjusted_balance_of_write(alice, bob, veboost, ve, lock_unlock_time):
balance = ve.balanceOf(alice)
amount = balance / 4

# Delegate to bob
veboost.boost(bob, int(amount), lock_unlock_time, sender=alice)

delegated_point = veboost.delegated(alice)
received_point = veboost.received(alice)

for i in range(10):
tx = veboost.adjusted_balance_of_write(alice, sender=bob)
delegable = veboost.delegable_balance(alice)
delegated = veboost.delegated_balance(alice)
ve_balance = ve.balanceOf(alice)

# Verify new point has been written (checkpoint)
new_point = veboost.delegated(alice)
assert new_point.ts > delegated_point.ts
delegated_point = new_point

new_point = veboost.received(alice)
assert new_point.ts > received_point.ts
received_point = new_point

# Invariant: VE balance is always the sum of delegable + delegated
assert ve_balance == delegable + delegated
assert veboost.balanceOf(alice) == tx.return_value == delegable

# Ensure bob's adjusted balance is equal to what Alice has delegated
tx = veboost.adjusted_balance_of_write(bob, sender=bob)
assert tx.return_value == veboost.balanceOf(bob)
assert veboost.delegated_balance(alice) == veboost.balanceOf(bob)
assert veboost.delegable_balance(bob) == 0 # Bob doesn't have any VE balance

chain.pending_timestamp += DAY * i
chain.mine()
39 changes: 0 additions & 39 deletions tests/test_migrate.py

This file was deleted.

0 comments on commit e03aba9

Please sign in to comment.