Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fantom tricrypto: gauge update #8

Open
wants to merge 3 commits into
base: fantom-tricrypto
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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: ftm-main-fork

# automatically fetch contract sources from Etherscan
autofetch_sources: True
Expand Down
101 changes: 39 additions & 62 deletions contracts/StrategyCurveTricrypto.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +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 IBaseFee {
function isCurrentBaseFeeAcceptable() external view returns (bool);
}

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 @@ -46,7 +23,10 @@ abstract contract StrategyCurveBase is BaseStrategy {

// Curve stuff
IGauge public constant gauge =
IGauge(0x00702BbDEaD24C40647f235F15971dB0867F6bdB); // Curve gauge contract, most are tokenized, held by strategy
IGauge(0x319E268f0A4C85D404734ee7958857F5891506d7); // 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 @@ -130,7 +110,22 @@ abstract contract StrategyCurveBase is BaseStrategy {
return balanceOfWant();
}

function _claimRewards() internal {
gaugeFactory.mint(address(gauge));
}

function claimRewards() external onlyVaultManagers {
// 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.
_claimRewards();
}

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 @@ -199,9 +194,7 @@ contract StrategyCurveTricrypto is StrategyCurveBase {
address spirit = 0x16327E3FbDaCA3bcF7E38F5Af2599D2DDc33aE52;
want.approve(address(gauge), type(uint256).max);
crv.approve(spooky, type(uint256).max);
wftm.approve(spooky, type(uint256).max);
pata-eth marked this conversation as resolved.
Show resolved Hide resolved
crv.approve(spirit, type(uint256).max);
wftm.approve(spirit, type(uint256).max);

// set our strategy's name
stratName = _name;
Expand All @@ -227,11 +220,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));
uint256 wftmBalance = wftm.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 All @@ -247,10 +241,6 @@ contract StrategyCurveTricrypto is StrategyCurveBase {
_sellToken(address(crv), crvBalance);
}
}
// sell WFTM if we have any
if (wftmBalance > 0) {
_sellToken(address(wftm), wftmBalance);
}

uint256 wethBalance = weth.balanceOf(address(this));
uint256 wbtcBalance = wbtc.balanceOf(address(this));
Expand Down Expand Up @@ -294,32 +284,19 @@ contract StrategyCurveTricrypto is StrategyCurveBase {
forceHarvestTriggerOnce = false;
}

// Sells our CRV, WFTM, or GEIST for our target token
// Sells our CRV for our target token
function _sellToken(address token, uint256 _amount) internal {
if (token == address(wftm)) {
address[] memory tokenPath = new address[](2);
tokenPath[0] = address(wftm);
tokenPath[1] = address(targetToken);
IUniswapV2Router02(router).swapExactTokensForTokens(
_amount,
uint256(0),
tokenPath,
address(this),
block.timestamp
);
} else {
address[] memory tokenPath = new address[](3);
tokenPath[0] = address(token);
tokenPath[1] = address(wftm);
tokenPath[2] = address(targetToken);
IUniswapV2Router02(router).swapExactTokensForTokens(
_amount,
uint256(0),
tokenPath,
address(this),
block.timestamp
);
}
address[] memory tokenPath = new address[](3);
tokenPath[0] = address(token);
tokenPath[1] = address(wftm);
tokenPath[2] = address(targetToken);
IUniswapV2Router02(router).swapExactTokensForTokens(
_amount,
uint256(0),
tokenPath,
address(this),
block.timestamp
);
}

/* ========== KEEP3RS ========== */
Expand Down
130 changes: 7 additions & 123 deletions contracts/interfaces/curve.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,138 +2,22 @@
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 claimable_reward(address _addressToCheck, address _rewardToken)
external
view
returns (uint256);
function claimable_tokens(address) external returns (uint256);

function withdraw(uint256) 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 IGaugeFactory {
function mint(address _gauge) external;
}

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

interface IMinter {
function mint(address) external;
interface ICurveFi {
function add_liquidity(uint256[3] calldata amounts, uint256 min_mint_amount)
external
payable;
}
43 changes: 0 additions & 43 deletions contracts/interfaces/yearn.sol

This file was deleted.

Loading