Skip to content

Commit

Permalink
gauge update
Browse files Browse the repository at this point in the history
  • Loading branch information
pata.eth committed May 22, 2022
1 parent a17fd32 commit 5a67538
Show file tree
Hide file tree
Showing 10 changed files with 206 additions and 263 deletions.
2 changes: 1 addition & 1 deletion brownie-config.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# use Ganache's forked mainnet mode as the default network
# NOTE: You don't *have* to do this, but it is often helpful for testing
networks:
default: mainnet-fork
default: arb-main-fork

# automatically fetch contract sources from Etherscan
autofetch_sources: True
Expand Down
65 changes: 39 additions & 26 deletions contracts/StrategyCurveTricrypto.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,9 @@ import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/math/Math.sol";

import "./interfaces/curve.sol";
import "./interfaces/yearn.sol";
import {IUniswapV2Router02} from "./interfaces/uniswap.sol";
import {
BaseStrategy,
StrategyParams
} from "@yearnvaults/contracts/BaseStrategy.sol";

interface IUniV3 {
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}

function exactInput(ExactInputParams calldata params)
external
payable
returns (uint256 amountOut);
}
import { IGauge, IGaugeFactory, ICurveFi } from "./interfaces/curve.sol";
import { IUniswapV2Router02 } from "./interfaces/uniswap.sol";
import { BaseStrategy, StrategyParams } from "@yearnvaults/contracts/BaseStrategy.sol";

abstract contract StrategyCurveBase is BaseStrategy {
using SafeERC20 for IERC20;
Expand All @@ -42,7 +23,10 @@ abstract contract StrategyCurveBase is BaseStrategy {

// Curve stuff
IGauge public constant gauge =
IGauge(0x97E2768e8E73511cA874545DC5Ff8067eB19B787); // Curve gauge contract, most are tokenized, held by strategy
IGauge(0x555766f3da968ecBefa690Ffd49A2Ac02f47aa5f); // Curve gauge contract, most are tokenized, held by strategy

IGaugeFactory public constant gaugeFactory =
IGaugeFactory(0xabC000d88f23Bb45525E447528DBF656A9D55bf5);

// keepCRV stuff
uint256 public keepCRV; // the percentage of CRV we re-lock for boost (in basis points)
Expand Down Expand Up @@ -125,7 +109,34 @@ abstract contract StrategyCurveBase is BaseStrategy {
return balanceOfWant();
}

function claimRewards() internal {
// Claims any pending CRV
//
// Mints claimable CRV from the factory gauge. Reward tokens are sent to `msg.sender`
// The method claim_rewards() from the old gauge now only applies to third-party tokens.
// There are no third-party tokens in this strategy.
gaugeFactory.mint(address(gauge));
}

function claimAndTransferRewards(address _targetAdress)
external
onlyVaultManagers
{
require(_targetAdress != address(0));

// Claim any pending rewards and transfer CRV balance to the new strategy
claimRewards();

uint256 crvBalance = crv.balanceOf(address(this));

if (crvBalance > 0) {
crv.safeTransfer(_targetAdress, crvBalance);
}
}

function prepareMigration(address _newStrategy) internal override {
// Withdraw LP tokens from the gauge. The transfer to the new strategy is done
// by migrate() in BaseStrategy.sol
uint256 _stakedBal = stakedBalance();
if (_stakedBal > 0) {
gauge.withdraw(_stakedBal);
Expand Down Expand Up @@ -225,10 +236,12 @@ contract StrategyCurveTricrypto is StrategyCurveBase {
uint256 _debtPayment
)
{
// harvest our rewards from the gauge
gauge.claim_rewards();
// Claim and get a fresh snapshot of the strategy's CRV balance
claimRewards();

uint256 crvBalance = crv.balanceOf(address(this));
// if we claimed any CRV, then sell it

// Sell CRV if we have any
if (crvBalance > 0) {
// keep some of our CRV to increase our boost
uint256 sendToVoter = crvBalance.mul(keepCRV).div(FEE_DENOMINATOR);
Expand Down
124 changes: 5 additions & 119 deletions contracts/interfaces/curve.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,138 +2,24 @@
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";

interface IGauge {
function deposit(uint256) external;

function balanceOf(address) external view returns (uint256);

function claim_rewards() external;

function claimable_tokens(address) external view returns (uint256);
function withdraw(uint256) external;

function claimable_reward(address _addressToCheck, address _rewardToken)
external
view
returns (uint256);
function claimable_tokens(address) external returns (uint256);
}

function withdraw(uint256) external;
interface IGaugeFactory {
function mint(address _gauge) external;
}

interface ICurveFi {
function get_virtual_price() external view returns (uint256);

function add_liquidity(
// EURt
uint256[2] calldata amounts,
uint256 min_mint_amount
) external payable;

function add_liquidity(
// Compound, sAave
uint256[2] calldata amounts,
uint256 min_mint_amount,
bool _use_underlying
) external payable returns (uint256);

function add_liquidity(
// Iron Bank, Aave
uint256[3] calldata amounts,
uint256 min_mint_amount,
bool _use_underlying
) external payable returns (uint256);

function add_liquidity(
// 3Crv Metapools
address pool,
uint256[4] calldata amounts,
uint256 min_mint_amount
) external;

function add_liquidity(
// Y and yBUSD
uint256[4] calldata amounts,
uint256 min_mint_amount,
bool _use_underlying
) external payable returns (uint256);

function add_liquidity(
// 3pool
uint256[3] calldata amounts,
uint256 min_mint_amount
) external payable;

function add_liquidity(
// sUSD
uint256[4] calldata amounts,
uint256 min_mint_amount
) external payable;

function remove_liquidity_imbalance(
uint256[2] calldata amounts,
uint256 max_burn_amount
) external;

function remove_liquidity(uint256 _amount, uint256[2] calldata amounts)
external;

function remove_liquidity_one_coin(
uint256 _token_amount,
int128 i,
uint256 min_amount
) external;

function exchange(
int128 from,
int128 to,
uint256 _from_amount,
uint256 _min_to_amount
) external;

function balances(uint256) external view returns (uint256);

function get_dy(
int128 from,
int128 to,
uint256 _from_amount
) external view returns (uint256);

// EURt
function calc_token_amount(uint256[2] calldata _amounts, bool _is_deposit)
external
view
returns (uint256);

// 3Crv Metapools
function calc_token_amount(
address _pool,
uint256[4] calldata _amounts,
bool _is_deposit
) external view returns (uint256);

// sUSD, Y pool, etc
function calc_token_amount(uint256[4] calldata _amounts, bool _is_deposit)
external
view
returns (uint256);

// 3pool, Iron Bank, etc
function calc_token_amount(uint256[3] calldata _amounts, bool _is_deposit)
external
view
returns (uint256);

function calc_withdraw_one_coin(uint256 amount, int128 i)
external
view
returns (uint256);
}

interface ICrvV3 is IERC20 {
function minter() external view returns (address);
}

interface IMinter {
function mint(address) external;
}
43 changes: 0 additions & 43 deletions contracts/interfaces/yearn.sol

This file was deleted.

35 changes: 24 additions & 11 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pytest
from brownie import config, Wei, Contract
from brownie import config, Contract, interface

# Snapshots the chain before each test and reverts after test completion.
@pytest.fixture(autouse=True)
Expand All @@ -11,14 +11,14 @@ def isolation(fn_isolation):
def whale(accounts):
# Totally in it for the tech
# Update this with a large holder of your want token (the largest EOA holder of LP)
whale = accounts.at("0xd2d2F6a38F3A323Df87346413269cdB62cBDDB71", force=True)
whale = accounts.at("0xA86D37706162B45ABB83C8C93d380CFE5cD472Ed", force=True)
yield whale


# this is the amount of funds we have our whale deposit. adjust this as needed based on their wallet balance
@pytest.fixture(scope="module")
def amount():
amount = 500e18
def amount(token, whale):
amount = token.balanceOf(whale) // 2
yield amount


Expand Down Expand Up @@ -47,7 +47,7 @@ def no_profit():
@pytest.fixture(scope="module")
def gauge():
# this should be the address of the convex deposit token
gauge = "0x97E2768e8E73511cA874545DC5Ff8067eB19B787"
gauge = "0x555766f3da968ecBefa690Ffd49A2Ac02f47aa5f"
yield Contract(gauge)


Expand All @@ -66,6 +66,13 @@ def token():
yield Contract(token_address)


@pytest.fixture(scope="module")
def crv():
# this should be the address of the ERC-20 used by the strategy/vault
crv_address = "0x11cDb42B0EB46D95f990BeDD4695A6e3fA034978"
yield interface.IERC20(crv_address)


# Only worry about changing things above this line
# ----------------------------------------------------------------------- #
# FOR NOW THIS IS DAI, since SMS isn't verified on dumb arbiscan
Expand All @@ -84,6 +91,13 @@ def other_vault_strategy():
yield Contract("0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1")


# only applicable if you are migrating an existing strategy (i.e., you are not
# deploying a brand new one). This strat is using an old version of a curve gauge
@pytest.fixture(scope="module")
def strategy_to_migrate_from():
yield Contract("0x19e70E3195fEC1A33745D9260Bf26c3f915Bb0CC")


@pytest.fixture(scope="module")
def healthCheck():
yield Contract("0x32059ccE723b4DD15dD5cb2a5187f814e6c470bC")
Expand All @@ -101,7 +115,7 @@ def zero_address():
# normal gov is ychad, 0xFEB4acf3df3cDEA7399794D0869ef76A6EfAff52
@pytest.fixture(scope="module")
def gov(accounts):
yield accounts.at("0xC0E2830724C946a6748dDFE09753613cd38f6767", force=True)
yield accounts.at("0xb6bc033D34733329971B938fEf32faD7e98E56aD", force=True)


@pytest.fixture(scope="module")
Expand Down Expand Up @@ -153,11 +167,10 @@ def vault(pm, gov, rewards, guardian, management, token, chain):
yield vault


# use this if your vault is already deployed
# @pytest.fixture(scope="function")
# def vault(pm, gov, rewards, guardian, management, token, chain):
# vault = Contract("0x497590d2d57f05cf8B42A36062fA53eBAe283498")
# yield vault
@pytest.fixture(scope="function")
def vaultDeployed():
vaultDeployed = Contract("0x239e14A19DFF93a17339DCC444f74406C17f8E67")
yield vaultDeployed


# replace the first value with the name of your strategy
Expand Down
18 changes: 18 additions & 0 deletions tests/test_liq_gauge.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from brownie import chain


def test_gauge_is_properly_setup(gauge):

assert (
gauge.reward_count() == 0
), "Third-party reward tokens not expected for this strategy"

WEEK = 86400 * 7

weeksNum = chain.time() // WEEK

# Pull current inflation_rate and verify it's not 0; i.e., the
# reward APY is greater than 0%.
assert (
gauge.inflation_rate(weeksNum) is not 0
), "This gauge is not currently rewarding any CRV"
Loading

0 comments on commit 5a67538

Please sign in to comment.