编译器
0.5.16+commit.9c3226ce
文件 1 的 12:Address.sol
pragma solidity ^0.5.5;
library Address {
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
function toPayable(address account) internal pure returns (address payable) {
return address(uint160(account));
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call.value(amount)("");
require(success, "Address: unable to send value, recipient may have reverted");
}
}
文件 2 的 12:Controller.sol
pragma solidity 0.5.16;
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../public/contracts/base/interface/IController.sol";
import "../public/contracts/base/interface/IStrategy.sol";
import "../public/contracts/base/interface/IVault.sol";
import "./interface/IFeeRewardForwarder.sol";
import "../public/contracts/base/inheritance/Governable.sol";
import "./interface/IHardRewards.sol";
contract Controller is IController, Governable {
using SafeERC20 for IERC20;
using Address for address;
using SafeMath for uint256;
address public constant multiSig = 0xF49440C1F012d041802b25A73e5B0B9166a75c02;
address public feeRewardForwarder;
IHardRewards public hardRewards;
uint256 public constant profitSharingNumerator = 30;
uint256 public constant profitSharingDenominator = 100;
event SharePriceChangeLog(
address indexed vault,
address indexed strategy,
uint256 oldSharePrice,
uint256 newSharePrice,
uint256 timestamp
);
mapping (address => bool) public whitelist;
mapping (bytes32 => bool) public codeWhitelist;
mapping (address => bool) public hardWorkers;
modifier onlyHardWorkerOrGovernance() {
require(hardWorkers[msg.sender] || (msg.sender == governance()),
"only hard worker can call this");
_;
}
constructor(address _storage, address _feeRewardForwarder, address[] memory _whitelist)
Governable(_storage) public {
require(_feeRewardForwarder != address(0), "feeRewardForwarder should not be empty");
feeRewardForwarder = _feeRewardForwarder;
hardWorkers[multiSig] = true;
addMultipleToWhitelist(_whitelist);
}
function addHardWorker(address _worker) public onlyGovernance {
require(_worker != address(0), "_worker must be defined");
hardWorkers[_worker] = true;
}
function removeHardWorker(address _worker) public onlyGovernance {
require(_worker != address(0), "_worker must be defined");
hardWorkers[_worker] = false;
}
function greyList(address _addr) public view returns (bool) {
return !whitelist[_addr] && !codeWhitelist[getContractHash(_addr)];
}
function addToWhitelist(address _target) public onlyGovernance {
whitelist[_target] = true;
}
function addMultipleToWhitelist(address[] memory _targets) public onlyGovernance {
for (uint256 i = 0; i < _targets.length; i++) {
whitelist[_targets[i]] = true;
}
}
function removeFromWhitelist(address _target) public onlyGovernance {
whitelist[_target] = false;
}
function removeMultipleFromWhitelist(address[] memory _targets) public onlyGovernance {
for (uint256 i = 0; i < _targets.length; i++) {
whitelist[_targets[i]] = false;
}
}
function getContractHash(address a) public view returns (bytes32 hash) {
assembly {
hash := extcodehash(a)
}
}
function addCodeToWhitelist(address _target) public onlyGovernance {
codeWhitelist[getContractHash(_target)] = true;
}
function removeCodeFromWhitelist(address _target) public onlyGovernance {
codeWhitelist[getContractHash(_target)] = false;
}
function setFeeRewardForwarder(address _feeRewardForwarder) public onlyGovernance {
require(_feeRewardForwarder != address(0), "new reward forwarder should not be empty");
feeRewardForwarder = _feeRewardForwarder;
}
function addVaultAndStrategy(address _vault, address _strategy) external onlyGovernance {
require(_vault != address(0), "new vault shouldn't be empty");
require(IVault(_vault).strategy() == address(0), "vault already has strategy");
require(_strategy != address(0), "new strategy shouldn't be empty");
IVault(_vault).setStrategy(_strategy);
}
function doHardWork(address _vault) external onlyHardWorkerOrGovernance {
uint256 oldSharePrice = IVault(_vault).getPricePerFullShare();
IVault(_vault).doHardWork();
if (address(hardRewards) != address(0)) {
hardRewards.rewardMe(msg.sender, _vault);
}
emit SharePriceChangeLog(
_vault,
IVault(_vault).strategy(),
oldSharePrice,
IVault(_vault).getPricePerFullShare(),
block.timestamp
);
}
function setHardRewards(address _hardRewards) external onlyGovernance {
hardRewards = IHardRewards(_hardRewards);
}
function salvage(address _token, uint256 _amount) external onlyGovernance {
IERC20(_token).safeTransfer(governance(), _amount);
}
function salvageStrategy(address _strategy, address _token, uint256 _amount) external onlyGovernance {
IStrategy(_strategy).salvage(governance(), _token, _amount);
}
function notifyFee(address underlying, uint256 fee) external {
if (fee > 0) {
IERC20(underlying).safeTransferFrom(msg.sender, address(this), fee);
IERC20(underlying).safeApprove(feeRewardForwarder, 0);
IERC20(underlying).safeApprove(feeRewardForwarder, fee);
IFeeRewardForwarder(feeRewardForwarder).poolNotifyFixedTarget(underlying, fee);
}
}
}
文件 3 的 12:Governable.sol
pragma solidity 0.5.16;
import "./Storage.sol";
contract Governable {
Storage public store;
constructor(address _store) public {
require(_store != address(0), "new storage shouldn't be empty");
store = Storage(_store);
}
modifier onlyGovernance() {
require(store.isGovernance(msg.sender), "Not governance");
_;
}
function setStorage(address _store) public onlyGovernance {
require(_store != address(0), "new storage shouldn't be empty");
store = Storage(_store);
}
function governance() public view returns (address) {
return store.governance();
}
}
文件 4 的 12:IController.sol
pragma solidity 0.5.16;
interface IController {
event SharePriceChangeLog(
address indexed vault,
address indexed strategy,
uint256 oldSharePrice,
uint256 newSharePrice,
uint256 timestamp
);
function greyList(address _target) external view returns(bool);
function addVaultAndStrategy(address _vault, address _strategy) external;
function doHardWork(address _vault) external;
function salvage(address _token, uint256 amount) external;
function salvageStrategy(address _strategy, address _token, uint256 amount) external;
function notifyFee(address _underlying, uint256 fee) external;
function profitSharingNumerator() external view returns (uint256);
function profitSharingDenominator() external view returns (uint256);
function feeRewardForwarder() external view returns(address);
function setFeeRewardForwarder(address _value) external;
function addHardWorker(address _worker) external;
}
文件 5 的 12:IERC20.sol
pragma solidity ^0.5.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 6 的 12:IFeeRewardForwarder.sol
pragma solidity 0.5.16;
interface IFeeRewardForwarder {
function setConversionPath(address from, address to, address[] calldata _uniswapRoute) external;
function setTokenPool(address _pool) external;
function poolNotifyFixedTarget(address _token, uint256 _amount) external;
function notifyIFarmBuybackAmount(address _token, address rewardPool, uint256 _amount) external;
}
文件 7 的 12:IHardRewards.sol
pragma solidity 0.5.16;
interface IHardRewards {
function rewardMe(address recipient, address vault) external;
}
文件 8 的 12:IStrategy.sol
pragma solidity 0.5.16;
interface IStrategy {
function unsalvagableTokens(address tokens) external view returns (bool);
function governance() external view returns (address);
function controller() external view returns (address);
function underlying() external view returns (address);
function vault() external view returns (address);
function withdrawAllToVault() external;
function withdrawToVault(uint256 amount) external;
function investedUnderlyingBalance() external view returns (uint256);
function salvage(address recipient, address token, uint256 amount) external;
function doHardWork() external;
function depositArbCheck() external view returns(bool);
}
文件 9 的 12:IVault.sol
pragma solidity 0.5.16;
interface IVault {
function initializeVault(
address _storage,
address _underlying,
uint256 _toInvestNumerator,
uint256 _toInvestDenominator
) external ;
function balanceOf(address) external view returns (uint256);
function underlyingBalanceInVault() external view returns (uint256);
function underlyingBalanceWithInvestment() external view returns (uint256);
function governance() external view returns (address);
function controller() external view returns (address);
function underlying() external view returns (address);
function strategy() external view returns (address);
function setStrategy(address _strategy) external;
function announceStrategyUpdate(address _strategy) external;
function setVaultFractionToInvest(uint256 numerator, uint256 denominator) external;
function deposit(uint256 amountWei) external;
function depositFor(uint256 amountWei, address holder) external;
function withdrawAll() external;
function withdraw(uint256 numberOfShares) external;
function getPricePerFullShare() external view returns (uint256);
function underlyingBalanceWithInvestmentForHolder(address holder) view external returns (uint256);
function doHardWork() external;
}
文件 10 的 12:SafeERC20.sol
pragma solidity ^0.5.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function callOptionalReturn(IERC20 token, bytes memory data) private {
require(address(token).isContract(), "SafeERC20: call to non-contract");
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 11 的 12:SafeMath.sol
pragma solidity ^0.5.0;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
文件 12 的 12:Storage.sol
pragma solidity 0.5.16;
contract Storage {
address public governance;
address public controller;
constructor() public {
governance = msg.sender;
}
modifier onlyGovernance() {
require(isGovernance(msg.sender), "Not governance");
_;
}
function setGovernance(address _governance) public onlyGovernance {
require(_governance != address(0), "new governance shouldn't be empty");
governance = _governance;
}
function setController(address _controller) public onlyGovernance {
require(_controller != address(0), "new controller shouldn't be empty");
controller = _controller;
}
function isGovernance(address account) public view returns (bool) {
return account == governance;
}
function isController(address account) public view returns (bool) {
return account == controller;
}
}
{
"compilationTarget": {
"contracts/Controller.sol": "Controller"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_storage","type":"address"},{"internalType":"address","name":"_feeRewardForwarder","type":"address"},{"internalType":"address[]","name":"_whitelist","type":"address[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":true,"internalType":"address","name":"strategy","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldSharePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSharePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"SharePriceChangeLog","type":"event"},{"constant":false,"inputs":[{"internalType":"address","name":"_target","type":"address"}],"name":"addCodeToWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_worker","type":"address"}],"name":"addHardWorker","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"_targets","type":"address[]"}],"name":"addMultipleToWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_target","type":"address"}],"name":"addToWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_strategy","type":"address"}],"name":"addVaultAndStrategy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"codeWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"doHardWork","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"feeRewardForwarder","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"a","type":"address"}],"name":"getContractHash","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"greyList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"hardRewards","outputs":[{"internalType":"contract IHardRewards","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hardWorkers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"multiSig","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"underlying","type":"address"},{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"notifyFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"profitSharingDenominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"profitSharingNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_target","type":"address"}],"name":"removeCodeFromWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_target","type":"address"}],"name":"removeFromWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_worker","type":"address"}],"name":"removeHardWorker","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"_targets","type":"address[]"}],"name":"removeMultipleFromWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"salvage","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"salvageStrategy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_feeRewardForwarder","type":"address"}],"name":"setFeeRewardForwarder","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_hardRewards","type":"address"}],"name":"setHardRewards","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_store","type":"address"}],"name":"setStorage","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"store","outputs":[{"internalType":"contract Storage","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}]