Skip to content

Commit

Permalink
feat: remove curve oracle from redemption contract (#232)
Browse files Browse the repository at this point in the history
* feat: remove curve oracle from redemption contract

* fix: tests

* chore: update ape version

* feat: add oracle price comparison test
  • Loading branch information
0xkorin authored Dec 1, 2023
1 parent d30ab01 commit 229528b
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 33 deletions.
19 changes: 2 additions & 17 deletions contracts/Redemption.vy
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,13 @@ interface AggregatorV3Interface:
interface IDYFI:
def burn(owner: address, amount: uint256): nonpayable

interface CurvePoolInterface:
def price_oracle() -> uint256: view

UNIT: constant(uint256) = 10**18
SLIPPAGE_TOLERANCE: constant(uint256) = 3
SLIPPAGE_DENOMINATOR: constant(uint256) = 1000

DYFI: immutable(IDYFI)
YFI: immutable(ERC20)
VEYFI: immutable(ERC20)
CURVE_POOL: immutable(CurvePoolInterface)
PRICE_FEED: immutable(AggregatorV3Interface)

# @dev Returns the address of the current owner.
Expand Down Expand Up @@ -101,14 +97,13 @@ A11: constant(int256) = 1_064_49_445_891_785_942_956
@external
def __init__(
yfi: address, d_yfi: address, ve_yfi: address, owner: address,
price_feed: address, curve_pool: address, scaling_factor: uint256,
price_feed: address, scaling_factor: uint256,
):
assert scaling_factor >= UNIT and scaling_factor <= 12 * UNIT
YFI = ERC20(yfi)
DYFI = IDYFI(d_yfi)
VEYFI = ERC20(ve_yfi)
PRICE_FEED = AggregatorV3Interface(price_feed)
CURVE_POOL = CurvePoolInterface(curve_pool)
self._transfer_ownership(owner)
self.payee = owner
self.packed_scaling_factor = shift(scaling_factor, 128) | shift(scaling_factor, 192)
Expand Down Expand Up @@ -189,24 +184,14 @@ def get_latest_price() -> uint256:
@internal
@view
def _get_latest_price() -> uint256:
oracle_price: uint256 = convert(self._get_oracle_price(), uint256)
pool_price: uint256 = CURVE_POOL.price_oracle()
if pool_price < oracle_price:
return oracle_price
return pool_price


@internal
@view
def _get_oracle_price() -> int256:
round_id: uint80 = 0
price: int256 = 0
started_at: uint256 = 0
updated_at: uint256 = 0
answered_in_round: uint80 = 0
(round_id, price, started_at, updated_at, answered_in_round) = PRICE_FEED.latestRoundData()
assert updated_at + 3600 > block.timestamp, "price too old"
return price
return convert(price, uint256)


@external
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
black==22.3.0
eth-ape==0.6.20
eth-ape==0.6.26
1 change: 0 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ def redemption(accounts, project, yfi, d_yfi, ve_yfi):
ve_yfi,
accounts[0],
oft,
"0xc26b89a667578ec7b3f11b2f98d6fd15c07c54ba",
10**18,
sender=accounts[0],
)
Expand Down
38 changes: 24 additions & 14 deletions tests/functional/test_redemption.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,13 @@ def test_sweep(d_yfi, yfi, redemption, gov):
def test_oracle(project, yfi, d_yfi, ve_yfi, gov):
mock = project.MockOracle.deploy(sender=gov)
redemption = project.Redemption.deploy(
yfi, d_yfi, ve_yfi, gov, mock, mock, 10 * AMOUNT, sender=gov
yfi, d_yfi, ve_yfi, gov, mock, 10 * AMOUNT, sender=gov
)

mock.set_price(2 * AMOUNT, AMOUNT, sender=gov)
assert redemption.get_latest_price() == 2 * AMOUNT

mock.set_price(2 * AMOUNT, 3 * AMOUNT, sender=gov)
mock.set_price(3 * AMOUNT, 2 * AMOUNT, sender=gov)
assert redemption.get_latest_price() == 3 * AMOUNT

mock.set_updated(1, sender=gov)
Expand All @@ -166,21 +166,31 @@ def test_chainlink_oracle(project, yfi, d_yfi, ve_yfi, gov):
assert actual == expected
assert abs(yfieth.latestRoundData()[1] - actual) / actual <= 0.01

mock = project.MockOracle.deploy(sender=gov)
mock.set_price(AMOUNT, AMOUNT, sender=gov)

redemption = project.Redemption.deploy(
yfi, d_yfi, ve_yfi, gov, combined, mock, 10 * AMOUNT, sender=gov
yfi, d_yfi, ve_yfi, gov, combined, 10 * AMOUNT, sender=gov
)
assert redemption.get_latest_price() == actual


def test_curve_oracle(project, yfi, d_yfi, ve_yfi, gov):
mock = project.MockOracle.deploy(sender=gov)
mock.set_price(AMOUNT, AMOUNT, sender=gov)
curve = project.MockOracle.at("0xC26b89A667578ec7b3f11b2F98d6Fd15C07C54ba")
redemption = project.Redemption.deploy(
yfi, d_yfi, ve_yfi, gov, mock, curve, 10 * AMOUNT, sender=gov
def test_redeployment_oracle(chain, accounts, project, d_yfi, ve_yfi, gov):
ychad = accounts["0xFEB4acf3df3cDEA7399794D0869ef76A6EfAff52"]
pool = ape.Contract("0xC26b89A667578ec7b3f11b2F98d6Fd15C07C54ba")
yfi = ape.Contract("0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e")
yfi.approve(pool, 1000 * AMOUNT, sender=ychad)
pool.exchange(1, 0, 100 * AMOUNT, 0, sender=ychad)
chain.pending_timestamp += 60
pool.exchange(1, 0, 100 * AMOUNT, 0, sender=ychad)
chain.pending_timestamp += 60
pool.exchange(1, 0, 100 * AMOUNT, 0, sender=ychad)

old = ape.Contract("0x2fBa208E1B2106d40DaA472Cb7AE0c6C7EFc0224")
new = project.Redemption.deploy(
yfi,
d_yfi,
ve_yfi,
gov,
"0x3EbEACa272Ce4f60E800f6C5EE678f50D2882fd4",
10 * AMOUNT,
sender=gov,
)
actual = curve.price_oracle()
assert redemption.get_latest_price() == actual
assert old.get_latest_price() == new.get_latest_price()

0 comments on commit 229528b

Please sign in to comment.