Skip to content

Commit

Permalink
feat: add remaining contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
StakeDAOHQ committed Feb 28, 2022
1 parent 52f84b0 commit de77895
Show file tree
Hide file tree
Showing 383 changed files with 63,255 additions and 0 deletions.
116 changes: 116 additions & 0 deletions angle/contracts/BaseStrategy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.2;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import "./interfaces/IController.sol";

abstract contract BaseStrategy {
using SafeERC20 for IERC20;
using Address for address;

uint256 public performanceFee = 1500;
uint256 public withdrawalFee = 50;
uint256 public constant FEE_DENOMINATOR = 10000;

address public governance;
address public controller;
address public strategist;
address public want;

uint256 public earned;

event Harvested(uint256 wantEarned, uint256 lifetimeEarned);

constructor(address _controller, address _want) {
governance = msg.sender;
strategist = msg.sender;
controller = _controller;
want = _want;
}

modifier onlyGovernance() {
require(msg.sender == governance, "!governance");
_;
}

modifier onlyController() {
require(msg.sender == controller, "!controller");
_;
}

modifier onlyAdmin() {
require(msg.sender == controller || msg.sender == strategist, "!admin");
_;
}

function clean(IERC20 _asset) external onlyGovernance returns (uint256 balance) {
require(want != address(_asset), "want");
balance = _asset.balanceOf(address(this));
_asset.safeTransfer(governance, balance);
}

function withdraw(uint256 _amount) external virtual onlyController {
uint256 _balance = IERC20(want).balanceOf(address(this));

if (_balance < _amount) {
_withdrawSome(_amount - _balance);
}

uint256 _fee = _amount * withdrawalFee / FEE_DENOMINATOR;
IERC20(want).safeTransfer(IController(controller).rewards(), _fee);
address _vault = IController(controller).vaults(address(want));
require(_vault != address(0), "!vault");
IERC20(want).safeTransfer(_vault, _amount - _fee);
}

function withdrawAll() external virtual onlyController returns (uint256 balance) {
_withdrawSome(balanceOfPool());

balance = IERC20(want).balanceOf(address(this));

address _vault = IController(controller).vaults(address(want));
require(_vault != address(0), "!vault");
IERC20(want).safeTransfer(_vault, balance);
}

function balanceOfWant() public view returns (uint256) {
return IERC20(want).balanceOf(address(this));
}

function balanceOf() public view returns (uint256) {
return balanceOfWant() + balanceOfPool();
}

function setWithdrawalFee(uint256 _withdrawalFee) external onlyGovernance {
withdrawalFee = _withdrawalFee;
}

function setPerformanceFee(uint256 _performanceFee) external onlyGovernance {
performanceFee = _performanceFee;
}

function setStrategist(address _strategist) external onlyGovernance {
strategist = _strategist;
}

function setGovernance(address _governance) external onlyGovernance {
governance = _governance;
}

function setController(address _controller) external onlyGovernance {
controller = _controller;
}

/* Implemented by strategy */

function name() external pure virtual returns (string memory);

function balanceOfPool() public view virtual returns (uint256);

function deposit() public virtual;

function _withdrawSome(uint256 _amount) internal virtual;
}
111 changes: 111 additions & 0 deletions angle/contracts/Controller.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.2;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

import "./interfaces/IStrategy.sol";

contract Controller {
using SafeERC20 for IERC20;
using Address for address;
//using SafeMath for uint256;

address public governance;
address public strategist;

address public rewards;
mapping(address => address) public vaults;
mapping(address => address) public strategies;

mapping(address => mapping(address => bool)) public approvedStrategies;

uint256 public constant max = 10000;

event SetStrategy(address indexed asset, address indexed strategy);
event ApproveStrategy(address indexed asset, address indexed strategy);
event SetVault(address indexed asset, address indexed vault);

constructor(address _rewards) {
governance = msg.sender;
strategist = msg.sender;
rewards = _rewards;
}

modifier onlyGovernance() {
require(msg.sender == governance, "!gov");
_;
}

modifier onlyAdmin() {
require(msg.sender == governance || msg.sender == strategist, "!(gov||strategist)");
_;
}

function setRewards(address _rewards) public onlyGovernance {
rewards = _rewards;
}

function setStrategist(address _strategist) public onlyGovernance {
strategist = _strategist;
}

function setGovernance(address _governance) public onlyGovernance {
governance = _governance;
}

function setVault(address _token, address _vault) public {
require(msg.sender == strategist || msg.sender == governance, "!strategist");
require(vaults[_token] == address(0), "vault");
vaults[_token] = _vault;
emit SetVault(_token, _vault);
}

function approveStrategy(address _token, address _strategy) public onlyGovernance {
approvedStrategies[_token][_strategy] = true;
emit ApproveStrategy(_token, _strategy);
}

function revokeStrategy(address _token, address _strategy) public onlyGovernance {
approvedStrategies[_token][_strategy] = false;
}

function setStrategy(address _token, address _strategy) public onlyAdmin {
require(approvedStrategies[_token][_strategy] == true, "!approved");

address _current = strategies[_token];
if (_current != address(0)) {
IStrategy(_current).withdrawAll();
}
strategies[_token] = _strategy;
emit SetStrategy(_token, _strategy);
}

function earn(address _token, uint256 _amount) public {
address _strategy = strategies[_token];
IERC20(_token).safeTransfer(_strategy, _amount);
IStrategy(_strategy).deposit();
}

function balanceOf(address _token) external view returns (uint256) {
return IStrategy(strategies[_token]).balanceOf();
}

function withdrawAll(address _token) public onlyAdmin {
IStrategy(strategies[_token]).withdrawAll();
}

function inCaseTokensGetStuck(address _token, uint256 _amount) public onlyAdmin {
IERC20(_token).safeTransfer(msg.sender, _amount);
}

function inCaseStrategyTokenGetStuck(address _strategy, address _token) public onlyAdmin {
IStrategy(_strategy).withdraw(_token);
}

function withdraw(address _token, uint256 _amount) public {
require(msg.sender == vaults[_token], "!vault");
IStrategy(strategies[_token]).withdraw(_amount);
}
}
Loading

0 comments on commit de77895

Please sign in to comment.