-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
52f84b0
commit de77895
Showing
383 changed files
with
63,255 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
Oops, something went wrong.