Contract 0xd5c5017659af1e53b48ae9d55b02756342a7d4ff

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8Do Hard Work196951262022-08-08 8:43:117 hrs 27 mins ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000082769302 ETH
0xec462621bb87c9310469e7e01c42b3c5022e6c59ff6543787313613201b86d0fDo Hard Work196541472022-08-07 20:33:5919 hrs 36 mins ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000102679359 ETH
0x4df07fe6973dcc651f38fc39049ef8f2fd49861d946b15e836402a3f44439aefDo Hard Work196065632022-08-07 8:25:061 day 7 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000063975854 ETH
0x76d344e0c621dcc836c9baf643209f16585ee9201403e7d1092bf3823a5c74b5Do Hard Work195673222022-08-06 20:16:571 day 19 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.00008695996 ETH
0x0f08a84c00651eaa16df55f70c1ca28fed022f7693ebf07fde42d27e9de9dd64Do Hard Work195208022022-08-06 8:09:172 days 8 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000113537169 ETH
0x40efdd540144a757220279fb051a1d34b811b90e1c0b0c1d2f079b39621013f5Do Hard Work195207482022-08-06 8:08:232 days 8 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000104748707 ETH
0x402b7dea46e30fa3acb1ff2a6c6e663dafaf1352a254bb9b0a8427cbd3118191Do Hard Work194845652022-08-05 19:59:142 days 20 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000139560189 ETH
0x9db93ca2f1788bccbbf6040461045db00afc56dc02f59c370f7ee97f8be6aafbDo Hard Work194322522022-08-05 7:49:473 days 8 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000107094554 ETH
0x0e5ca9fbef3eba30ecff17feff9e3a6bbd2683a8088aa2c5180942c6ea0ab1f8Do Hard Work193960232022-08-04 19:42:003 days 20 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.00013765244 ETH
0xf62dff663440638361937da961c38575f15471cc964abdf32dd6f9baff99345dDo Hard Work193531192022-08-04 7:32:344 days 8 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000115760632 ETH
0x36e59ae74754d347840d4ce8f32a6fc4728f85601cb8b71e2ed3d56f4f77ab41Do Hard Work193095642022-08-03 19:24:144 days 20 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000124789712 ETH
0x312457e0d658993033c693d10140032c98e4171b4aba5ee3ee320ee94f338b33Do Hard Work192608672022-08-03 7:15:285 days 8 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000104117383 ETH
0x11a0d01edaf2acacee4894a5f18ff6c03cbc4a84fb01d9301795c89c257e0294Do Hard Work192221152022-08-02 19:07:595 days 21 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000154043988 ETH
0xeb471463f0fee0b9c1974462a1bd86531637cbe4d4108f16a81fcc81ef26a744Do Hard Work191739782022-08-02 6:58:256 days 9 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000133192274 ETH
0x21720b7880ea54d39d5ac5b148a3a0485927a6d21c07cb0eec94e7d641bb865fDo Hard Work191403532022-08-01 18:50:566 days 21 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000128418978 ETH
0x9958987db3b8f5ea33765ad96608ebb6805b47ec0d459d28ea7f1ea3fa35e869Do Hard Work190945482022-08-01 6:42:307 days 9 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000089254257 ETH
0x7ff0b974c3ed3a5a0948b7bb2aed4c43baa15746b0fdc2e2081576d4c0d408dfDo Hard Work190593132022-07-31 18:33:417 days 21 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000118876778 ETH
0xd21e05ce8e186d7160e3787688213dc3c4e40b1ab31c3503ecb8c538e307b274Do Hard Work190085112022-07-31 6:24:328 days 9 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000069386263 ETH
0x57f173b420fd1f4cb8b4fcf5eacca459fc7aef6ef36dc14c70439b82ee1df022Do Hard Work189678412022-07-30 18:16:588 days 21 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000100566732 ETH
0x8969daef611360a0cc02baeafc621ed81237bd6fc314c544468410dab7b3606bDo Hard Work189243452022-07-30 6:08:129 days 10 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000113502925 ETH
0x89679079dca7de42649ed8bba6cc7c0ddc7494911195f0723e8cdb3461914e5bDo Hard Work188892252022-07-29 17:57:509 days 22 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000177487704 ETH
0x1da49d7983a54b4d87952e2412a18d8fcfc86a08f8e74a2fb1c8a832415623ecDo Hard Work188428582022-07-29 5:49:3010 days 10 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000187075271 ETH
0xbd27cc7cc072517fc486ec37f4b91bd3d5619745ccd90fe053814518c4c7a2e7Do Hard Work188042012022-07-28 17:40:4210 days 22 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000248946095 ETH
0x0ee00c6e05a52aa6149ff97c7afee68fdda824c6f515205bb129624eee589e63Do Hard Work187504342022-07-28 5:32:3911 days 10 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000187808467 ETH
0x4cf7d726ac9743ca9c97f2093d0d638e24191427f64e50458a7294ce23823cf0Do Hard Work187121972022-07-27 17:23:5411 days 22 hrs ago0x3a817495eaca931bead26845ae83f93f978723b0 IN  Harvest Finance: Controller0 ETH0.000138556711 ETH
[ Download CSV Export 

OVERVIEW

Handles the implementation logic for fee splitting, time delays, tracking active strategies & vaults, tracking hard workers, and various misc. smart contracts.

Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago Harvest Finance: Controller 0xfc2640ca71b1724b89dc2714e661b0089f8c0eed0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago 0x26b27e13e38fa8f8e43b8fc3ff7c601a8aa0d032 Harvest Finance: Controller0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago 0x26b27e13e38fa8f8e43b8fc3ff7c601a8aa0d032 Harvest Finance: Controller0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago 0x26b27e13e38fa8f8e43b8fc3ff7c601a8aa0d032 Harvest Finance: Controller0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago 0x26b27e13e38fa8f8e43b8fc3ff7c601a8aa0d032 Harvest Finance: Controller0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago 0x26b27e13e38fa8f8e43b8fc3ff7c601a8aa0d032 Harvest Finance: Controller0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago 0xd6d33ad0504c3767832a96d7e2de088270407e9d Harvest Finance: Controller0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago 0xd6d33ad0504c3767832a96d7e2de088270407e9d Harvest Finance: Controller0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago 0xd6d33ad0504c3767832a96d7e2de088270407e9d Harvest Finance: Controller0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago 0xd6d33ad0504c3767832a96d7e2de088270407e9d Harvest Finance: Controller0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago 0xd6d33ad0504c3767832a96d7e2de088270407e9d Harvest Finance: Controller0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago 0xd6d33ad0504c3767832a96d7e2de088270407e9d Harvest Finance: Controller0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago 0xd6d33ad0504c3767832a96d7e2de088270407e9d Harvest Finance: Controller0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago Harvest Finance: Controller 0xfc2640ca71b1724b89dc2714e661b0089f8c0eed0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago Harvest Finance: Controller Harvest Finance: Registry0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago 0xd6d33ad0504c3767832a96d7e2de088270407e9d Harvest Finance: Controller0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago Harvest Finance: Controller Harvest Finance: Registry0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago Harvest Finance: Controller 0xfc2640ca71b1724b89dc2714e661b0089f8c0eed0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago Harvest Finance: Controller 0xfc2640ca71b1724b89dc2714e661b0089f8c0eed0 ETH
0xed9a576dace91f581b3484bacb76599065f8829b1e3a997b011740c28cf84de8196951262022-08-08 8:43:117 hrs 27 mins ago Harvest Finance: Controller 0xfc2640ca71b1724b89dc2714e661b0089f8c0eed0 ETH
0xec462621bb87c9310469e7e01c42b3c5022e6c59ff6543787313613201b86d0f196541472022-08-07 20:33:5919 hrs 36 mins ago Harvest Finance: Controller 0xfc2640ca71b1724b89dc2714e661b0089f8c0eed0 ETH
0xec462621bb87c9310469e7e01c42b3c5022e6c59ff6543787313613201b86d0f196541472022-08-07 20:33:5919 hrs 36 mins ago 0x26b27e13e38fa8f8e43b8fc3ff7c601a8aa0d032 Harvest Finance: Controller0 ETH
0xec462621bb87c9310469e7e01c42b3c5022e6c59ff6543787313613201b86d0f196541472022-08-07 20:33:5919 hrs 36 mins ago 0x26b27e13e38fa8f8e43b8fc3ff7c601a8aa0d032 Harvest Finance: Controller0 ETH
0xec462621bb87c9310469e7e01c42b3c5022e6c59ff6543787313613201b86d0f196541472022-08-07 20:33:5919 hrs 36 mins ago 0x26b27e13e38fa8f8e43b8fc3ff7c601a8aa0d032 Harvest Finance: Controller0 ETH
0xec462621bb87c9310469e7e01c42b3c5022e6c59ff6543787313613201b86d0f196541472022-08-07 20:33:5919 hrs 36 mins ago 0x26b27e13e38fa8f8e43b8fc3ff7c601a8aa0d032 Harvest Finance: Controller0 ETH
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ControllerV1

Compiler Version
v0.5.16+commit.9c3226ce

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 24 : ControllerV1.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 "./inheritance/Governable.sol";

import "./interfaces/IController.sol";
import "./interfaces/IStrategy.sol";
import "./interfaces/IVault.sol";

import "./RewardForwarderV1.sol";


contract ControllerV1 is IController, Governable {
    using SafeERC20 for IERC20;
    using Address for address;
    using SafeMath for uint256;

    // ========================= Fields =========================

    // external parties
    address public targetToken;
    address public profitSharingReceiver;
    address public rewardForwarder;
    address public universalLiquidator;
    address public dolomiteYieldFarmingRouter;

    uint256 public nextImplementationDelay;

    /// 15% of fees captured go to iFARM stakers
    uint256 public profitSharingNumerator = 1500;
    uint256 public nextProfitSharingNumerator = 0;
    uint256 public nextProfitSharingNumeratorTimestamp = 0;

    /// 5% of fees captured go to strategists
    uint256 public strategistFeeNumerator = 500;
    uint256 public nextStrategistFeeNumerator = 0;
    uint256 public nextStrategistFeeNumeratorTimestamp = 0;

    /// 5% of fees captured go to the devs of the platform
    uint256 public platformFeeNumerator = 500;
    uint256 public nextPlatformFeeNumerator = 0;
    uint256 public nextPlatformFeeNumeratorTimestamp = 0;

    /// used for queuing a new delay
    uint256 public tempNextImplementationDelay = 0;
    uint256 public tempNextImplementationDelayTimestamp = 0;

    uint256 public constant FEE_DENOMINATOR = 10000;

    // [Grey list]
    // An EOA can safely interact with the system no matter what.
    // If you're using Metamask, you're using an EOA.
    // Only smart contracts may be affected by this grey list.
    //
    // This contract will not be able to ban any EOA from the system
    // even if an EOA is being added to the greyList, he/she will still be able
    // to interact with the whole system as if nothing happened.
    // Only smart contracts will be affected by being added to the greyList.
    mapping (address => bool) public greyList;

    /// @notice This mapping allows certain contracts to stake on a user's behalf
    mapping (address => bool) public stakingWhiteList;

    // All vaults that we have
    mapping (address => bool) public vaults;

    // All strategies that we have
    mapping (address => bool) public strategies;

    // All eligible hardWorkers that we have
    mapping (address => bool) public hardWorkers;

    // ========================= Modifiers =========================

    modifier validVault(address _vault){
        require(vaults[_vault], "vault does not exist");
        _;
    }

    modifier confirmSharePrice(
        address vault,
        uint256 _hint,
        uint256 _deviationNumerator,
        uint256 _deviationDenominator
    ) {
        uint256 sharePrice = IVault(vault).getPricePerFullShare();
        uint256 resolution = 1e18;
        if (sharePrice > _hint) {
            require(
                sharePrice.mul(resolution).div(_hint) <= _deviationNumerator.mul(resolution).div(_deviationDenominator),
                "share price deviation"
            );
        } else {
            require(
                _hint.mul(resolution).div(sharePrice) <= _deviationNumerator.mul(resolution).div(_deviationDenominator),
                "share price deviation"
            );
        }
        _;
    }

    modifier onlyHardWorkerOrGovernance() {
        require(hardWorkers[msg.sender] || (msg.sender == governance()),
            "only hard worker can call this");
        _;
    }

    constructor(
        address _storage,
        address _targetToken,
        address _profitSharingReceiver,
        address _rewardForwarder,
        address _universalLiquidator,
        uint _nextImplementationDelay
    )
    Governable(_storage)
    public {
        require(_targetToken != address(0), "_targetToken should not be empty");
        require(_profitSharingReceiver != address(0), "_profitSharingReceiver should not be empty");
        require(_rewardForwarder != address(0), "_rewardForwarder should not be empty");
        require(_universalLiquidator != address(0), "_universalLiquidator should not be empty");
        require(_nextImplementationDelay > 0, "_nextImplementationDelay should be gt 0");

        targetToken = _targetToken;
        profitSharingReceiver = _profitSharingReceiver;
        rewardForwarder = _rewardForwarder;
        universalLiquidator = _universalLiquidator;
        nextImplementationDelay = _nextImplementationDelay;
    }

    function hasVault(address _vault) external view returns (bool) {
        return vaults[_vault];
    }

    function hasStrategy(address _strategy) external view returns (bool) {
        return strategies[_strategy];
    }

    // Only smart contracts will be affected by the greyList.
    function addToGreyList(address _target) public onlyGovernance {
        greyList[_target] = true;
    }

    function removeFromGreyList(address _target) public onlyGovernance {
        greyList[_target] = false;
    }

    function addToStakingWhiteList(address _target) public onlyGovernance {
        require(
            !stakingWhiteList[_target],
            "_target cannot already be staking"
        );

        stakingWhiteList[_target] = true;
        emit AddedStakingContract(_target);
    }

    function removeFromStakingWhiteList(address _target) public onlyGovernance {
        require(
            stakingWhiteList[_target],
            "_target must already be staking"
        );

        stakingWhiteList[_target] = false;
        emit RemovedStakingContract(_target);
    }

    function setRewardForwarder(address _rewardForwarder) public onlyGovernance {
        require(_rewardForwarder != address(0), "new reward forwarder should not be empty");
        rewardForwarder = _rewardForwarder;
    }

    function setTargetToken(address _targetToken) public onlyGovernance {
        require(_targetToken != address(0), "new target token should not be empty");
        targetToken = _targetToken;
    }

    function setProfitSharingReceiver(address _profitSharingReceiver) public onlyGovernance {
        require(_profitSharingReceiver != address(0), "new profit sharing receiver should not be empty");
        profitSharingReceiver = _profitSharingReceiver;
    }

    function setUniversalLiquidator(address _universalLiquidator) public onlyGovernance {
        require(_universalLiquidator != address(0), "new universal liquidator should not be empty");
        universalLiquidator = _universalLiquidator;
    }

    function setDolomiteYieldFarmingRouter(address _dolomiteYieldFarmingRouter) public onlyGovernance {
        require(_dolomiteYieldFarmingRouter != address(0), "new reward forwarder should not be empty");
        dolomiteYieldFarmingRouter = _dolomiteYieldFarmingRouter;
    }

    function addVaultAndStrategy(address _vault, address _strategy) external onlyGovernance {
        _addVaultAndStrategy(_vault, _strategy);
    }

    function addVaultsAndStrategies(
        address[] calldata _vaults,
        address[] calldata _strategies
    ) external onlyGovernance {
        require(
            _vaults.length == _strategies.length,
            "invalid vaults/strategies length"
        );
        for (uint i = 0; i < _vaults.length; i++) {
            _addVaultAndStrategy(_vaults[i], _strategies[i]);
        }
    }

    function getPricePerFullShare(address _vault) public view returns (uint256) {
        return IVault(_vault).getPricePerFullShare();
    }

    function doHardWork(
        address _vault,
        uint256 _hint,
        uint256 _deviationNumerator,
        uint256 _deviationDenominator
    )
    external
    validVault(_vault)
    onlyHardWorkerOrGovernance
    confirmSharePrice(_vault, _hint, _deviationNumerator, _deviationDenominator) {
        uint256 oldSharePrice = IVault(_vault).getPricePerFullShare();
        IVault(_vault).doHardWork();
        emit SharePriceChangeLog(
            _vault,
            IVault(_vault).strategy(),
            oldSharePrice,
            IVault(_vault).getPricePerFullShare(),
            block.timestamp
        );
    }

    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 withdrawAll(
        address _vault,
        uint256 _hint,
        uint256 _deviationNumerator,
        uint256 _deviationDenominator
    )
    external
    confirmSharePrice(_vault, _hint, _deviationNumerator, _deviationDenominator)
    onlyGovernance
    validVault(_vault) {
        IVault(_vault).withdrawAll();
    }

    function setStrategy(
        address _vault,
        address _strategy,
        uint256 _hint,
        uint256 _deviationNumerator,
        uint256 _deviationDenominator
    )
    external
    confirmSharePrice(_vault, _hint, _deviationNumerator, _deviationDenominator)
    onlyGovernance
    validVault(_vault) {
        IVault(_vault).setStrategy(_strategy);
    }

    // transfers token in the controller contract to the governance
    function salvage(address _token, uint256 _amount) external onlyGovernance {
        IERC20(_token).safeTransfer(governance(), _amount);
    }

    function salvageStrategy(address _strategy, address _token, uint256 _amount) external onlyGovernance {
        // the strategy is responsible for maintaining the list of
        // salvageable tokens, to make sure that governance cannot come
        // in and take away the coins
        IStrategy(_strategy).salvageToken(governance(), _token, _amount);
    }

    function profitSharingDenominator() public view returns (uint) {
        // keep the interface for this function as a `view` for now, in case it changes in the future
        return FEE_DENOMINATOR;
    }

    function strategistFeeDenominator() public view returns (uint) {
        // keep the interface for this function as a `view` for now, in case it changes in the future
        return FEE_DENOMINATOR;
    }

    function platformFeeDenominator() public view returns (uint) {
        // keep the interface for this function as a `view` for now, in case it changes in the future
        return FEE_DENOMINATOR;
    }

    function setProfitSharingNumerator(uint _profitSharingNumerator) public onlyGovernance {
        require(
            _profitSharingNumerator + strategistFeeNumerator + platformFeeNumerator < FEE_DENOMINATOR,
            "invalid profit sharing fee numerator"
        );

        nextProfitSharingNumerator = _profitSharingNumerator;
        nextProfitSharingNumeratorTimestamp = block.timestamp + nextImplementationDelay;
        emit QueueProfitSharingNumeratorChange(nextProfitSharingNumerator, nextProfitSharingNumeratorTimestamp);
    }

    function confirmSetProfitSharingNumerator() public onlyGovernance {
        require(
            nextProfitSharingNumerator != 0
            && nextProfitSharingNumeratorTimestamp != 0
            && block.timestamp >= nextProfitSharingNumeratorTimestamp,
            "invalid timestamp or no new profit sharing numerator confirmed"
        );
        profitSharingNumerator = nextProfitSharingNumerator;
        nextProfitSharingNumerator = 0;
        nextProfitSharingNumeratorTimestamp = 0;
        emit ConfirmProfitSharingNumeratorChange(profitSharingNumerator);
    }

    function setStrategistFeeNumerator(uint _strategistFeeNumerator) public onlyGovernance {
        require(
            _strategistFeeNumerator + platformFeeNumerator + profitSharingNumerator < FEE_DENOMINATOR,
            "invalid strategist fee numerator"
        );

        nextStrategistFeeNumerator = _strategistFeeNumerator;
        nextStrategistFeeNumeratorTimestamp = block.timestamp + nextImplementationDelay;
        emit QueueStrategistFeeNumeratorChange(nextStrategistFeeNumerator, nextStrategistFeeNumeratorTimestamp);
    }

    function confirmSetStrategistFeeNumerator() public onlyGovernance {
        require(
            nextStrategistFeeNumerator != 0
            && nextStrategistFeeNumeratorTimestamp != 0
            && block.timestamp >= nextStrategistFeeNumeratorTimestamp,
            "invalid timestamp or no new strategist fee numerator confirmed"
        );
        strategistFeeNumerator = nextStrategistFeeNumerator;
        nextStrategistFeeNumerator = 0;
        nextStrategistFeeNumeratorTimestamp = 0;
        emit ConfirmStrategistFeeNumeratorChange(strategistFeeNumerator);
    }

    function setPlatformFeeNumerator(uint _platformFeeNumerator) public onlyGovernance {
        require(
            _platformFeeNumerator + strategistFeeNumerator + profitSharingNumerator < FEE_DENOMINATOR,
            "invalid platform fee numerator"
        );

        nextPlatformFeeNumerator = _platformFeeNumerator;
        nextPlatformFeeNumeratorTimestamp = block.timestamp + nextImplementationDelay;
        emit QueuePlatformFeeNumeratorChange(nextPlatformFeeNumerator, nextPlatformFeeNumeratorTimestamp);
    }

    function confirmSetPlatformFeeNumerator() public onlyGovernance {
        require(
            nextPlatformFeeNumerator != 0
            && nextPlatformFeeNumeratorTimestamp != 0
            && block.timestamp >= nextPlatformFeeNumeratorTimestamp,
            "invalid timestamp or no new platform fee numerator confirmed"
        );
        platformFeeNumerator = nextPlatformFeeNumerator;
        nextPlatformFeeNumerator = 0;
        nextPlatformFeeNumeratorTimestamp = 0;
        emit ConfirmPlatformFeeNumeratorChange(platformFeeNumerator);
    }

    function setNextImplementationDelay(uint256 _nextImplementationDelay) public onlyGovernance {
        require(
            _nextImplementationDelay > 0,
            "invalid _nextImplementationDelay"
        );

        tempNextImplementationDelay = _nextImplementationDelay;
        tempNextImplementationDelayTimestamp = block.timestamp + nextImplementationDelay;
        emit QueueNextImplementationDelay(tempNextImplementationDelay, tempNextImplementationDelayTimestamp);
    }

    function confirmNextImplementationDelay() public onlyGovernance {
        require(
            tempNextImplementationDelayTimestamp != 0 && block.timestamp >= tempNextImplementationDelayTimestamp,
            "invalid timestamp or no new implementation delay confirmed"
        );
        nextImplementationDelay = tempNextImplementationDelay;
        tempNextImplementationDelay = 0;
        tempNextImplementationDelayTimestamp = 0;
        emit ConfirmNextImplementationDelay(nextImplementationDelay);
    }

    // ========================= Internal Functions =========================

    function _addVaultAndStrategy(address _vault, address _strategy) internal {
        require(_vault != address(0), "new vault shouldn't be empty");
        require(!vaults[_vault], "vault already exists");
        require(!strategies[_strategy], "strategy already exists");
        require(_strategy != address(0), "new strategy shouldn't be empty");

        vaults[_vault] = true;
        strategies[_strategy] = true;

        // no need to protect against sandwich, because there will be no call to withdrawAll
        // as the vault and strategy is brand new
        IVault(_vault).setStrategy(_strategy);
    }
}

File 2 of 24 : Address.sol
pragma solidity ^0.5.5;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following 
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

    /**
     * @dev Converts an `address` into `address payable`. Note that this is
     * simply a type cast: the actual underlying value is not changed.
     *
     * _Available since v2.4.0._
     */
    function toPayable(address account) internal pure returns (address payable) {
        return address(uint160(account));
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     *
     * _Available since v2.4.0._
     */
    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");
    }
}

File 3 of 24 : SafeMath.sol
pragma solidity ^0.5.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     *
     * _Available since v2.4.0._
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    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;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

File 4 of 24 : SafeERC20.sol
pragma solidity ^0.5.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
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 {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        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));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves.

        // A Solidity high level call has three parts:
        //  1. The target address is checked to verify it contains contract code
        //  2. The call itself is made, and success asserted
        //  3. The return value is decoded, which in turn checks the size of the returned data.
        // solhint-disable-next-line max-line-length
        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");
        }
    }
}

File 5 of 24 : IERC20.sol
pragma solidity ^0.5.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see {ERC20Detailed}.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 6 of 24 : 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();
  }
}

File 7 of 24 : IController.sol
pragma solidity ^0.5.16;

interface IController {

    // ========================= Events =========================

    event QueueProfitSharingNumeratorChange(uint profitSharingNumerator, uint validAtTimestamp);
    event ConfirmProfitSharingNumeratorChange(uint profitSharingNumerator);

    event QueueStrategistFeeNumeratorChange(uint strategistFeeNumerator, uint validAtTimestamp);
    event ConfirmStrategistFeeNumeratorChange(uint strategistFeeNumerator);

    event QueuePlatformFeeNumeratorChange(uint platformFeeNumerator, uint validAtTimestamp);
    event ConfirmPlatformFeeNumeratorChange(uint platformFeeNumerator);

    event QueueNextImplementationDelay(uint implementationDelay, uint validAtTimestamp);
    event ConfirmNextImplementationDelay(uint implementationDelay);

    event AddedStakingContract(address indexed stakingContract);
    event RemovedStakingContract(address indexed stakingContract);

    event SharePriceChangeLog(
        address indexed vault,
        address indexed strategy,
        uint256 oldSharePrice,
        uint256 newSharePrice,
        uint256 timestamp
    );

    // ==================== Functions ====================

    /**
     * An EOA can safely interact with the system no matter what. If you're using Metamask, you're using an EOA. Only
     * smart contracts may be affected by this grey list. This contract will not be able to ban any EOA from the system
     * even if an EOA is being added to the greyList, he/she will still be able to interact with the whole system as if
     * nothing happened. Only smart contracts will be affected by being added to the greyList. This grey list is only
     * used in VaultV3.sol, see the code there for reference
     */
    function greyList(address _target) external view returns (bool);

    function stakingWhiteList(address _target) external view returns (bool);

    function store() external view returns (address);

    function governance() external view returns (address);

    function hasVault(address _vault) external view returns (bool);

    function hasStrategy(address _strategy) external view returns (bool);

    function addVaultAndStrategy(address _vault, address _strategy) external;

    function addVaultsAndStrategies(address[] calldata _vaults, address[] calldata _strategies) external;

    function doHardWork(
        address _vault,
        uint256 _hint,
        uint256 _deviationNumerator,
        uint256 _deviationDenominator
    ) external;

    function addHardWorker(address _worker) external;

    function removeHardWorker(address _worker) external;

    function salvage(address _token, uint256 amount) external;

    function salvageStrategy(address _strategy, address _token, uint256 amount) external;

    /**
     * @return The targeted profit token to convert all-non-compounding rewards to. Defaults to WETH.
     */
    function targetToken() external view returns (address);

    function setTargetToken(address _targetToken) external;

    function profitSharingReceiver() external view returns (address);

    function setProfitSharingReceiver(address _profitSharingReceiver) external;

    function rewardForwarder() external view returns (address);

    function setRewardForwarder(address _rewardForwarder) external;

    function setUniversalLiquidator(address _universalLiquidator) external;

    function universalLiquidator() external view returns (address);

    function dolomiteYieldFarmingRouter() external view returns (address);

    function setDolomiteYieldFarmingRouter(address _value) external;

    function nextImplementationDelay() external view returns (uint256);

    function profitSharingNumerator() external view returns (uint256);

    function strategistFeeNumerator() external view returns (uint256);

    function platformFeeNumerator() external view returns (uint256);

    function profitSharingDenominator() external view returns (uint256);

    function strategistFeeDenominator() external view returns (uint256);

    function platformFeeDenominator() external view returns (uint256);

    function setProfitSharingNumerator(uint _profitSharingNumerator) external;

    function confirmSetProfitSharingNumerator() external;

    function setStrategistFeeNumerator(uint _strategistFeeNumerator) external;

    function confirmSetStrategistFeeNumerator() external;

    function setPlatformFeeNumerator(uint _platformFeeNumerator) external;

    function confirmSetPlatformFeeNumerator() external;

    function nextProfitSharingNumerator() external view returns (uint256);

    function nextProfitSharingNumeratorTimestamp() external view returns (uint256);

    function nextStrategistFeeNumerator() external view returns (uint256);

    function nextStrategistFeeNumeratorTimestamp() external view returns (uint256);

    function nextPlatformFeeNumerator() external view returns (uint256);

    function nextPlatformFeeNumeratorTimestamp() external view returns (uint256);

    function tempNextImplementationDelay() external view returns (uint256);

    function tempNextImplementationDelayTimestamp() external view returns (uint256);

    function setNextImplementationDelay(uint256 _nextImplementationDelay) external;

    function confirmNextImplementationDelay() external;
}

File 8 of 24 : IStrategy.sol
pragma solidity ^0.5.16;

import "../inheritance/ControllableInit.sol";


contract IStrategy {

    /// @notice declared as public so child contract can call it
    function isUnsalvageableToken(address token) public view returns (bool);

    function salvageToken(address recipient, address token, uint amount) external;

    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 doHardWork() external;

    function depositArbCheck() external view returns (bool);

    function strategist() external view returns (address);

    /**
     * @return  The value of any accumulated rewards that are under control by the strategy. Each index corresponds with
     *          the tokens in `rewardTokens`. This function is not a `view`, because some protocols, like Curve, need
     *          writeable functions to get the # of claimable reward tokens
     */
    function getRewardPoolValues() external returns (uint256[] memory);
}

File 9 of 24 : IVault.sol
pragma solidity ^0.5.16;

interface IVault {

    function initializeVault(
        address _storage,
        address _underlying,
        uint256 _toInvestNumerator,
        uint256 _toInvestDenominator
    ) external;

    function balanceOf(address _holder) 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 underlyingUnit() external view returns (uint);

    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 _amount) external;

    function depositFor(uint256 _amount, 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);

    /**
     * This should be callable only by the controller (by the hard worker) or by governance
     */
    function doHardWork() external;
}

File 10 of 24 : RewardForwarderV1.sol
pragma solidity ^0.5.16;

import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";

import "./inheritance/Governable.sol";
import "./interfaces/IRewardForwarder.sol";
import "./interfaces/IProfitSharingReceiver.sol";
import "./interfaces/IStrategy.sol";
import "./interfaces/IUniversalLiquidator.sol";
import "./interfaces/uniswap/IUniswapV2Router02.sol";
import "./inheritance/Controllable.sol";
import "./inheritance/Constants.sol";


/**
 * @dev This contract receives rewards from strategies and is responsible for routing the reward's liquidation into
 *      specific buyback tokens and profit tokens for the DAO.
 */
contract RewardForwarderV1 is IRewardForwarder, Controllable, Constants {
    using SafeERC20 for IERC20;
    using SafeMath for uint256;

    constructor(
        address _storage
    ) public Controllable(_storage) {}

    function notifyFeeAndBuybackAmounts(
        address _token,
        uint256 _profitSharingFee,
        uint256 _strategistFee,
        uint256 _platformFee,
        address[] calldata _buybackTokens,
        uint256[] calldata _buybackAmounts
    ) external returns (uint[] memory) {
        return _notifyFeeAndBuybackAmounts(
            _token,
            _profitSharingFee,
            _strategistFee,
            _platformFee,
            _buybackTokens,
            _buybackAmounts
        );
    }

    function notifyFee(
        address _token,
        uint256 _profitSharingFee,
        uint256 _strategistFee,
        uint256 _platformFee
    ) external {
        _notifyFeeAndBuybackAmounts(
            _token,
            _profitSharingFee,
            _strategistFee,
            _platformFee,
            new address[](0),
            new uint256[](0)
        );
    }

    function _notifyFeeAndBuybackAmounts(
        address _token,
        uint256 _profitSharingFee,
        uint256 _strategistFee,
        uint256 _platformFee,
        address[] memory _buybackTokens,
        uint256[] memory _buybackAmounts
    ) internal returns (uint[] memory) {
        address _controller = controller();
        require(
            IController(_controller).hasStrategy(msg.sender),
            "msg.sender must be a strategy"
        );

        address liquidator = IController(_controller).universalLiquidator();
        {
            uint totalTransferAmount = _profitSharingFee.add(_strategistFee).add(_platformFee);
            for (uint i = 0; i < _buybackAmounts.length; i++) {
                totalTransferAmount = totalTransferAmount.add(_buybackAmounts[i]);
            }
            require(totalTransferAmount > 0, "totalTransferAmount should not be 0");
            IERC20(_token).safeTransferFrom(msg.sender, address(this), totalTransferAmount);

            IERC20(_token).safeApprove(liquidator, 0);
            IERC20(_token).safeApprove(liquidator, totalTransferAmount);
        }

        address _targetToken = IController(_controller).targetToken();
        uint amountOutMin = 1;

        if (_strategistFee > 0) {
            IUniversalLiquidator(liquidator).swapTokens(
                _token,
                _targetToken,
                _strategistFee,
                amountOutMin,
                IStrategy(msg.sender).strategist()
            );
        }
        if (_platformFee > 0) {
            IUniversalLiquidator(liquidator).swapTokens(
                _token,
                _targetToken,
                _platformFee,
                amountOutMin,
                IController(_controller).governance()
            );
        }
        if (_profitSharingFee > 0) {
            IUniversalLiquidator(liquidator).swapTokens(
                _token,
                _targetToken,
                _profitSharingFee,
                amountOutMin,
                IController(_controller).profitSharingReceiver()
            );
        }

        uint[] memory amounts = new uint[](_buybackTokens.length);
        for (uint i = 0; i < amounts.length; ++i) {
            if (_buybackAmounts[i] > 0) {
                amounts[i] = IUniversalLiquidator(liquidator).swapTokens(
                    _token,
                    _buybackTokens[i],
                    _buybackAmounts[i],
                    amountOutMin,
                    msg.sender
                );
            }
        }

        return amounts;
    }
}

File 11 of 24 : Storage.sol
pragma solidity ^0.5.16;

import "../interfaces/IController.sol";


contract Storage {

  event GovernanceChanged(address newGovernance);
  event GovernanceQueued(address newGovernance, uint implementationTimestamp);
  event ControllerChanged(address newController);
  event ControllerQueued(address newController, uint implementationTimestamp);

  address public governance;
  address public controller;

  address public nextGovernance;
  uint256 public nextGovernanceTimestamp;

  address public nextController;
  uint256 public nextControllerTimestamp;

  modifier onlyGovernance() {
    require(isGovernance(msg.sender), "Not governance");
    _;
  }

  constructor () public {
    governance = msg.sender;
    emit GovernanceChanged(msg.sender);
  }

  function setInitialController(address _controller) public onlyGovernance {
    require(
      controller == address(0),
      "controller already set"
    );
    require(
      IController(_controller).nextImplementationDelay() >= 0,
      "new controller doesn't get delay properly"
    );

    controller = _controller;
    emit ControllerChanged(_controller);
  }

  function nextImplementationDelay() public view returns (uint) {
    return IController(controller).nextImplementationDelay();
  }

  function setGovernance(address _governance) public onlyGovernance {
    require(_governance != address(0), "new governance shouldn't be empty");
    nextGovernance = _governance;
    nextGovernanceTimestamp = block.timestamp + nextImplementationDelay();
    emit GovernanceQueued(nextGovernance, nextGovernanceTimestamp);
  }

  function confirmGovernance() public onlyGovernance {
    require(
      nextGovernance != address(0) && nextGovernanceTimestamp != 0,
      "no governance queued"
    );
    require(
      block.timestamp >= nextGovernanceTimestamp,
      "governance not yet ready"
    );
    governance = nextGovernance;
    emit GovernanceChanged(governance);

    nextGovernance = address(0);
    nextGovernanceTimestamp = 0;
  }

  function setController(address _controller) public onlyGovernance {
    require(_controller != address(0), "new controller shouldn't be empty");
    require(IController(_controller).nextImplementationDelay() >= 0, "new controller doesn't get delay properly");

    nextController = _controller;
    nextControllerTimestamp = block.timestamp + nextImplementationDelay();
    emit ControllerQueued(nextController, nextControllerTimestamp);
  }

  function confirmController() public onlyGovernance {
    require(
      nextController != address(0) && nextControllerTimestamp != 0,
      "no controller queued"
    );
    require(
      block.timestamp >= nextControllerTimestamp,
      "controller not yet ready"
    );
    controller = nextController;
    emit ControllerChanged(controller);

    nextController = address(0);
    nextControllerTimestamp = 0;
  }

  function isGovernance(address account) public view returns (bool) {
    return account == governance;
  }

  function isController(address account) public view returns (bool) {
    return account == controller;
  }
}

File 12 of 24 : ControllableInit.sol
pragma solidity ^0.5.16;

import "./GovernableInit.sol";


/**
 * A clone of Governable supporting the Initializable interface and pattern
 */
contract ControllableInit is GovernableInit {

    constructor() public {
    }

    function initialize(address _storage) public initializer {
        GovernableInit.initialize(_storage);
    }

    modifier onlyController() {
        require(Storage(_storage()).isController(msg.sender), "Not a controller");
        _;
    }

    modifier onlyControllerOrGovernance(){
        require(
          Storage(_storage()).isController(msg.sender) || Storage(_storage()).isGovernance(msg.sender),
          "The caller must be controller or governance"
        );
        _;
    }

    function controller() public view returns (address) {
        return Storage(_storage()).controller();
    }
}

File 13 of 24 : GovernableInit.sol
pragma solidity ^0.5.16;

import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "../upgradability/UpgradeableReentrancyGuard.sol";
import "./Storage.sol";


/**
 * A clone of Governable supporting the Initializable interface and pattern
 */
contract GovernableInit is UpgradeableReentrancyGuard {

  bytes32 internal constant _STORAGE_SLOT = 0xa7ec62784904ff31cbcc32d09932a58e7f1e4476e1d041995b37c917990b16dc;

  modifier onlyGovernance() {
    require(Storage(_storage()).isGovernance(msg.sender), "Not governance");
    _;
  }

  constructor() public {
    assert(_STORAGE_SLOT == bytes32(uint256(keccak256("eip1967.governableInit.storage")) - 1));
  }

  function initialize(address _store) public initializer {
    UpgradeableReentrancyGuard.initialize();
    _setStorage(_store);
  }

  function _setStorage(address newStorage) private {
    bytes32 slot = _STORAGE_SLOT;
    // solhint-disable-next-line no-inline-assembly
    assembly {
      sstore(slot, newStorage)
    }
  }

  function setStorage(address _store) public onlyGovernance {
    require(_store != address(0), "new storage shouldn't be empty");
    _setStorage(_store);
  }

  function _storage() internal view returns (address str) {
    bytes32 slot = _STORAGE_SLOT;
    // solhint-disable-next-line no-inline-assembly
    assembly {
      str := sload(slot)
    }
  }

  function governance() public view returns (address) {
    return Storage(_storage()).governance();
  }
}

File 14 of 24 : Initializable.sol
pragma solidity >=0.4.24 <0.7.0;


/**
 * @title Initializable
 *
 * @dev Helper contract to support initializer functions. To use it, replace
 * the constructor with a function that has the `initializer` modifier.
 * WARNING: Unlike constructors, initializer functions must be manually
 * invoked. This applies both to deploying an Initializable contract, as well
 * as extending an Initializable contract via inheritance.
 * WARNING: When used with inheritance, manual care must be taken to not invoke
 * a parent initializer twice, or ensure that all initializers are idempotent,
 * because this is not dealt with automatically as with constructors.
 */
contract Initializable {

  /**
   * @dev Indicates that the contract has been initialized.
   */
  bool private initialized;

  /**
   * @dev Indicates that the contract is in the process of being initialized.
   */
  bool private initializing;

  /**
   * @dev Modifier to use in the initializer function of a contract.
   */
  modifier initializer() {
    require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");

    bool isTopLevelCall = !initializing;
    if (isTopLevelCall) {
      initializing = true;
      initialized = true;
    }

    _;

    if (isTopLevelCall) {
      initializing = false;
    }
  }

  /// @dev Returns true if and only if the function is running in the constructor
  function isConstructor() private view returns (bool) {
    // extcodesize checks the size of the code stored in an address, and
    // address returns the current address. Since the code is still not
    // deployed when running a constructor, any checks on its code size will
    // yield zero, making it an effective way to detect if a contract is
    // under construction or not.
    address self = address(this);
    uint256 cs;
    assembly { cs := extcodesize(self) }
    return cs == 0;
  }

  // Reserved storage space to allow for layout changes in the future.
  uint256[50] private ______gap;
}

File 15 of 24 : UpgradeableReentrancyGuard.sol
pragma solidity >=0.5.4;

import "@openzeppelin/upgrades/contracts/Initializable.sol";


/**
 * Same old `ReentrancyGuard`, but can be used by upgradable contracts
 */
contract UpgradeableReentrancyGuard is Initializable {

    bytes32 internal constant _NOT_ENTERED_SLOT = 0x62ae7bf2df4e95c187ea09c8c47c3fc3d9abc36298f5b5b6c5e2e7b4b291fe25;

    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_getNotEntered(_NOT_ENTERED_SLOT), "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _setNotEntered(_NOT_ENTERED_SLOT, false);

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _setNotEntered(_NOT_ENTERED_SLOT, true);
    }

    constructor() public {
        assert(_NOT_ENTERED_SLOT == bytes32(uint256(keccak256("eip1967.reentrancyGuard.notEntered")) - 1));
    }

    function initialize() public initializer {
        _setNotEntered(_NOT_ENTERED_SLOT, true);
    }

    function _getNotEntered(bytes32 slot) private view returns (bool) {
        uint str;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            str := sload(slot)
        }
        return str == 1;
    }

    function _setNotEntered(bytes32 slot, bool _value) private {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(slot, _value)
        }
    }

}

File 16 of 24 : ERC20Burnable.sol
pragma solidity ^0.5.0;

import "../../GSN/Context.sol";
import "./ERC20.sol";

/**
 * @dev Extension of {ERC20} that allows token holders to destroy both their own
 * tokens and those that they have an allowance for, in a way that can be
 * recognized off-chain (via event analysis).
 */
contract ERC20Burnable is Context, ERC20 {
    /**
     * @dev Destroys `amount` tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 amount) public {
        _burn(_msgSender(), amount);
    }

    /**
     * @dev See {ERC20-_burnFrom}.
     */
    function burnFrom(address account, uint256 amount) public {
        _burnFrom(account, amount);
    }
}

File 17 of 24 : IRewardForwarder.sol
pragma solidity ^0.5.16;


/**
 * @dev A routing contract that is responsible for taking the harvested gains and routing them into FARM and additional
 *      buyback tokens for the corresponding strategy
 */
interface IRewardForwarder {

    function store() external view returns (address);

    function governance() external view returns (address);

    /**
     * @dev This function sends converted `_buybackTokens` to `msg.sender`. The returned amounts will match the
     *      `amounts` return value. The fee amounts are converted to the profit sharing token and sent to the proper
     *      addresses (profit sharing, strategist, and governance (platform)).
     *
     * @param _token            the token that will be compounded or sold into the profit sharing token for the Harvest
     *                          collective (users that stake iFARM)
     * @param _profitSharingFee the amount of `_token` that will be sold into the profit sharing token
     * @param _strategistFee    the amount of `_token` that will be sold into the profit sharing token for the
     *                          strategist
     * @param _platformFee      the amount of `_token` that will be sold into the profit sharing token for the Harvest
     *                          treasury
     * @param _buybackTokens    the output tokens that `_buyBackAmounts` should be swapped to (outputToken)
     * @param _buybackAmounts   the amounts of `_token` that will be bought into more `_buybackTokens` token
     * @return The amounts that were purchased of _buybackTokens
     */
    function notifyFeeAndBuybackAmounts(
        address _token,
        uint256 _profitSharingFee,
        uint256 _strategistFee,
        uint256 _platformFee,
        address[] calldata _buybackTokens,
        uint256[] calldata _buybackAmounts
    ) external returns (uint[] memory amounts);

    /**
     * @dev This function converts the fee amounts to the profit sharing token and sends them to the proper addresses
     *      (profit sharing, strategist, and governance (platform)).
     *
     * @param _token            the token that will be compounded or sold into the profit sharing token for the Harvest
     *                          collective (users that stake iFARM)
     * @param _profitSharingFee the amount of `_token` that will be sold into the profit sharing token
     * @param _strategistFee    the amount of `_token` that will be sold into the profit sharing token for the
     *                          strategist
     * @param _platformFee      the amount of `_token` that will be sold into the profit sharing token for the Harvest
     *                          treasury
     * @return The amounts that were purchased of _buybackTokens
     */
    function notifyFee(
        address _token,
        uint256 _profitSharingFee,
        uint256 _strategistFee,
        uint256 _platformFee
    ) external;
}

File 18 of 24 : IProfitSharingReceiver.sol
pragma solidity ^0.5.16;


interface IProfitSharingReceiver {

    function governance() external view returns (address);

    function withdrawTokens(address[] calldata _tokens) external;
}

File 19 of 24 : IUniversalLiquidator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;


/**
 * @dev A contract that handles all liquidations from an `inputToken` to an `outputToken`. This contract simplifies
 *      all swap logic so strategies can be focused on management of funds and forwarding gains to this contract
 *      for the most efficient liquidation. If the liquidation path of an asset changes, governance needs only to
 *      create a new instance of this contract or modify the liquidation path via `configureSwap`, and all callers of
 *      the contract benefit from the change and uniformity.
 */
interface IUniversalLiquidator {

    // ==================== Events ====================

    event Swap(
        address indexed buyToken,
        address indexed sellToken,
        address indexed recipient,
        address initiator,
        uint256 amountIn,
        uint256 slippage,
        uint256 total
    );

    // ==================== Functions ====================

    function governance() external view returns (address);

    function controller() external view returns (address);

    function nextImplementation() external view returns (address);

    function scheduleUpgrade(address _nextImplementation) external;

    /**
     * Constructor replacement because this contract is meant to be upgradable
     */
    function initializeUniversalLiquidator(
        address _storage
    ) external;

    /**
     * @param _path     The path that is used for selling token at path[0] into path[path.length - 1].
     * @param _router   The router to use for this path.
     */
    function configureSwap(
        address[] calldata _path,
        address _router
    ) external;

    /**
     * @param _paths    The paths that are used for selling token at path[i][0] into path[i][path[i].length - 1].
     * @param _routers  The routers to use for each index, `i`.
     */
    function configureSwaps(
        address[][] calldata _paths,
        address[] calldata _routers
    ) external;

    /**
     * @return The router used to execute the swap from `_inputToken` to `_outputToken`
     */
    function getSwapRouter(
        address _inputToken,
        address _outputToken
    ) external view returns (address);

    function swapTokens(
        address _tokenIn,
        address _tokenOut,
        uint256 _amountIn,
        uint256 _amountOutMin,
        address _recipient
    ) external returns (uint _amountOut);
}

File 20 of 24 : IUniswapV2Router02.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;


interface IUniswapV2Router02 {

    function factory() external pure returns (address);

    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);

    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);

    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB);

    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountETH);

    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountA, uint amountB);

    function removeLiquidityETHWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountToken, uint amountETH);

    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);

    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);

    function swapExactETHForTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    )
        external
        payable
        returns (uint[] memory amounts);

    function swapTokensForExactETH(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    )
        external
        returns (uint[] memory amounts);

    function swapExactTokensForETH(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    )
        external
        returns (uint[] memory amounts);

    function swapETHForExactTokens(
        uint amountOut,
        address[] calldata path,
        address to,
        uint deadline
    )
        external
        payable
        returns (uint[] memory amounts);

    function quote(
        uint amountA,
        uint reserveA,
        uint reserveB
    ) external pure returns (uint amountB);

    function getAmountOut(
        uint amountIn,
        uint reserveIn,
        uint reserveOut
    ) external pure returns (uint amountOut);

    function getAmountIn(
        uint amountOut,
        uint reserveIn,
        uint reserveOut
    ) external pure returns (uint amountIn);

    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);

    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);

    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountETH);

    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;

    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;

    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}

File 21 of 24 : Controllable.sol
pragma solidity ^0.5.16;

import "./Governable.sol";


contract Controllable is Governable {

  constructor(address _storage) Governable(_storage) public {
  }

  modifier onlyController() {
    require(store.isController(msg.sender), "Not a controller");
    _;
  }

  modifier onlyControllerOrGovernance(){
    require((store.isController(msg.sender) || store.isGovernance(msg.sender)),
      "The caller must be controller or governance");
    _;
  }

  function controller() public view returns (address) {
    return store.controller();
  }
}

File 22 of 24 : Constants.sol
pragma solidity ^0.5.16;


contract Constants {

    address constant public CRV = 0x11cDb42B0EB46D95f990BeDD4695A6e3fA034978;

    address constant public CRV_TRI_CRYPTO = 0x8e0B8c8BB9db49a46697F3a5Bb8A308e744821D2;

    address constant public CRV_TRI_CRYPTO_GAUGE = 0x97E2768e8E73511cA874545DC5Ff8067eB19B787;

    address constant public CRV_TRI_CRYPTO_POOL = 0x960ea3e3C7FB317332d990873d354E18d7645590;

    address constant public DAI = 0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1;

    /// @notice Used as governance
    address constant public DEFAULT_MULTI_SIG_ADDRESS = 0xb39710a1309847363b9cBE5085E427cc2cAeE563;

    // We can set this later once we know the address
//    address constant public FARM = 0x0000000000000000000000000000000000000000;

    address constant public LINK = 0xf97f4df75117a78c1A5a0DBb814Af92458539FB4;

    address constant public ONE_INCH = 0x0000000000000000000000000000000000000000;

    address constant public ONE_INCH_CALLER = 0x0000000000000000000000000000000000000000;

    address constant public SUSHI = 0xd4d42F0b6DEF4CE0383636770eF773390d85c61A;

    address constant public SUSHI_ROUTER = 0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506;

    address constant public UNI = 0xFa7F8980b0f1E64A2062791cc3b0871572f1F7f0;

    address constant public UNISWAP_V3_ROUTER = 0xE592427A0AEce92De3Edee1F18E0157C05861564;

    address constant public USDC = 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8;

    address constant public USDT = 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9;

    address constant public WBTC = 0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f;

    address constant public WETH = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
}

File 23 of 24 : Context.sol
pragma solidity ^0.5.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
contract Context {
    // Empty internal constructor, to prevent people from mistakenly deploying
    // an instance of this contract, which should be used via inheritance.
    constructor () internal { }
    // solhint-disable-previous-line no-empty-blocks

    function _msgSender() internal view returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

File 24 of 24 : ERC20.sol
pragma solidity ^0.5.0;

import "../../GSN/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20Mintable}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20};
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for `sender`'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: burn from the zero address");

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`.`amount` is then deducted
     * from the caller's allowance.
     *
     * See {_burn} and {_approve}.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_storage","type":"address"},{"internalType":"address","name":"_targetToken","type":"address"},{"internalType":"address","name":"_profitSharingReceiver","type":"address"},{"internalType":"address","name":"_rewardForwarder","type":"address"},{"internalType":"address","name":"_universalLiquidator","type":"address"},{"internalType":"uint256","name":"_nextImplementationDelay","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakingContract","type":"address"}],"name":"AddedStakingContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"implementationDelay","type":"uint256"}],"name":"ConfirmNextImplementationDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"platformFeeNumerator","type":"uint256"}],"name":"ConfirmPlatformFeeNumeratorChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profitSharingNumerator","type":"uint256"}],"name":"ConfirmProfitSharingNumeratorChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"strategistFeeNumerator","type":"uint256"}],"name":"ConfirmStrategistFeeNumeratorChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"implementationDelay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"validAtTimestamp","type":"uint256"}],"name":"QueueNextImplementationDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"platformFeeNumerator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"validAtTimestamp","type":"uint256"}],"name":"QueuePlatformFeeNumeratorChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profitSharingNumerator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"validAtTimestamp","type":"uint256"}],"name":"QueueProfitSharingNumeratorChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"strategistFeeNumerator","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"validAtTimestamp","type":"uint256"}],"name":"QueueStrategistFeeNumeratorChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stakingContract","type":"address"}],"name":"RemovedStakingContract","type":"event"},{"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":true,"inputs":[],"name":"FEE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","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":"_target","type":"address"}],"name":"addToGreyList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_target","type":"address"}],"name":"addToStakingWhiteList","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":false,"inputs":[{"internalType":"address[]","name":"_vaults","type":"address[]"},{"internalType":"address[]","name":"_strategies","type":"address[]"}],"name":"addVaultsAndStrategies","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"confirmNextImplementationDelay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"confirmSetPlatformFeeNumerator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"confirmSetProfitSharingNumerator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"confirmSetStrategistFeeNumerator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"uint256","name":"_hint","type":"uint256"},{"internalType":"uint256","name":"_deviationNumerator","type":"uint256"},{"internalType":"uint256","name":"_deviationDenominator","type":"uint256"}],"name":"doHardWork","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"dolomiteYieldFarmingRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"getPricePerFullShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"","type":"address"}],"name":"greyList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[{"internalType":"address","name":"_strategy","type":"address"}],"name":"hasStrategy","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_vault","type":"address"}],"name":"hasVault","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"nextImplementationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"nextPlatformFeeNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"nextPlatformFeeNumeratorTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"nextProfitSharingNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"nextProfitSharingNumeratorTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"nextStrategistFeeNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"nextStrategistFeeNumeratorTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"platformFeeDenominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"platformFeeNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","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":true,"inputs":[],"name":"profitSharingReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_target","type":"address"}],"name":"removeFromGreyList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_target","type":"address"}],"name":"removeFromStakingWhiteList","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":true,"inputs":[],"name":"rewardForwarder","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","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":"_dolomiteYieldFarmingRouter","type":"address"}],"name":"setDolomiteYieldFarmingRouter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_nextImplementationDelay","type":"uint256"}],"name":"setNextImplementationDelay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_platformFeeNumerator","type":"uint256"}],"name":"setPlatformFeeNumerator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_profitSharingNumerator","type":"uint256"}],"name":"setProfitSharingNumerator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_profitSharingReceiver","type":"address"}],"name":"setProfitSharingReceiver","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rewardForwarder","type":"address"}],"name":"setRewardForwarder","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":false,"inputs":[{"internalType":"uint256","name":"_strategistFeeNumerator","type":"uint256"}],"name":"setStrategistFeeNumerator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"uint256","name":"_hint","type":"uint256"},{"internalType":"uint256","name":"_deviationNumerator","type":"uint256"},{"internalType":"uint256","name":"_deviationDenominator","type":"uint256"}],"name":"setStrategy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_targetToken","type":"address"}],"name":"setTargetToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_universalLiquidator","type":"address"}],"name":"setUniversalLiquidator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stakingWhiteList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","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":"strategies","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"strategistFeeDenominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"strategistFeeNumerator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"targetToken","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tempNextImplementationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tempNextImplementationDelayTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"universalLiquidator","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"vaults","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"uint256","name":"_hint","type":"uint256"},{"internalType":"uint256","name":"_deviationNumerator","type":"uint256"},{"internalType":"uint256","name":"_deviationDenominator","type":"uint256"}],"name":"withdrawAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]

60806040526105dc600755600060085560006009556101f4600a556000600b556000600c556101f4600d556000600e556000600f55600060105560006011553480156200004b57600080fd5b506040516200409538038062004095833981810160405260c08110156200007157600080fd5b508051602082015160408301516060840151608085015160a0909501519394929391929091856001600160a01b038116620000f3576040805162461bcd60e51b815260206004820152601e60248201527f6e65772073746f726167652073686f756c646e277420626520656d7074790000604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b03928316179055851662000163576040805162461bcd60e51b815260206004820181905260248201527f5f746172676574546f6b656e2073686f756c64206e6f7420626520656d707479604482015290519081900360640190fd5b6001600160a01b038416620001aa5760405162461bcd60e51b815260040180806020018281038252602a8152602001806200401c602a913960400191505060405180910390fd5b6001600160a01b038316620001f15760405162461bcd60e51b815260040180806020018281038252602481526020018062003ff86024913960400191505060405180910390fd5b6001600160a01b038216620002385760405162461bcd60e51b81526004018080602001828103825260288152602001806200406d6028913960400191505060405180910390fd5b60008111620002795760405162461bcd60e51b8152600401808060200182810382526027815260200180620040466027913960400191505060405180910390fd5b600180546001600160a01b03199081166001600160a01b0397881617909155600280548216958716959095179094556003805485169386169390931790925560048054909316931692909217905560065550613d1d80620002db6000396000f3fe608060405234801561001057600080fd5b506004361061038e5760003560e01c80635ba36d66116101de578063a2f61af61161010f578063ca793927116100ad578063e0ae28341161007c578063e0ae28341461098d578063e4cfbbd5146109b3578063ed32fa33146109d9578063f33e232f14610a075761038e565b8063ca7939271461093a578063d73792a914610960578063d8db022f14610968578063da8ae160146109705761038e565b8063a98e929c116100e9578063a98e929c14610842578063b60f151a1461084a578063b8393eaf14610852578063c651b514146108785761038e565b8063a2f61af61461080c578063a622ee7c14610814578063a83656931461083a5761038e565b80637c3723cf1161017c5780639137c1a7116101565780639137c1a7146107b957806392d6475e146107df57806393815eae146107e7578063975057e7146108045761038e565b80637c3723cf1461076557806383cf10811461078b578063858434cd146107935761038e565b80636da9abed116101b85780636da9abed146107275780636e4af83e1461072f578063727875f7146107555780637ba31f701461075d5761038e565b80635ba36d661461070f57806362775b7a1461071757806367fe2cb91461071f5761038e565b80632ec1acbb116102c357806339ebf8231161026157806340c0423e1161023057806340c0423e1461067357806346fe47c6146106ab57806358d94fbc146106d15780635aa6e675146107075761038e565b806339ebf823146105df5780633a3f0941146103935780633c53eddd146106055780633e3309cc146106475761038e565b80633259eeb61161029d5780633259eeb614610565578063327107f71461058b57806333d95f411461059357806338f5a5e4146105b95761038e565b80632ec1acbb146104f3578063301153f11461051957806330e412ad1461053f5761038e565b80631a6367041161033057806320d1ceaf1161030a57806320d1ceaf146104bd57806325f0234a146103935780632848efd4146104c55780632da624a3146104cd5761038e565b80631a636704146104875780631b66cb001461048f5780631dad61b4146104b55761038e565b806307e2f7131161036c57806307e2f713146103d95780630d453efb146103f857806313a869241461043257806316a66c111461046a5761038e565b8063026a0dd01461039357806303140ff4146103ad57806306974e8d146103b5575b600080fd5b61039b610a0f565b60408051918252519081900360200190f35b61039b610a15565b6103bd610a1b565b604080516001600160a01b039092168252519081900360200190f35b6103f6600480360360208110156103ef57600080fd5b5035610a2a565b005b61041e6004803603602081101561040e57600080fd5b50356001600160a01b0316610b78565b604080519115158252519081900360200190f35b6103f66004803603608081101561044857600080fd5b506001600160a01b038135169060208101359060408101359060600135610b96565b6103f66004803603602081101561048057600080fd5b503561102f565b6103f6611193565b6103f6600480360360208110156104a557600080fd5b50356001600160a01b03166112f0565b6103f6611428565b61039b611585565b61039b61158b565b61039b600480360360208110156104e357600080fd5b50356001600160a01b0316611591565b6103f66004803603602081101561050957600080fd5b50356001600160a01b03166115fe565b6103f66004803603602081101561052f57600080fd5b50356001600160a01b0316611736565b61041e6004803603602081101561055557600080fd5b50356001600160a01b031661186e565b6103f66004803603602081101561057b57600080fd5b50356001600160a01b0316611883565b6103bd6119b8565b6103f6600480360360208110156105a957600080fd5b50356001600160a01b03166119c7565b6103f6600480360360208110156105cf57600080fd5b50356001600160a01b0316611aff565b61041e600480360360208110156105f557600080fd5b50356001600160a01b0316611bdc565b6103f6600480360360a081101561061b57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060800135611bf1565b6103f66004803603604081101561065d57600080fd5b506001600160a01b038135169060200135611f10565b6103f66004803603608081101561068957600080fd5b506001600160a01b038135169060208101359060408101359060600135611fef565b61041e600480360360208110156106c157600080fd5b50356001600160a01b03166122f0565b6103f6600480360360608110156106e757600080fd5b506001600160a01b03813581169160208101359091169060400135612305565b6103bd61245f565b61039b6124df565b61039b6124e5565b61039b6124eb565b61039b6124f1565b6103f66004803603602081101561074557600080fd5b50356001600160a01b03166124f7565b61039b6125d1565b6103bd6125d7565b6103f66004803603602081101561077b57600080fd5b50356001600160a01b03166125e6565b6103bd61271e565b61041e600480360360208110156107a957600080fd5b50356001600160a01b031661272d565b6103f6600480360360208110156107cf57600080fd5b50356001600160a01b031661274b565b61039b612899565b6103f6600480360360208110156107fd57600080fd5b503561289f565b6103bd6129fa565b61039b612a09565b61041e6004803603602081101561082a57600080fd5b50356001600160a01b0316612a0f565b61039b612a24565b6103bd612a2a565b61039b612a39565b61041e6004803603602081101561086857600080fd5b50356001600160a01b0316612a3f565b6103f66004803603604081101561088e57600080fd5b8101906020810181356401000000008111156108a957600080fd5b8201836020820111156108bb57600080fd5b803590602001918460208302840111640100000000831117156108dd57600080fd5b9193909290916020810190356401000000008111156108fb57600080fd5b82018360208201111561090d57600080fd5b8035906020019184602083028401116401000000008311171561092f57600080fd5b509092509050612a54565b6103f66004803603602081101561095057600080fd5b50356001600160a01b0316612bbb565b61039b612cf3565b6103f6612cf9565b6103f66004803603602081101561098657600080fd5b5035612e56565b6103f6600480360360208110156109a357600080fd5b50356001600160a01b0316612fba565b6103f6600480360360208110156109c957600080fd5b50356001600160a01b0316613129565b6103f6600480360360408110156109ef57600080fd5b506001600160a01b0381358116916020013516613286565b6103f6613349565b61271090565b600a5481565b6004546001600160a01b031681565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b158015610a7557600080fd5b505afa158015610a89573d6000803e3d6000fd5b505050506040513d6020811015610a9f57600080fd5b5051610ae3576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b612710600d54600a5483010110610b2b5760405162461bcd60e51b8152600401808060200182810382526024815260200180613ac06024913960400191505060405180910390fd5b60088190556006544201600981905560408051838152602081019290925280517f454569828940e893d360d50bebb5e79bbce7e6747f2d14456726cc10b3ede7809281900390910190a150565b6001600160a01b031660009081526014602052604090205460ff1690565b6001600160a01b038416600090815260146020526040902054849060ff16610c05576040805162461bcd60e51b815260206004820152601460248201527f7661756c7420646f6573206e6f74206578697374000000000000000000000000604482015290519081900360640190fd5b3360009081526016602052604090205460ff1680610c3b5750610c2661245f565b6001600160a01b0316336001600160a01b0316145b610c8c576040805162461bcd60e51b815260206004820152601e60248201527f6f6e6c79206861726420776f726b65722063616e2063616c6c20746869730000604482015290519081900360640190fd5b848484846000846001600160a01b03166377c7b8fc6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ccb57600080fd5b505afa158015610cdf573d6000803e3d6000fd5b505050506040513d6020811015610cf557600080fd5b50519050670de0b6b3a764000084821115610d9657610d2a83610d1e868463ffffffff61349916565b9063ffffffff6134fb16565b610d3e86610d1e858563ffffffff61349916565b1115610d91576040805162461bcd60e51b815260206004820152601560248201527f736861726520707269636520646576696174696f6e0000000000000000000000604482015290519081900360640190fd5b610e11565b610daa83610d1e868463ffffffff61349916565b610dbe83610d1e888563ffffffff61349916565b1115610e11576040805162461bcd60e51b815260206004820152601560248201527f736861726520707269636520646576696174696f6e0000000000000000000000604482015290519081900360640190fd5b60008b6001600160a01b03166377c7b8fc6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e4c57600080fd5b505afa158015610e60573d6000803e3d6000fd5b505050506040513d6020811015610e7657600080fd5b5051604080517f4fa5d85400000000000000000000000000000000000000000000000000000000815290519192506001600160a01b038e1691634fa5d8549160048082019260009290919082900301818387803b158015610ed657600080fd5b505af1158015610eea573d6000803e3d6000fd5b505050508b6001600160a01b031663a8c62e766040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2757600080fd5b505afa158015610f3b573d6000803e3d6000fd5b505050506040513d6020811015610f5157600080fd5b5051604080517f77c7b8fc00000000000000000000000000000000000000000000000000000000815290516001600160a01b03928316928f16917f43ffccb0abea5304f42c5d67d56e479f21f76ecc142c39a770725e99125243bc91859184916377c7b8fc91600480820192602092909190829003018186803b158015610fd757600080fd5b505afa158015610feb573d6000803e3d6000fd5b505050506040513d602081101561100157600080fd5b50516040805192835260208301919091524282820152519081900360600190a3505050505050505050505050565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b15801561107a57600080fd5b505afa15801561108e573d6000803e3d6000fd5b505050506040513d60208110156110a457600080fd5b50516110e8576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b612710600754600a5483010110611146576040805162461bcd60e51b815260206004820152601e60248201527f696e76616c696420706c6174666f726d20666565206e756d657261746f720000604482015290519081900360640190fd5b600e8190556006544201600f81905560408051838152602081019290925280517fb4091cb81492903c5627f2e9c0a0edd2ff7fe98e57fd5bb5b215e6b675af97f39281900390910190a150565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b1580156111de57600080fd5b505afa1580156111f2573d6000803e3d6000fd5b505050506040513d602081101561120857600080fd5b505161124c576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b600e541580159061125e5750600f5415155b801561126c5750600f544210155b6112a75760405162461bcd60e51b815260040180806020018281038252603c815260200180613b42603c913960400191505060405180910390fd5b600e8054600d819055600091829055600f9190915560408051918252517f711032da58d7b74bfb6169701c24c8a0d61210a7d364ded469d149ffda2151ee9181900360200190a1565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b15801561133b57600080fd5b505afa15801561134f573d6000803e3d6000fd5b505050506040513d602081101561136557600080fd5b50516113a9576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b0381166113ee5760405162461bcd60e51b8152600401808060200182810382526024815260200180613b1e6024913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b15801561147357600080fd5b505afa158015611487573d6000803e3d6000fd5b505050506040513d602081101561149d57600080fd5b50516114e1576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b600b54158015906114f35750600c5415155b80156115015750600c544210155b61153c5760405162461bcd60e51b815260040180806020018281038252603e815260200180613c43603e913960400191505060405180910390fd5b600b8054600a819055600091829055600c9190915560408051918252517f9b7cdf7886710b8127124f8b9ccb48cdf4377472238df82bdf661594fcad79de9181900360200190a1565b600d5481565b600f5481565b6000816001600160a01b03166377c7b8fc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115cc57600080fd5b505afa1580156115e0573d6000803e3d6000fd5b505050506040513d60208110156115f657600080fd5b505192915050565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b15801561164957600080fd5b505afa15801561165d573d6000803e3d6000fd5b505050506040513d602081101561167357600080fd5b50516116b7576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b0381166116fc5760405162461bcd60e51b815260040180806020018281038252602c815260200180613b7e602c913960400191505060405180910390fd5b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b15801561178157600080fd5b505afa158015611795573d6000803e3d6000fd5b505050506040513d60208110156117ab57600080fd5b50516117ef576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b03811661184a576040805162461bcd60e51b815260206004820152601760248201527f5f776f726b6572206d75737420626520646566696e6564000000000000000000604482015290519081900360640190fd5b6001600160a01b03166000908152601660205260409020805460ff19166001179055565b60126020526000908152604090205460ff1681565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b1580156118ce57600080fd5b505afa1580156118e2573d6000803e3d6000fd5b505050506040513d60208110156118f857600080fd5b505161193c576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b038116611997576040805162461bcd60e51b815260206004820152601760248201527f5f776f726b6572206d75737420626520646566696e6564000000000000000000604482015290519081900360640190fd5b6001600160a01b03166000908152601660205260409020805460ff19169055565b6001546001600160a01b031681565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b158015611a1257600080fd5b505afa158015611a26573d6000803e3d6000fd5b505050506040513d6020811015611a3c57600080fd5b5051611a80576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b038116611ac55760405162461bcd60e51b815260040180806020018281038252602f815260200180613baa602f913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b158015611b4a57600080fd5b505afa158015611b5e573d6000803e3d6000fd5b505050506040513d6020811015611b7457600080fd5b5051611bb8576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b03166000908152601260205260409020805460ff19166001179055565b60156020526000908152604090205460ff1681565b848383836000846001600160a01b03166377c7b8fc6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c3057600080fd5b505afa158015611c44573d6000803e3d6000fd5b505050506040513d6020811015611c5a57600080fd5b50519050670de0b6b3a764000084821115611cef57611c8383610d1e868463ffffffff61349916565b611c9786610d1e858563ffffffff61349916565b1115611cea576040805162461bcd60e51b815260206004820152601560248201527f736861726520707269636520646576696174696f6e0000000000000000000000604482015290519081900360640190fd5b611d6a565b611d0383610d1e868463ffffffff61349916565b611d1783610d1e888563ffffffff61349916565b1115611d6a576040805162461bcd60e51b815260206004820152601560248201527f736861726520707269636520646576696174696f6e0000000000000000000000604482015290519081900360640190fd5b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b158015611db557600080fd5b505afa158015611dc9573d6000803e3d6000fd5b505050506040513d6020811015611ddf57600080fd5b5051611e23576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b038b166000908152601460205260409020548b9060ff16611e92576040805162461bcd60e51b815260206004820152601460248201527f7661756c7420646f6573206e6f74206578697374000000000000000000000000604482015290519081900360640190fd5b8b6001600160a01b03166333a100ca8c6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050600060405180830381600087803b158015611eea57600080fd5b505af1158015611efe573d6000803e3d6000fd5b50505050505050505050505050505050565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b158015611f5b57600080fd5b505afa158015611f6f573d6000803e3d6000fd5b505050506040513d6020811015611f8557600080fd5b5051611fc9576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b611feb611fd461245f565b6001600160a01b038416908363ffffffff61353d16565b5050565b838383836000846001600160a01b03166377c7b8fc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561202e57600080fd5b505afa158015612042573d6000803e3d6000fd5b505050506040513d602081101561205857600080fd5b50519050670de0b6b3a7640000848211156120ed5761208183610d1e868463ffffffff61349916565b61209586610d1e858563ffffffff61349916565b11156120e8576040805162461bcd60e51b815260206004820152601560248201527f736861726520707269636520646576696174696f6e0000000000000000000000604482015290519081900360640190fd5b612168565b61210183610d1e868463ffffffff61349916565b61211583610d1e888563ffffffff61349916565b1115612168576040805162461bcd60e51b815260206004820152601560248201527f736861726520707269636520646576696174696f6e0000000000000000000000604482015290519081900360640190fd5b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b1580156121b357600080fd5b505afa1580156121c7573d6000803e3d6000fd5b505050506040513d60208110156121dd57600080fd5b5051612221576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b038a166000908152601460205260409020548a9060ff16612290576040805162461bcd60e51b815260206004820152601460248201527f7661756c7420646f6573206e6f74206578697374000000000000000000000000604482015290519081900360640190fd5b8a6001600160a01b031663853828b66040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156122cb57600080fd5b505af11580156122df573d6000803e3d6000fd5b505050505050505050505050505050565b60136020526000908152604090205460ff1681565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b15801561235057600080fd5b505afa158015612364573d6000803e3d6000fd5b505050506040513d602081101561237a57600080fd5b50516123be576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b826001600160a01b031663bdb1b33e6123d561245f565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291861660248301526044820185905251606480830192600092919082900301818387803b15801561244257600080fd5b505af1158015612456573d6000803e3d6000fd5b50505050505050565b60008060009054906101000a90046001600160a01b03166001600160a01b0316635aa6e6756040518163ffffffff1660e01b815260040160206040518083038186803b1580156124ae57600080fd5b505afa1580156124c2573d6000803e3d6000fd5b505050506040513d60208110156124d857600080fd5b5051905090565b600c5481565b60105481565b600b5481565b600e5481565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b15801561254257600080fd5b505afa158015612556573d6000803e3d6000fd5b505050506040513d602081101561256c57600080fd5b50516125b0576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b03166000908152601260205260409020805460ff19169055565b60115481565b6005546001600160a01b031681565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b15801561263157600080fd5b505afa158015612645573d6000803e3d6000fd5b505050506040513d602081101561265b57600080fd5b505161269f576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b0381166126e45760405162461bcd60e51b8152600401808060200182810382526028815260200180613c1b6028913960400191505060405180910390fd5b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6002546001600160a01b031681565b6001600160a01b031660009081526015602052604090205460ff1690565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b15801561279657600080fd5b505afa1580156127aa573d6000803e3d6000fd5b505050506040513d60208110156127c057600080fd5b5051612804576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b03811661285f576040805162461bcd60e51b815260206004820152601e60248201527f6e65772073746f726167652073686f756c646e277420626520656d7074790000604482015290519081900360640190fd5b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b60095481565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b1580156128ea57600080fd5b505afa1580156128fe573d6000803e3d6000fd5b505050506040513d602081101561291457600080fd5b5051612958576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b600081116129ad576040805162461bcd60e51b815260206004820181905260248201527f696e76616c6964205f6e657874496d706c656d656e746174696f6e44656c6179604482015290519081900360640190fd5b60108190556006544201601181905560408051838152602081019290925280517f50094cf031d78c61151cd4a2ee4b75a70ab0686745d91b602f3a3a55cd82e7e49281900390910190a150565b6000546001600160a01b031681565b60085481565b60146020526000908152604090205460ff1681565b60065481565b6003546001600160a01b031681565b60075481565b60166020526000908152604090205460ff1681565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b158015612a9f57600080fd5b505afa158015612ab3573d6000803e3d6000fd5b505050506040513d6020811015612ac957600080fd5b5051612b0d576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b828114612b61576040805162461bcd60e51b815260206004820181905260248201527f696e76616c6964207661756c74732f73747261746567696573206c656e677468604482015290519081900360640190fd5b60005b83811015612bb457612bac858583818110612b7b57fe5b905060200201356001600160a01b0316848484818110612b9757fe5b905060200201356001600160a01b03166135c2565b600101612b64565b5050505050565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b158015612c0657600080fd5b505afa158015612c1a573d6000803e3d6000fd5b505050506040513d6020811015612c3057600080fd5b5051612c74576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b038116612cb95760405162461bcd60e51b8152600401808060200182810382526028815260200180613c1b6028913960400191505060405180910390fd5b600580547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b61271081565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b158015612d4457600080fd5b505afa158015612d58573d6000803e3d6000fd5b505050506040513d6020811015612d6e57600080fd5b5051612db2576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b60085415801590612dc4575060095415155b8015612dd257506009544210155b612e0d5760405162461bcd60e51b815260040180806020018281038252603e815260200180613cab603e913960400191505060405180910390fd5b60088054600781905560009182905560099190915560408051918252517f23e1dd55aa2ebe15ad326d57337eac57d86808cb57db0b78e1d0fc549831ae689181900360200190a1565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b158015612ea157600080fd5b505afa158015612eb5573d6000803e3d6000fd5b505050506040513d6020811015612ecb57600080fd5b5051612f0f576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b612710600754600d5483010110612f6d576040805162461bcd60e51b815260206004820181905260248201527f696e76616c6964207374726174656769737420666565206e756d657261746f72604482015290519081900360640190fd5b600b8190556006544201600c81905560408051838152602081019290925280517fd6d7504e192bf5c67617a4eb5c31d19d6228d84c4dda481ed6b09eb56c71ac709281900390910190a150565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b15801561300557600080fd5b505afa158015613019573d6000803e3d6000fd5b505050506040513d602081101561302f57600080fd5b5051613073576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b03811660009081526013602052604090205460ff166130e0576040805162461bcd60e51b815260206004820152601f60248201527f5f746172676574206d75737420616c7265616479206265207374616b696e6700604482015290519081900360640190fd5b6001600160a01b038116600081815260136020526040808220805460ff19169055517f6936ae2c79519cdd02e17a16c92a9f62ae3b9899dfa1f4698b3e5ecf6b57b48f9190a250565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b15801561317457600080fd5b505afa158015613188573d6000803e3d6000fd5b505050506040513d602081101561319e57600080fd5b50516131e2576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6001600160a01b03811660009081526013602052604090205460ff161561323a5760405162461bcd60e51b8152600401808060200182810382526021815260200180613bfa6021913960400191505060405180910390fd5b6001600160a01b038116600081815260136020526040808220805460ff19166001179055517f47825c9e94699c45b22f07199fef1946a332d8e2bfa49f2c92b6059136f2a3649190a250565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b1580156132d157600080fd5b505afa1580156132e5573d6000803e3d6000fd5b505050506040513d60208110156132fb57600080fd5b505161333f576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b611feb82826135c2565b600054604080516337b87c3960e21b815233600482015290516001600160a01b039092169163dee1f0e491602480820192602092909190829003018186803b15801561339457600080fd5b505afa1580156133a8573d6000803e3d6000fd5b505050506040513d60208110156133be57600080fd5b5051613402576040805162461bcd60e51b815260206004820152600e60248201526d4e6f7420676f7665726e616e636560901b604482015290519081900360640190fd5b6011541580159061341557506011544210155b6134505760405162461bcd60e51b815260040180806020018281038252603a815260200180613ae4603a913960400191505060405180910390fd5b60108054600681905560009182905560119190915560408051918252517f40d822b056e584aa7a80824c44ea8fcb499c7d6854c938e4c5634fc506d5482e9181900360200190a1565b6000826134a8575060006134f5565b828202828482816134b557fe5b04146134f25760405162461bcd60e51b8152600401808060200182810382526021815260200180613bd96021913960400191505060405180910390fd5b90505b92915050565b60006134f283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613805565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526135bd9084906138a7565b505050565b6001600160a01b03821661361d576040805162461bcd60e51b815260206004820152601c60248201527f6e6577207661756c742073686f756c646e277420626520656d70747900000000604482015290519081900360640190fd5b6001600160a01b03821660009081526014602052604090205460ff161561368b576040805162461bcd60e51b815260206004820152601460248201527f7661756c7420616c726561647920657869737473000000000000000000000000604482015290519081900360640190fd5b6001600160a01b03811660009081526015602052604090205460ff16156136f9576040805162461bcd60e51b815260206004820152601760248201527f737472617465677920616c726561647920657869737473000000000000000000604482015290519081900360640190fd5b6001600160a01b038116613754576040805162461bcd60e51b815260206004820152601f60248201527f6e65772073747261746567792073686f756c646e277420626520656d70747900604482015290519081900360640190fd5b6001600160a01b0382811660008181526014602090815260408083208054600160ff199182168117909255958716808552601590935281842080549096161790945583517f33a100ca0000000000000000000000000000000000000000000000000000000081526004810191909152925191926333a100ca926024808301939282900301818387803b1580156137e957600080fd5b505af11580156137fd573d6000803e3d6000fd5b505050505050565b600081836138915760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561385657818101518382015260200161383e565b50505050905090810190601f1680156138835780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161389d57fe5b0495945050505050565b6138b9826001600160a01b0316613a83565b61390a576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b6020831061396657805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613929565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146139c8576040519150601f19603f3d011682016040523d82523d6000602084013e6139cd565b606091505b509150915081613a24576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115613a7d57808060200190516020811015613a4057600080fd5b5051613a7d5760405162461bcd60e51b815260040180806020018281038252602a815260200180613c81602a913960400191505060405180910390fd5b50505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590613ab757508115155b94935050505056fe696e76616c69642070726f6669742073686172696e6720666565206e756d657261746f72696e76616c69642074696d657374616d70206f72206e6f206e657720696d706c656d656e746174696f6e2064656c617920636f6e6669726d65646e65772074617267657420746f6b656e2073686f756c64206e6f7420626520656d707479696e76616c69642074696d657374616d70206f72206e6f206e657720706c6174666f726d20666565206e756d657261746f7220636f6e6669726d65646e657720756e6976657273616c206c697175696461746f722073686f756c64206e6f7420626520656d7074796e65772070726f6669742073686172696e672072656365697665722073686f756c64206e6f7420626520656d707479536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775f7461726765742063616e6e6f7420616c7265616479206265207374616b696e676e65772072657761726420666f727761726465722073686f756c64206e6f7420626520656d707479696e76616c69642074696d657374616d70206f72206e6f206e6577207374726174656769737420666565206e756d657261746f7220636f6e6669726d65645361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564696e76616c69642074696d657374616d70206f72206e6f206e65772070726f6669742073686172696e67206e756d657261746f7220636f6e6669726d6564a265627a7a723158209a795df7a10174f60e8ff9114cc5df7a46fae8ed7e8091a940fd55de6dc3190f64736f6c634300051000325f726577617264466f727761726465722073686f756c64206e6f7420626520656d7074795f70726f66697453686172696e6752656365697665722073686f756c64206e6f7420626520656d7074795f6e657874496d706c656d656e746174696f6e44656c61792073686f756c6420626520677420305f756e6976657273616c4c697175696461746f722073686f756c64206e6f7420626520656d707479000000000000000000000000c1234a98617385d1a4b87274465375409f7e248f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab10000000000000000000000005f11efdf4422b548007cae9919b0b38c35fa6be700000000000000000000000026b27e13e38fa8f8e43b8fc3ff7c601a8aa0d032000000000000000000000000e5dcf0eb836adb04ff58a472b6924fe941c4fe76000000000000000000000000000000000000000000000000000000000000003c

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000c1234a98617385d1a4b87274465375409f7e248f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab10000000000000000000000005f11efdf4422b548007cae9919b0b38c35fa6be700000000000000000000000026b27e13e38fa8f8e43b8fc3ff7c601a8aa0d032000000000000000000000000e5dcf0eb836adb04ff58a472b6924fe941c4fe76000000000000000000000000000000000000000000000000000000000000003c

-----Decoded View---------------
Arg [0] : _storage (address): 0xc1234a98617385d1a4b87274465375409f7e248f
Arg [1] : _targetToken (address): 0x82af49447d8a07e3bd95bd0d56f35241523fbab1
Arg [2] : _profitSharingReceiver (address): 0x5f11efdf4422b548007cae9919b0b38c35fa6be7
Arg [3] : _rewardForwarder (address): 0x26b27e13e38fa8f8e43b8fc3ff7c601a8aa0d032
Arg [4] : _universalLiquidator (address): 0xe5dcf0eb836adb04ff58a472b6924fe941c4fe76
Arg [5] : _nextImplementationDelay (uint256): 60

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000c1234a98617385d1a4b87274465375409f7e248f
Arg [1] : 00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
Arg [2] : 0000000000000000000000005f11efdf4422b548007cae9919b0b38c35fa6be7
Arg [3] : 00000000000000000000000026b27e13e38fa8f8e43b8fc3ff7c601a8aa0d032
Arg [4] : 000000000000000000000000e5dcf0eb836adb04ff58a472b6924fe941c4fe76
Arg [5] : 000000000000000000000000000000000000000000000000000000000000003c


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.