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

Add barnbridge strategy #82

Open
wants to merge 19 commits into
base: main
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
14 changes: 14 additions & 0 deletions .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ REPORT_GAS=false
# CURVE_3POOL_MINTR=0xd061D61a4d941c39E5453435B6345Dc261C2fcE0
# CURVE_CRV=0xD533a949740bb3306d119CC777fa900bA034cd52

# StrategyBarnBridgeUSDC
# BARN_BRIDGE_USDC_SMART_YIELD=0x4B8d90D68F26DEF303Dcb6CFc9b63A1aAEC15840
# BARN_BRIDGE_USDC_COMP_PROVIDER_POOL=0xDAA037F99d168b552c0c61B7Fb64cF7819D78310
# BARN_BRIDGE_USDC_YIELD_FARM=0x68Af34129755091E22F91899cEAC48657e5a5062
# BARN_BRIDGE_BOND=0x0391D2021f89DC339F60Fff84546EA23E337750f

# StrategyBarnBridgeDAI
# BARN_BRIDGE_DAI_SMART_YIELD=0x673f9488619821aB4f4155FdFFe06f6139De518F
# BARN_BRIDGE_DAI_COMP_PROVIDER_POOL=0xe6c1A8E7a879d7feBB8144276a62f9a6b381bd37
# Currently BarnBride Yield Farm does not support DAI
# BARN_BRIDGE_DAI_YIELD_FARM=

# IMPERSONATED_DEPLOYER=0xab5801a7d398351b8be11c439e05c5b3259aec9b
# ETH_FUNDER=0xab5801a7d398351b8be11c439e05c5b3259aec9b
# DAI_FUNDER=0xf977814e90da44bfa03b6295a0616a897441acec
Expand All @@ -95,6 +107,7 @@ REPORT_GAS=false
# WETH_FUNDER=0x0f4ee9631f4be0a63756515141281a3e2b293bbe
# COMPOUND_COMP_FUNDER=0xbe0eb53f46cd790cd13851d5eff43d12404d33e8
# CURVE_CRV_FUNDER=0xf977814e90da44bfa03b6295a0616a897441acec
# BARN_BRIDGE_BOND_FUNDER=0x0F4ee9631f4be0a63756515141281A3E2B293Bbe

# DUMMY_ASSET=
# DUMMY_FUNDER=
Expand All @@ -107,6 +120,7 @@ REPORT_GAS=false
# STRATEGY_CURVE_3POOL_DAI=
# STRATEGY_CURVE_3POOL_USDC=
# STRATEGY_CURVE_3POOL_USDT=
# STRATEGY_BARN_BRIDGE_JC_USDC=

# ROLLUP_CHAIN=
# REGISTRY=
190 changes: 190 additions & 0 deletions contracts/strategies/StrategyBarnBridgeJToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

import "./interfaces/BarnBridge/IISmartYield.sol";
import "./interfaces/BarnBridge/IYieldFarmContinuous.sol";
import "./dependencies/BarnBridge/SmartYield.sol";
import "./dependencies/BarnBridge/YieldFarm/YieldFarmContinuous.sol";

import "./interfaces/IStrategy.sol";
import "./interfaces/uniswap/IUniswapV2.sol";

/**
* @notice Deposits ERC20 token into Barn Bridge Smart Yield and issues stBarnBridgeJToken(e.g. stBarnBridgeJcUSDC) in L2.
*/
contract StrategyBarnBridgeJToken is IStrategy, Ownable {
using SafeERC20 for IERC20;
using Address for address;
using SafeMath for uint256;

// The address of BarnBridge smart yield
address public smartYield;
SmartYield smartYieldContract;
// The address of compound provider pool
address public compProviderPool;

// Info of supplying erc20 token to Smart Yield
// The symbol of the supplying token
string public symbol;
// The address of supplying token(e.g. USDC, DAI)
address public supplyToken;

// The address of junior token(e.g. bb_cUSDC, bb_cDAI)
// This address is the same as the smartYield address
address public jToken;

// The address of BarnBridge Yield Farom Continuous
address public yieldFarm;
YieldFarmContinuous yieldFarmContract;
// The address of BarnBridge governance token
address public bond;

address public uniswap;

address public controller;

constructor(
address _smartYield,
address _compProviderPool,
string memory _symbol,
address _yieldFarm,
address _supplyToken,
address _bond,
address _uniswap,
address _controller
) {
smartYield = _smartYield;
smartYieldContract = SmartYield(_smartYield);
compProviderPool = _compProviderPool;
symbol = _symbol;
supplyToken = _supplyToken;
jToken = _smartYield;
yieldFarm = _yieldFarm;
yieldFarmContract = YieldFarmContinuous(_yieldFarm);
bond = _bond;
uniswap = _uniswap;
controller = _controller;
}

/**
* @dev Require that the caller must be an EOA account to avoid flash loans.
*/
modifier onlyEOA() {
require(msg.sender == tx.origin, "Not EOA");
_;
}

function getAssetAddress() external view override returns (address) {
return supplyToken;
}

function syncBalance() external override returns (uint256) {
uint256 jTokenBalance = yieldFarmContract.balances(address(this));
// Calculate share of jTokenBalance in the debt
uint256 forfeits = calForfeits(jTokenBalance);
// jTokenPrice is jToken price * 1e18
uint256 jTokenPrice = IISmartYield(smartYield).price();
return jTokenBalance.mul(jTokenPrice).div(1e18).sub(forfeits);
}

function calForfeits(uint256 jTokenAmount) public view returns (uint256) {
// share of jTokenAmount in the debt
uint256 debtShare = jTokenAmount.mul(1e18).div(IERC20(jToken).totalSupply());
uint256 forfeits = IISmartYield(smartYield).abondDebt().mul(debtShare).div(1e18);
return forfeits;
}

function harvest() external override onlyEOA {
IYieldFarmContinuous(yieldFarm).claim();
uint256 bondBalance = IERC20(bond).balanceOf(address(this));
if (bondBalance > 0) {
// Sell BOND for more supplying token(e.g. USDC, DAI)
IERC20(bond).safeIncreaseAllowance(uniswap, bondBalance);

address[] memory paths = new address[](2);
paths[0] = bond;
paths[1] = supplyToken;

IUniswapV2(uniswap).swapExactTokensForTokens(
bondBalance,
uint256(0),
paths,
address(this),
block.timestamp.add(1800)
);

uint256 obtainedSupplyTokenAmount = IERC20(supplyToken).balanceOf(address(this));
IERC20(supplyToken).safeIncreaseAllowance(compProviderPool, obtainedSupplyTokenAmount);
IISmartYield(smartYield).buyTokens(
obtainedSupplyTokenAmount,
uint256(0),
block.timestamp.add(1800)
);

// Stake junior token(e.g. bb_cUSDC, bb_cDAI) to Yield Farm for earn BOND token
uint256 jTokenBalance = IERC20(jToken).balanceOf(address(this));
IERC20(jToken).safeIncreaseAllowance(yieldFarm, jTokenBalance);
IYieldFarmContinuous(yieldFarm).deposit(jTokenBalance);
}
}

function aggregateCommit(uint256 _commitAmount) external override {
require(msg.sender == controller, "Not controller");
require(_commitAmount > 0, "Nothing to commit");

// Pull supplying token(e.g. USDC, DAI) from Controller
IERC20(supplyToken).safeTransferFrom(msg.sender, address(this), _commitAmount);

// Buy junior token(e.g. bb_cUSDC, bb_cDAI)
IERC20(supplyToken).safeIncreaseAllowance(compProviderPool, _commitAmount);
IISmartYield(smartYield).buyTokens(
_commitAmount,
uint256(0),
block.timestamp.add(1800)
);

// Stake junior token to Yield Farm for earn BOND token
uint256 jTokenBalance = IERC20(jToken).balanceOf(address(this));
IERC20(jToken).safeIncreaseAllowance(yieldFarm, jTokenBalance);
IYieldFarmContinuous(yieldFarm).deposit(jTokenBalance);

emit Committed(_commitAmount);
}

function aggregateUncommit(uint256 _uncommitAmount) external override {
require(msg.sender == controller, "Not controller");
require(_uncommitAmount > 0, "Nothing to uncommit");

// Unstake junior token(e.g. bb_cUSDC, bb_cDAI) from Yield Farm
// jTokenPrice is junior token price * 1e18
uint256 jTokenPrice = ISmartYield(smartYield).price();
uint256 jTokenWithdrawAmount = _uncommitAmount.mul(1e18).div(jTokenPrice);
IYieldFarmContinuous(yieldFarm).withdraw(jTokenWithdrawAmount);

// Instant withdraw
IISmartYield(smartYield).sellTokens(
jTokenWithdrawAmount,
uint256(0),
block.timestamp.add(1800)
);

// Transfer supply token to Controller
uint256 supplyTokenBalance = IERC20(supplyToken).balanceOf(address(this));
IERC20(supplyToken).safeTransfer(controller, supplyTokenBalance);

emit UnCommitted(_uncommitAmount);
}

function setController(address _controller) external onlyOwner {
emit ControllerChanged(controller, _controller);
controller = _controller;
}
}
46 changes: 46 additions & 0 deletions contracts/strategies/dependencies/BarnBridge/Governed.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.6.0 <0.8.0;
pragma abicoder v2;

abstract contract Governed {

address public dao;
address public guardian;

modifier onlyDao {
require(
dao == msg.sender,
"GOV: not dao"
);
_;
}

modifier onlyDaoOrGuardian {
require(
msg.sender == dao || msg.sender == guardian,
"GOV: not dao/guardian"
);
_;
}

constructor()
{
dao = msg.sender;
guardian = msg.sender;
}

function setDao(address dao_)
external
onlyDao
{
dao = dao_;
}

function setGuardian(address guardian_)
external
onlyDao
{
guardian = guardian_;
}

}
13 changes: 13 additions & 0 deletions contracts/strategies/dependencies/BarnBridge/IBond.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.6.0 <0.8.0;
pragma abicoder v2;

import "@openzeppelin/contracts/token/ERC721/IERC721.sol";

interface IBond is IERC721 {
function smartYield() external view returns (address);

function mint(address to, uint256 tokenId) external;

function burn(uint256 tokenId) external;
}
Loading