pragma solidity ^0.6.12; 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 decimals() external view returns (uint); 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); } 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) { // Solidity only automatically asserts when dividing by 0 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; } } library Address { function isContract(address account) internal view returns (bool) { bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != 0x0 && codehash != accountHash); } 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"); // solhint-disable-next-line avoid-call-value (bool success, ) = recipient.call.value(amount)(""); require(success, "Address: unable to send value, recipient may have reverted"); } } 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 callOptionalReturn(IERC20 token, bytes memory data) private { require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } interface StrategyKeep3r { function workable() external view returns (bool); function harvest(address) external; function forceHarvest(address) external; } interface VaultKeep3r { function earnable(address) external returns(bool); function earn(address) external; function forceEarn(address) external; } interface IKeep3rEscrow { function isKeep3rEscrow() external pure returns (bool); function returnLPsToGovernance() external /*onlyGovernor*/; function addLiquidityToJob(address liquidity, address job, uint amount) external /*onlyGovernor*/; function applyCreditToJob(address provider, address liquidity, address job) external /*onlyGovernor*/; function unbondLiquidityFromJob(address liquidity, address job, uint amount) external /*onlyGovernor*/; function removeLiquidityFromJob(address liquidity, address job) external /*onlyGovernor*/; } interface Uni { function swapExactTokensForTokens(uint, uint, address[] calldata, address, uint) external; } contract metaKeep3r { using SafeERC20 for IERC20; using Address for address; using SafeMath for uint256; // escrow contract of KP3R LP tokens IKeep3rEscrow[] escrow; // these 2 are for v1 => interface is done VaultKeep3r vKeep3rsv1; StrategyKeep3r[] sKeep3rsv1; // v2s are here => interface hasn't been done VaultKeep3rV2[] vKeep3rsv2; StrategyKeep3rV2[] sKeep3rsv2; constructor() public { // there are 2 escrow contracts escrow.push(IKeep3rEscrow(address(0x9fA395901A92490D1496c94a8578e1f4eF9fB1d1))); escrow.push(IKeep3rEscrow(address(0x8f2245D1051f3777E314ba6FdEe1152774CE868C))); // keep3r for all v1 vaults vKeep3rsv1 = VaultKeep3r(address(0xd0aC37E3524F295D141d3839d5ed5F26A40b589D)); // v1 curve strategy keep3r sKeep3rsv1.push(StrategyKeep3r(address(0x054A87DdFdE3ccb5DDB03739375329BcC1b03203))); // for eth & else maybe sKeep3rsv1.push(address(TBD)); } function earnable(address _addr, uint _version) public returns (bool) { if (_version == 1) { vKeep3rsv1.earnable(_addr); } else if (_version == 2) { // vKeep3rsv2... // do checking after the v2 vault keep3r interface is done } else { revert("!version"); } } /* earn(address), forceEarn(address) are almost the same */ function workable(address _addr, uint _version) public returns (bool ret, address target) { if (_version == 1) { for (uint i = 0; i < sKeep3rsv1.length; i++) { if (sKeep3rsv1[i].workable(_addr)) { ret = true; target = sKeep3rsv1[i] } } } else (_version == 2) { // v2 interface hasn't decided // do workable check here } else { revert("!version"); } } /* harvest(address), forceHarvest(address) are almost the same */ }
0.6.12