{
  "language": "Solidity",
  "sources": {
    "contracts/interfaces/IMasterChef.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\n\ninterface IMasterChef {\n    using BoringERC20 for IERC20;\n    struct UserInfo {\n        uint256 amount;     // How many LP tokens the user has provided.\n        uint256 rewardDebt; // Reward debt. See explanation below.\n    }\n\n    struct PoolInfo {\n        IERC20 lpToken;           // Address of LP token contract.\n        uint256 allocPoint;       // How many allocation points assigned to this pool. SUSHI to distribute per block.\n        uint256 lastRewardBlock;  // Last block number that SUSHI distribution occurs.\n        uint256 accSushiPerShare; // Accumulated SUSHI per share, times 1e12. See below.\n    }\n\n    function poolInfo(uint256 pid) external view returns (IMasterChef.PoolInfo memory);\n    function totalAllocPoint() external view returns (uint256);\n    function deposit(uint256 _pid, uint256 _amount) external;\n}\n"
    },
    "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.6.12;\n\nimport \"../interfaces/IERC20.sol\";\n\nlibrary BoringERC20 {\n    function safeSymbol(IERC20 token) internal view returns(string memory) {\n        (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x95d89b41));\n        return success && data.length > 0 ? abi.decode(data, (string)) : \"???\";\n    }\n\n    function safeName(IERC20 token) internal view returns(string memory) {\n        (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x06fdde03));\n        return success && data.length > 0 ? abi.decode(data, (string)) : \"???\";\n    }\n\n    function safeDecimals(IERC20 token) internal view returns (uint8) {\n        (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x313ce567));\n        return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;\n    }\n\n    function safeTransfer(IERC20 token, address to, uint256 amount) internal {\n        (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0xa9059cbb, to, amount));\n        require(success && (data.length == 0 || abi.decode(data, (bool))), \"BoringERC20: Transfer failed\");\n    }\n\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 amount) internal {\n        (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0x23b872dd, from, to, amount));\n        require(success && (data.length == 0 || abi.decode(data, (bool))), \"BoringERC20: TransferFrom failed\");\n    }\n}"
    },
    "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\ninterface IERC20 {\n    function totalSupply() external view returns (uint256);\n    function balanceOf(address account) external view returns (uint256);\n    function allowance(address owner, address spender) external view returns (uint256);\n    function approve(address spender, uint256 amount) external returns (bool);\n    event Transfer(address indexed from, address indexed to, uint256 value);\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    // EIP 2612\n    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n}"
    },
    "contracts/MiniChefV2.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringBatchable.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\nimport \"./libraries/SignedSafeMath.sol\";\nimport \"./interfaces/IRewarder.sol\";\nimport \"./interfaces/IMasterChef.sol\";\n\ninterface IMigratorChef {\n    // Take the current LP token address and return the new LP token address.\n    // Migrator should have full access to the caller's LP token.\n    function migrate(IERC20 token) external returns (IERC20);\n}\n\n/// @notice The (older) MasterChef contract gives out a constant number of SUSHI tokens per block.\n/// It is the only address with minting rights for SUSHI.\n/// The idea for this MasterChef V2 (MCV2) contract is therefore to be the owner of a dummy token\n/// that is deposited into the MasterChef V1 (MCV1) contract.\n/// The allocation point for this pool on MCV1 is the total allocation point for all pools that receive double incentives.\ncontract MiniChefV2 is BoringOwnable, BoringBatchable {\n    using BoringMath for uint256;\n    using BoringMath128 for uint128;\n    using BoringERC20 for IERC20;\n    using SignedSafeMath for int256;\n\n    /// @notice Info of each MCV2 user.\n    /// `amount` LP token amount the user has provided.\n    /// `rewardDebt` The amount of SUSHI entitled to the user.\n    struct UserInfo {\n        uint256 amount;\n        int256 rewardDebt;\n    }\n\n    /// @notice Info of each MCV2 pool.\n    /// `allocPoint` The amount of allocation points assigned to the pool.\n    /// Also known as the amount of SUSHI to distribute per block.\n    struct PoolInfo {\n        uint128 accSushiPerShare;\n        uint64 lastRewardTime;\n        uint64 allocPoint;\n    }\n\n    /// @notice Address of SUSHI contract.\n    IERC20 public immutable SUSHI;\n    // @notice The migrator contract. It has a lot of power. Can only be set through governance (owner).\n    IMigratorChef public migrator;\n\n    /// @notice Info of each MCV2 pool.\n    PoolInfo[] public poolInfo;\n    /// @notice Address of the LP token for each MCV2 pool.\n    IERC20[] public lpToken;\n    /// @notice Address of each `IRewarder` contract in MCV2.\n    IRewarder[] public rewarder;\n\n    /// @notice Info of each user that stakes LP tokens.\n    mapping (uint256 => mapping (address => UserInfo)) public userInfo;\n    /// @dev Total allocation points. Must be the sum of all allocation points in all pools.\n    uint256 public totalAllocPoint;\n\n    uint256 public sushiPerSecond;\n    uint256 private constant ACC_SUSHI_PRECISION = 1e12;\n\n    event Deposit(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n    event Withdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n    event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n    event Harvest(address indexed user, uint256 indexed pid, uint256 amount);\n    event LogPoolAddition(uint256 indexed pid, uint256 allocPoint, IERC20 indexed lpToken, IRewarder indexed rewarder);\n    event LogSetPool(uint256 indexed pid, uint256 allocPoint, IRewarder indexed rewarder, bool overwrite);\n    event LogUpdatePool(uint256 indexed pid, uint64 lastRewardTime, uint256 lpSupply, uint256 accSushiPerShare);\n    event LogSushiPerSecond(uint256 sushiPerSecond);\n\n    /// @param _sushi The SUSHI token contract address.\n    constructor(IERC20 _sushi) public {\n        SUSHI = _sushi;\n    }\n\n    /// @notice Returns the number of MCV2 pools.\n    function poolLength() public view returns (uint256 pools) {\n        pools = poolInfo.length;\n    }\n\n    /// @notice Add a new LP to the pool. Can only be called by the owner.\n    /// DO NOT add the same LP token more than once. Rewards will be messed up if you do.\n    /// @param allocPoint AP of the new pool.\n    /// @param _lpToken Address of the LP ERC-20 token.\n    /// @param _rewarder Address of the rewarder delegate.\n    function add(uint256 allocPoint, IERC20 _lpToken, IRewarder _rewarder) public onlyOwner {\n        totalAllocPoint = totalAllocPoint.add(allocPoint);\n        lpToken.push(_lpToken);\n        rewarder.push(_rewarder);\n\n        poolInfo.push(PoolInfo({\n            allocPoint: allocPoint.to64(),\n            lastRewardTime: block.timestamp.to64(),\n            accSushiPerShare: 0\n        }));\n        emit LogPoolAddition(lpToken.length.sub(1), allocPoint, _lpToken, _rewarder);\n    }\n\n    /// @notice Update the given pool's SUSHI allocation point and `IRewarder` contract. Can only be called by the owner.\n    /// @param _pid The index of the pool. See `poolInfo`.\n    /// @param _allocPoint New AP of the pool.\n    /// @param _rewarder Address of the rewarder delegate.\n    /// @param overwrite True if _rewarder should be `set`. Otherwise `_rewarder` is ignored.\n    function set(uint256 _pid, uint256 _allocPoint, IRewarder _rewarder, bool overwrite) public onlyOwner {\n        totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint);\n        poolInfo[_pid].allocPoint = _allocPoint.to64();\n        if (overwrite) { rewarder[_pid] = _rewarder; }\n        emit LogSetPool(_pid, _allocPoint, overwrite ? _rewarder : rewarder[_pid], overwrite);\n    }\n\n    /// @notice Sets the sushi per second to be distributed. Can only be called by the owner.\n    /// @param _sushiPerSecond The amount of Sushi to be distributed per second.\n    function setSushiPerSecond(uint256 _sushiPerSecond) public onlyOwner {\n        sushiPerSecond = _sushiPerSecond;\n        emit LogSushiPerSecond(_sushiPerSecond);\n    }\n\n    /// @notice Set the `migrator` contract. Can only be called by the owner.\n    /// @param _migrator The contract address to set.\n    function setMigrator(IMigratorChef _migrator) public onlyOwner {\n        migrator = _migrator;\n    }\n\n    /// @notice Migrate LP token to another LP contract through the `migrator` contract.\n    /// @param _pid The index of the pool. See `poolInfo`.\n    function migrate(uint256 _pid) public {\n        require(address(migrator) != address(0), \"MasterChefV2: no migrator set\");\n        IERC20 _lpToken = lpToken[_pid];\n        uint256 bal = _lpToken.balanceOf(address(this));\n        _lpToken.approve(address(migrator), bal);\n        IERC20 newLpToken = migrator.migrate(_lpToken);\n        require(bal == newLpToken.balanceOf(address(this)), \"MasterChefV2: migrated balance must match\");\n        lpToken[_pid] = newLpToken;\n    }\n\n    /// @notice View function to see pending SUSHI on frontend.\n    /// @param _pid The index of the pool. See `poolInfo`.\n    /// @param _user Address of user.\n    /// @return pending SUSHI reward for a given user.\n    function pendingSushi(uint256 _pid, address _user) external view returns (uint256 pending) {\n        PoolInfo memory pool = poolInfo[_pid];\n        UserInfo storage user = userInfo[_pid][_user];\n        uint256 accSushiPerShare = pool.accSushiPerShare;\n        uint256 lpSupply = lpToken[_pid].balanceOf(address(this));\n        if (block.timestamp > pool.lastRewardTime && lpSupply != 0) {\n            uint256 time = block.timestamp.sub(pool.lastRewardTime);\n            uint256 sushiReward = time.mul(sushiPerSecond).mul(pool.allocPoint) / totalAllocPoint;\n            accSushiPerShare = accSushiPerShare.add(sushiReward.mul(ACC_SUSHI_PRECISION) / lpSupply);\n        }\n        pending = int256(user.amount.mul(accSushiPerShare) / ACC_SUSHI_PRECISION).sub(user.rewardDebt).toUInt256();\n    }\n\n    /// @notice Update reward variables for all pools. Be careful of gas spending!\n    /// @param pids Pool IDs of all to be updated. Make sure to update all active pools.\n    function massUpdatePools(uint256[] calldata pids) external {\n        uint256 len = pids.length;\n        for (uint256 i = 0; i < len; ++i) {\n            updatePool(pids[i]);\n        }\n    }\n\n    /// @notice Update reward variables of the given pool.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @return pool Returns the pool that was updated.\n    function updatePool(uint256 pid) public returns (PoolInfo memory pool) {\n        pool = poolInfo[pid];\n        if (block.timestamp > pool.lastRewardTime) {\n            uint256 lpSupply = lpToken[pid].balanceOf(address(this));\n            if (lpSupply > 0) {\n                uint256 time = block.timestamp.sub(pool.lastRewardTime);\n                uint256 sushiReward = time.mul(sushiPerSecond).mul(pool.allocPoint) / totalAllocPoint;\n                pool.accSushiPerShare = pool.accSushiPerShare.add((sushiReward.mul(ACC_SUSHI_PRECISION) / lpSupply).to128());\n            }\n            pool.lastRewardTime = block.timestamp.to64();\n            poolInfo[pid] = pool;\n            emit LogUpdatePool(pid, pool.lastRewardTime, lpSupply, pool.accSushiPerShare);\n        }\n    }\n\n    /// @notice Deposit LP tokens to MCV2 for SUSHI allocation.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @param amount LP token amount to deposit.\n    /// @param to The receiver of `amount` deposit benefit.\n    function deposit(uint256 pid, uint256 amount, address to) public {\n        PoolInfo memory pool = updatePool(pid);\n        UserInfo storage user = userInfo[pid][to];\n\n        // Effects\n        user.amount = user.amount.add(amount);\n        user.rewardDebt = user.rewardDebt.add(int256(amount.mul(pool.accSushiPerShare) / ACC_SUSHI_PRECISION));\n\n        // Interactions\n        IRewarder _rewarder = rewarder[pid];\n        if (address(_rewarder) != address(0)) {\n            _rewarder.onSushiReward(pid, to, to, 0, user.amount);\n        }\n\n        lpToken[pid].safeTransferFrom(msg.sender, address(this), amount);\n\n        emit Deposit(msg.sender, pid, amount, to);\n    }\n\n    /// @notice Withdraw LP tokens from MCV2.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @param amount LP token amount to withdraw.\n    /// @param to Receiver of the LP tokens.\n    function withdraw(uint256 pid, uint256 amount, address to) public {\n        PoolInfo memory pool = updatePool(pid);\n        UserInfo storage user = userInfo[pid][msg.sender];\n\n        // Effects\n        user.rewardDebt = user.rewardDebt.sub(int256(amount.mul(pool.accSushiPerShare) / ACC_SUSHI_PRECISION));\n        user.amount = user.amount.sub(amount);\n\n        // Interactions\n        IRewarder _rewarder = rewarder[pid];\n        if (address(_rewarder) != address(0)) {\n            _rewarder.onSushiReward(pid, msg.sender, to, 0, user.amount);\n        }\n        \n        lpToken[pid].safeTransfer(to, amount);\n\n        emit Withdraw(msg.sender, pid, amount, to);\n    }\n\n    /// @notice Harvest proceeds for transaction sender to `to`.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @param to Receiver of SUSHI rewards.\n    function harvest(uint256 pid, address to) public {\n        PoolInfo memory pool = updatePool(pid);\n        UserInfo storage user = userInfo[pid][msg.sender];\n        int256 accumulatedSushi = int256(user.amount.mul(pool.accSushiPerShare) / ACC_SUSHI_PRECISION);\n        uint256 _pendingSushi = accumulatedSushi.sub(user.rewardDebt).toUInt256();\n\n        // Effects\n        user.rewardDebt = accumulatedSushi;\n\n        // Interactions\n        if (_pendingSushi != 0) {\n            SUSHI.safeTransfer(to, _pendingSushi);\n        }\n        \n        IRewarder _rewarder = rewarder[pid];\n        if (address(_rewarder) != address(0)) {\n            _rewarder.onSushiReward( pid, msg.sender, to, _pendingSushi, user.amount);\n        }\n\n        emit Harvest(msg.sender, pid, _pendingSushi);\n    }\n    \n    /// @notice Withdraw LP tokens from MCV2 and harvest proceeds for transaction sender to `to`.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @param amount LP token amount to withdraw.\n    /// @param to Receiver of the LP tokens and SUSHI rewards.\n    function withdrawAndHarvest(uint256 pid, uint256 amount, address to) public {\n        PoolInfo memory pool = updatePool(pid);\n        UserInfo storage user = userInfo[pid][msg.sender];\n        int256 accumulatedSushi = int256(user.amount.mul(pool.accSushiPerShare) / ACC_SUSHI_PRECISION);\n        uint256 _pendingSushi = accumulatedSushi.sub(user.rewardDebt).toUInt256();\n\n        // Effects\n        user.rewardDebt = accumulatedSushi.sub(int256(amount.mul(pool.accSushiPerShare) / ACC_SUSHI_PRECISION));\n        user.amount = user.amount.sub(amount);\n        \n        // Interactions\n        SUSHI.safeTransfer(to, _pendingSushi);\n\n        IRewarder _rewarder = rewarder[pid];\n        if (address(_rewarder) != address(0)) {\n            _rewarder.onSushiReward(pid, msg.sender, to, _pendingSushi, user.amount);\n        }\n\n        lpToken[pid].safeTransfer(to, amount);\n\n        emit Withdraw(msg.sender, pid, amount, to);\n        emit Harvest(msg.sender, pid, _pendingSushi);\n    }\n\n    /// @notice Withdraw without caring about rewards. EMERGENCY ONLY.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @param to Receiver of the LP tokens.\n    function emergencyWithdraw(uint256 pid, address to) public {\n        UserInfo storage user = userInfo[pid][msg.sender];\n        uint256 amount = user.amount;\n        user.amount = 0;\n        user.rewardDebt = 0;\n\n        IRewarder _rewarder = rewarder[pid];\n        if (address(_rewarder) != address(0)) {\n            _rewarder.onSushiReward(pid, msg.sender, to, 0, 0);\n        }\n\n        // Note: transfer can fail or succeed if `amount` is zero.\n        lpToken[pid].safeTransfer(to, amount);\n        emit EmergencyWithdraw(msg.sender, pid, amount, to);\n    }\n}\n"
    },
    "@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n// a library for performing overflow-safe math, updated with awesomeness from of DappHub (https://github.com/dapphub/ds-math)\nlibrary BoringMath {\n    function add(uint256 a, uint256 b) internal pure returns (uint256 c) {require((c = a + b) >= b, \"BoringMath: Add Overflow\");}\n    function sub(uint256 a, uint256 b) internal pure returns (uint256 c) {require((c = a - b) <= a, \"BoringMath: Underflow\");}\n    function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {require(b == 0 || (c = a * b)/b == a, \"BoringMath: Mul Overflow\");}\n    function to128(uint256 a) internal pure returns (uint128 c) {\n        require(a <= uint128(-1), \"BoringMath: uint128 Overflow\");\n        c = uint128(a);\n    }\n    function to64(uint256 a) internal pure returns (uint64 c) {\n        require(a <= uint64(-1), \"BoringMath: uint64 Overflow\");\n        c = uint64(a);\n    }\n    function to32(uint256 a) internal pure returns (uint32 c) {\n        require(a <= uint32(-1), \"BoringMath: uint32 Overflow\");\n        c = uint32(a);\n    }\n}\n\nlibrary BoringMath128 {\n    function add(uint128 a, uint128 b) internal pure returns (uint128 c) {require((c = a + b) >= b, \"BoringMath: Add Overflow\");}\n    function sub(uint128 a, uint128 b) internal pure returns (uint128 c) {require((c = a - b) <= a, \"BoringMath: Underflow\");}\n}\n\nlibrary BoringMath64 {\n    function add(uint64 a, uint64 b) internal pure returns (uint64 c) {require((c = a + b) >= b, \"BoringMath: Add Overflow\");}\n    function sub(uint64 a, uint64 b) internal pure returns (uint64 c) {require((c = a - b) <= a, \"BoringMath: Underflow\");}\n}\n\nlibrary BoringMath32 {\n    function add(uint32 a, uint32 b) internal pure returns (uint32 c) {require((c = a + b) >= b, \"BoringMath: Add Overflow\");}\n    function sub(uint32 a, uint32 b) internal pure returns (uint32 c) {require((c = a - b) <= a, \"BoringMath: Underflow\");}\n}"
    },
    "@boringcrypto/boring-solidity/contracts/BoringBatchable.sol": {
      "content": "// SPDX-License-Identifier: UNLICENSED\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\n\n// P1 - P3: OK\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n// solhint-disable avoid-low-level-calls\n\nimport \"./libraries/BoringERC20.sol\";\n\n// T1 - T4: OK\ncontract BaseBoringBatchable {\n    function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {\n        // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n        if (_returnData.length < 68) return \"Transaction reverted silently\";\n\n        assembly {\n            // Slice the sighash.\n            _returnData := add(_returnData, 0x04)\n        }\n        return abi.decode(_returnData, (string)); // All that remains is the revert string\n    }    \n    \n    // F3 - F9: OK\n    // F1: External is ok here because this is the batch function, adding it to a batch makes no sense\n    // F2: Calls in the batch may be payable, delegatecall operates in the same context, so each call in the batch has access to msg.value\n    // C1 - C21: OK\n    // C3: The length of the loop is fully under user control, so can't be exploited\n    // C7: Delegatecall is only used on the same contract, so it's safe\n    function batch(bytes[] calldata calls, bool revertOnFail) external payable returns(bool[] memory successes, bytes[] memory results) {\n        // Interactions\n        successes = new bool[](calls.length);\n        results = new bytes[](calls.length);\n        for (uint256 i = 0; i < calls.length; i++) {\n            (bool success, bytes memory result) = address(this).delegatecall(calls[i]);\n            require(success || !revertOnFail, _getRevertMsg(result));\n            successes[i] = success;\n            results[i] = result;\n        }\n    }\n}\n\n// T1 - T4: OK\ncontract BoringBatchable is BaseBoringBatchable {\n    // F1 - F9: OK\n    // F6: Parameters can be used front-run the permit and the user's permit will fail (due to nonce or other revert)\n    //     if part of a batch this could be used to grief once as the second call would not need the permit\n    // C1 - C21: OK\n    function permitToken(IERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n        // Interactions\n        // X1 - X5\n        token.permit(from, to, amount, deadline, v, r, s);\n    }\n}"
    },
    "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\n\n// P1 - P3: OK\npragma solidity 0.6.12;\n\n// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol\n// Edited by BoringCrypto\n\n// T1 - T4: OK\ncontract BoringOwnableData {\n    // V1 - V5: OK\n    address public owner;\n    // V1 - V5: OK\n    address public pendingOwner;\n}\n\n// T1 - T4: OK\ncontract BoringOwnable is BoringOwnableData {\n    // E1: OK\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    constructor () public {\n        owner = msg.sender;\n        emit OwnershipTransferred(address(0), msg.sender);\n    }\n\n    // F1 - F9: OK\n    // C1 - C21: OK\n    function transferOwnership(address newOwner, bool direct, bool renounce) public onlyOwner {\n        if (direct) {\n            // Checks\n            require(newOwner != address(0) || renounce, \"Ownable: zero address\");\n\n            // Effects\n            emit OwnershipTransferred(owner, newOwner);\n            owner = newOwner;\n            pendingOwner = address(0);\n        } else {\n            // Effects\n            pendingOwner = newOwner;\n        }\n    }\n\n    // F1 - F9: OK\n    // C1 - C21: OK\n    function claimOwnership() public {\n        address _pendingOwner = pendingOwner;\n        \n        // Checks\n        require(msg.sender == _pendingOwner, \"Ownable: caller != pending owner\");\n\n        // Effects\n        emit OwnershipTransferred(owner, _pendingOwner);\n        owner = _pendingOwner;\n        pendingOwner = address(0);\n    }\n\n    // M1 - M5: OK\n    // C1 - C21: OK\n    modifier onlyOwner() {\n        require(msg.sender == owner, \"Ownable: caller is not the owner\");\n        _;\n    }\n}"
    },
    "contracts/libraries/SignedSafeMath.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary SignedSafeMath {\n    int256 constant private _INT256_MIN = -2**255;\n\n    /**\n     * @dev Returns the multiplication of two signed integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     *\n     * - Multiplication cannot overflow.\n     */\n    function mul(int256 a, int256 b) internal pure returns (int256) {\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n        // benefit is lost if 'b' is also tested.\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n        if (a == 0) {\n            return 0;\n        }\n\n        require(!(a == -1 && b == _INT256_MIN), \"SignedSafeMath: multiplication overflow\");\n\n        int256 c = a * b;\n        require(c / a == b, \"SignedSafeMath: multiplication overflow\");\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the integer division of two signed integers. Reverts on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(int256 a, int256 b) internal pure returns (int256) {\n        require(b != 0, \"SignedSafeMath: division by zero\");\n        require(!(b == -1 && a == _INT256_MIN), \"SignedSafeMath: division overflow\");\n\n        int256 c = a / b;\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the subtraction of two signed integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(int256 a, int256 b) internal pure returns (int256) {\n        int256 c = a - b;\n        require((b >= 0 && c <= a) || (b < 0 && c > a), \"SignedSafeMath: subtraction overflow\");\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the addition of two signed integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     *\n     * - Addition cannot overflow.\n     */\n    function add(int256 a, int256 b) internal pure returns (int256) {\n        int256 c = a + b;\n        require((b >= 0 && c >= a) || (b < 0 && c < a), \"SignedSafeMath: addition overflow\");\n\n        return c;\n    }\n\n    function toUInt256(int256 a) internal pure returns (uint256) {\n        require(a >= 0, \"Integer < 0\");\n        return uint256(a);\n    }\n}"
    },
    "contracts/interfaces/IRewarder.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\ninterface IRewarder {\n    using BoringERC20 for IERC20;\n    function onSushiReward(uint256 pid, address user, address recipient, uint256 sushiAmount, uint256 newLpAmount) external;\n    function pendingTokens(uint256 pid, address user, uint256 sushiAmount) external view returns (IERC20[] memory, uint256[] memory);\n}\n"
    },
    "contracts/mocks/RewarderMock.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"../interfaces/IRewarder.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\n\n\ncontract RewarderMock is IRewarder {\n    using BoringMath for uint256;\n    using BoringERC20 for IERC20;\n    uint256 private immutable rewardMultiplier;\n    IERC20 private immutable rewardToken;\n    uint256 private constant REWARD_TOKEN_DIVISOR = 1e18;\n    address private immutable MASTERCHEF_V2;\n\n    constructor (uint256 _rewardMultiplier, IERC20 _rewardToken, address _MASTERCHEF_V2) public {\n        rewardMultiplier = _rewardMultiplier;\n        rewardToken = _rewardToken;\n        MASTERCHEF_V2 = _MASTERCHEF_V2;\n    }\n\n    function onSushiReward (uint256, address user, address to, uint256 sushiAmount, uint256) onlyMCV2 override external {\n        uint256 pendingReward = sushiAmount.mul(rewardMultiplier) / REWARD_TOKEN_DIVISOR;\n        uint256 rewardBal = rewardToken.balanceOf(address(this));\n        if (pendingReward > rewardBal) {\n            rewardToken.safeTransfer(to, rewardBal);\n        } else {\n            rewardToken.safeTransfer(to, pendingReward);\n        }\n    }\n    \n    function pendingTokens(uint256 pid, address user, uint256 sushiAmount) override external view returns (IERC20[] memory rewardTokens, uint256[] memory rewardAmounts) {\n        IERC20[] memory _rewardTokens = new IERC20[](1);\n        _rewardTokens[0] = (rewardToken);\n        uint256[] memory _rewardAmounts = new uint256[](1);\n        _rewardAmounts[0] = sushiAmount.mul(rewardMultiplier) / REWARD_TOKEN_DIVISOR;\n        return (_rewardTokens, _rewardAmounts);\n    }\n\n    modifier onlyMCV2 {\n        require(\n            msg.sender == MASTERCHEF_V2,\n            \"Only MCV2 can call this function.\"\n        );\n        _;\n    }\n  \n}\n"
    },
    "contracts/mocks/ComplexRewarderTime.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\nimport \"../interfaces/IRewarder.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\nimport \"../MasterChefV2.sol\";\n\n/// @author @0xKeno\ncontract ComplexRewarderTime is IRewarder,  BoringOwnable{\n    using BoringMath for uint256;\n    using BoringMath128 for uint128;\n    using BoringERC20 for IERC20;\n\n    IERC20 private immutable rewardToken;\n\n    /// @notice Info of each MCV2 user.\n    /// `amount` LP token amount the user has provided.\n    /// `rewardDebt` The amount of SUSHI entitled to the user.\n    struct UserInfo {\n        uint256 amount;\n        uint256 rewardDebt;\n    }\n\n    /// @notice Info of each MCV2 pool.\n    /// `allocPoint` The amount of allocation points assigned to the pool.\n    /// Also known as the amount of SUSHI to distribute per block.\n    struct PoolInfo {\n        uint128 accSushiPerShare;\n        uint64 lastRewardTime;\n        uint64 allocPoint;\n    }\n\n    /// @notice Info of each pool.\n    mapping (uint256 => PoolInfo) public poolInfo;\n\n    uint256[] public poolIds;\n\n    /// @notice Info of each user that stakes LP tokens.\n    mapping (uint256 => mapping (address => UserInfo)) public userInfo;\n    /// @dev Total allocation points. Must be the sum of all allocation points in all pools.\n    uint256 totalAllocPoint;\n\n    uint256 public rewardPerSecond;\n    uint256 private constant ACC_TOKEN_PRECISION = 1e12;\n\n    address private immutable MASTERCHEF_V2;\n\n    event LogOnReward(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n    event LogPoolAddition(uint256 indexed pid, uint256 allocPoint);\n    event LogSetPool(uint256 indexed pid, uint256 allocPoint);\n    event LogUpdatePool(uint256 indexed pid, uint64 lastRewardTime, uint256 lpSupply, uint256 accSushiPerShare);\n    event LogRewardPerSecond(uint256 rewardPerSecond);\n    event LogInit();\n\n    constructor (IERC20 _rewardToken, uint256 _rewardPerSecond, address _MASTERCHEF_V2) public {\n        rewardToken = _rewardToken;\n        rewardPerSecond = _rewardPerSecond;\n        MASTERCHEF_V2 = _MASTERCHEF_V2;\n    }\n\n\n    function onSushiReward (uint256 pid, address _user, address to, uint256, uint256 lpToken) onlyMCV2 override external {\n        PoolInfo memory pool = updatePool(pid);\n        UserInfo storage user = userInfo[pid][_user];\n        uint256 pending;\n        if (user.amount > 0) {\n            pending =\n                (user.amount.mul(pool.accSushiPerShare) / ACC_TOKEN_PRECISION).sub(\n                    user.rewardDebt\n                );\n            rewardToken.safeTransfer(to, pending);\n        }\n        user.amount = lpToken;\n        user.rewardDebt = lpToken.mul(pool.accSushiPerShare) / ACC_TOKEN_PRECISION;\n        emit LogOnReward(_user, pid, pending, to);\n    }\n    \n    function pendingTokens(uint256 pid, address user, uint256) override external view returns (IERC20[] memory rewardTokens, uint256[] memory rewardAmounts) {\n        IERC20[] memory _rewardTokens = new IERC20[](1);\n        _rewardTokens[0] = (rewardToken);\n        uint256[] memory _rewardAmounts = new uint256[](1);\n        _rewardAmounts[0] = pendingToken(pid, user);\n        return (_rewardTokens, _rewardAmounts);\n    }\n\n    /// @notice Sets the sushi per second to be distributed. Can only be called by the owner.\n    /// @param _rewardPerSecond The amount of Sushi to be distributed per second.\n    function setRewardPerSecond(uint256 _rewardPerSecond) public onlyOwner {\n        rewardPerSecond = _rewardPerSecond;\n        emit LogRewardPerSecond(_rewardPerSecond);\n    }\n\n    modifier onlyMCV2 {\n        require(\n            msg.sender == MASTERCHEF_V2,\n            \"Only MCV2 can call this function.\"\n        );\n        _;\n    }\n\n    /// @notice Returns the number of MCV2 pools.\n    function poolLength() public view returns (uint256 pools) {\n        pools = poolIds.length;\n    }\n\n    /// @notice Add a new LP to the pool. Can only be called by the owner.\n    /// DO NOT add the same LP token more than once. Rewards will be messed up if you do.\n    /// @param allocPoint AP of the new pool.\n    /// @param _pid Pid on MCV2\n    function add(uint256 allocPoint, uint256 _pid) public onlyOwner {\n        require(poolInfo[_pid].lastRewardTime == 0, \"Pool already exists\");\n        uint256 lastRewardTime = block.timestamp;\n        totalAllocPoint = totalAllocPoint.add(allocPoint);\n\n        poolInfo[_pid] = PoolInfo({\n            allocPoint: allocPoint.to64(),\n            lastRewardTime: lastRewardTime.to64(),\n            accSushiPerShare: 0\n        });\n        poolIds.push(_pid);\n        emit LogPoolAddition(_pid, allocPoint);\n    }\n\n    /// @notice Update the given pool's SUSHI allocation point and `IRewarder` contract. Can only be called by the owner.\n    /// @param _pid The index of the pool. See `poolInfo`.\n    /// @param _allocPoint New AP of the pool.\n    function set(uint256 _pid, uint256 _allocPoint) public onlyOwner {\n        totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint);\n        poolInfo[_pid].allocPoint = _allocPoint.to64();\n        emit LogSetPool(_pid, _allocPoint);\n    }\n\n    /// @notice View function to see pending Token\n    /// @param _pid The index of the pool. See `poolInfo`.\n    /// @param _user Address of user.\n    /// @return pending SUSHI reward for a given user.\n    function pendingToken(uint256 _pid, address _user) public view returns (uint256 pending) {\n        PoolInfo memory pool = poolInfo[_pid];\n        UserInfo storage user = userInfo[_pid][_user];\n        uint256 accSushiPerShare = pool.accSushiPerShare;\n        uint256 lpSupply = MasterChefV2(MASTERCHEF_V2).lpToken(_pid).balanceOf(MASTERCHEF_V2);\n        if (block.timestamp > pool.lastRewardTime && lpSupply != 0) {\n            uint256 time = block.timestamp.sub(pool.lastRewardTime);\n            uint256 sushiReward = time.mul(rewardPerSecond).mul(pool.allocPoint) / totalAllocPoint;\n            accSushiPerShare = accSushiPerShare.add(sushiReward.mul(ACC_TOKEN_PRECISION) / lpSupply);\n        }\n        pending = (user.amount.mul(accSushiPerShare) / ACC_TOKEN_PRECISION).sub(user.rewardDebt);\n    }\n\n    /// @notice Update reward variables for all pools. Be careful of gas spending!\n    /// @param pids Pool IDs of all to be updated. Make sure to update all active pools.\n    function massUpdatePools(uint256[] calldata pids) external {\n        uint256 len = pids.length;\n        for (uint256 i = 0; i < len; ++i) {\n            updatePool(pids[i]);\n        }\n    }\n\n    /// @notice Update reward variables of the given pool.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @return pool Returns the pool that was updated.\n    function updatePool(uint256 pid) public returns (PoolInfo memory pool) {\n        pool = poolInfo[pid];\n        if (block.timestamp > pool.lastRewardTime) {\n            uint256 lpSupply = MasterChefV2(MASTERCHEF_V2).lpToken(pid).balanceOf(MASTERCHEF_V2);\n\n            if (lpSupply > 0) {\n                uint256 time = block.timestamp.sub(pool.lastRewardTime);\n                uint256 sushiReward = time.mul(rewardPerSecond).mul(pool.allocPoint) / totalAllocPoint;\n                pool.accSushiPerShare = pool.accSushiPerShare.add((sushiReward.mul(ACC_TOKEN_PRECISION) / lpSupply).to128());\n            }\n            pool.lastRewardTime = block.timestamp.to64();\n            poolInfo[pid] = pool;\n            emit LogUpdatePool(pid, pool.lastRewardTime, lpSupply, pool.accSushiPerShare);\n        }\n    }\n\n}\n"
    },
    "contracts/MasterChefV2.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringBatchable.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\nimport \"./libraries/SignedSafeMath.sol\";\nimport \"./interfaces/IRewarder.sol\";\nimport \"./interfaces/IMasterChef.sol\";\n\ninterface IMigratorChef {\n    // Take the current LP token address and return the new LP token address.\n    // Migrator should have full access to the caller's LP token.\n    function migrate(IERC20 token) external returns (IERC20);\n}\n\n/// @notice The (older) MasterChef contract gives out a constant number of SUSHI tokens per block.\n/// It is the only address with minting rights for SUSHI.\n/// The idea for this MasterChef V2 (MCV2) contract is therefore to be the owner of a dummy token\n/// that is deposited into the MasterChef V1 (MCV1) contract.\n/// The allocation point for this pool on MCV1 is the total allocation point for all pools that receive double incentives.\ncontract MasterChefV2 is BoringOwnable, BoringBatchable {\n    using BoringMath for uint256;\n    using BoringMath128 for uint128;\n    using BoringERC20 for IERC20;\n    using SignedSafeMath for int256;\n\n    /// @notice Info of each MCV2 user.\n    /// `amount` LP token amount the user has provided.\n    /// `rewardDebt` The amount of SUSHI entitled to the user.\n    struct UserInfo {\n        uint256 amount;\n        int256 rewardDebt;\n    }\n\n    /// @notice Info of each MCV2 pool.\n    /// `allocPoint` The amount of allocation points assigned to the pool.\n    /// Also known as the amount of SUSHI to distribute per block.\n    struct PoolInfo {\n        uint128 accSushiPerShare;\n        uint64 lastRewardBlock;\n        uint64 allocPoint;\n    }\n\n    /// @notice Address of MCV1 contract.\n    IMasterChef public immutable MASTER_CHEF;\n    /// @notice Address of SUSHI contract.\n    IERC20 public immutable SUSHI;\n    /// @notice The index of MCV2 master pool in MCV1.\n    uint256 public immutable MASTER_PID;\n    // @notice The migrator contract. It has a lot of power. Can only be set through governance (owner).\n    IMigratorChef public migrator;\n\n    /// @notice Info of each MCV2 pool.\n    PoolInfo[] public poolInfo;\n    /// @notice Address of the LP token for each MCV2 pool.\n    IERC20[] public lpToken;\n    /// @notice Address of each `IRewarder` contract in MCV2.\n    IRewarder[] public rewarder;\n\n    /// @notice Info of each user that stakes LP tokens.\n    mapping (uint256 => mapping (address => UserInfo)) public userInfo;\n    /// @dev Total allocation points. Must be the sum of all allocation points in all pools.\n    uint256 public totalAllocPoint;\n\n    uint256 private constant MASTERCHEF_SUSHI_PER_BLOCK = 1e20;\n    uint256 private constant ACC_SUSHI_PRECISION = 1e12;\n\n    event Deposit(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n    event Withdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n    event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n    event Harvest(address indexed user, uint256 indexed pid, uint256 amount);\n    event LogPoolAddition(uint256 indexed pid, uint256 allocPoint, IERC20 indexed lpToken, IRewarder indexed rewarder);\n    event LogSetPool(uint256 indexed pid, uint256 allocPoint, IRewarder indexed rewarder, bool overwrite);\n    event LogUpdatePool(uint256 indexed pid, uint64 lastRewardBlock, uint256 lpSupply, uint256 accSushiPerShare);\n    event LogInit();\n\n    /// @param _MASTER_CHEF The SushiSwap MCV1 contract address.\n    /// @param _sushi The SUSHI token contract address.\n    /// @param _MASTER_PID The pool ID of the dummy token on the base MCV1 contract.\n    constructor(IMasterChef _MASTER_CHEF, IERC20 _sushi, uint256 _MASTER_PID) public {\n        MASTER_CHEF = _MASTER_CHEF;\n        SUSHI = _sushi;\n        MASTER_PID = _MASTER_PID;\n    }\n\n    /// @notice Deposits a dummy token to `MASTER_CHEF` MCV1. This is required because MCV1 holds the minting rights for SUSHI.\n    /// Any balance of transaction sender in `dummyToken` is transferred.\n    /// The allocation point for the pool on MCV1 is the total allocation point for all pools that receive double incentives.\n    /// @param dummyToken The address of the ERC-20 token to deposit into MCV1.\n    function init(IERC20 dummyToken) external {\n        uint256 balance = dummyToken.balanceOf(msg.sender);\n        require(balance != 0, \"MasterChefV2: Balance must exceed 0\");\n        dummyToken.safeTransferFrom(msg.sender, address(this), balance);\n        dummyToken.approve(address(MASTER_CHEF), balance);\n        MASTER_CHEF.deposit(MASTER_PID, balance);\n        emit LogInit();\n    }\n\n    /// @notice Returns the number of MCV2 pools.\n    function poolLength() public view returns (uint256 pools) {\n        pools = poolInfo.length;\n    }\n\n    /// @notice Add a new LP to the pool. Can only be called by the owner.\n    /// DO NOT add the same LP token more than once. Rewards will be messed up if you do.\n    /// @param allocPoint AP of the new pool.\n    /// @param _lpToken Address of the LP ERC-20 token.\n    /// @param _rewarder Address of the rewarder delegate.\n    function add(uint256 allocPoint, IERC20 _lpToken, IRewarder _rewarder) public onlyOwner {\n        uint256 lastRewardBlock = block.number;\n        totalAllocPoint = totalAllocPoint.add(allocPoint);\n        lpToken.push(_lpToken);\n        rewarder.push(_rewarder);\n\n        poolInfo.push(PoolInfo({\n            allocPoint: allocPoint.to64(),\n            lastRewardBlock: lastRewardBlock.to64(),\n            accSushiPerShare: 0\n        }));\n        emit LogPoolAddition(lpToken.length.sub(1), allocPoint, _lpToken, _rewarder);\n    }\n\n    /// @notice Update the given pool's SUSHI allocation point and `IRewarder` contract. Can only be called by the owner.\n    /// @param _pid The index of the pool. See `poolInfo`.\n    /// @param _allocPoint New AP of the pool.\n    /// @param _rewarder Address of the rewarder delegate.\n    /// @param overwrite True if _rewarder should be `set`. Otherwise `_rewarder` is ignored.\n    function set(uint256 _pid, uint256 _allocPoint, IRewarder _rewarder, bool overwrite) public onlyOwner {\n        totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint);\n        poolInfo[_pid].allocPoint = _allocPoint.to64();\n        if (overwrite) { rewarder[_pid] = _rewarder; }\n        emit LogSetPool(_pid, _allocPoint, overwrite ? _rewarder : rewarder[_pid], overwrite);\n    }\n\n    /// @notice Set the `migrator` contract. Can only be called by the owner.\n    /// @param _migrator The contract address to set.\n    function setMigrator(IMigratorChef _migrator) public onlyOwner {\n        migrator = _migrator;\n    }\n\n    /// @notice Migrate LP token to another LP contract through the `migrator` contract.\n    /// @param _pid The index of the pool. See `poolInfo`.\n    function migrate(uint256 _pid) public {\n        require(address(migrator) != address(0), \"MasterChefV2: no migrator set\");\n        IERC20 _lpToken = lpToken[_pid];\n        uint256 bal = _lpToken.balanceOf(address(this));\n        _lpToken.approve(address(migrator), bal);\n        IERC20 newLpToken = migrator.migrate(_lpToken);\n        require(bal == newLpToken.balanceOf(address(this)), \"MasterChefV2: migrated balance must match\");\n        lpToken[_pid] = newLpToken;\n    }\n\n    /// @notice View function to see pending SUSHI on frontend.\n    /// @param _pid The index of the pool. See `poolInfo`.\n    /// @param _user Address of user.\n    /// @return pending SUSHI reward for a given user.\n    function pendingSushi(uint256 _pid, address _user) external view returns (uint256 pending) {\n        PoolInfo memory pool = poolInfo[_pid];\n        UserInfo storage user = userInfo[_pid][_user];\n        uint256 accSushiPerShare = pool.accSushiPerShare;\n        uint256 lpSupply = lpToken[_pid].balanceOf(address(this));\n        if (block.number > pool.lastRewardBlock && lpSupply != 0) {\n            uint256 blocks = block.number.sub(pool.lastRewardBlock);\n            uint256 sushiReward = blocks.mul(sushiPerBlock()).mul(pool.allocPoint) / totalAllocPoint;\n            accSushiPerShare = accSushiPerShare.add(sushiReward.mul(ACC_SUSHI_PRECISION) / lpSupply);\n        }\n        pending = int256(user.amount.mul(accSushiPerShare) / ACC_SUSHI_PRECISION).sub(user.rewardDebt).toUInt256();\n    }\n\n    /// @notice Update reward variables for all pools. Be careful of gas spending!\n    /// @param pids Pool IDs of all to be updated. Make sure to update all active pools.\n    function massUpdatePools(uint256[] calldata pids) external {\n        uint256 len = pids.length;\n        for (uint256 i = 0; i < len; ++i) {\n            updatePool(pids[i]);\n        }\n    }\n\n    /// @notice Calculates and returns the `amount` of SUSHI per block.\n    function sushiPerBlock() public view returns (uint256 amount) {\n        amount = uint256(MASTERCHEF_SUSHI_PER_BLOCK)\n            .mul(MASTER_CHEF.poolInfo(MASTER_PID).allocPoint) / MASTER_CHEF.totalAllocPoint();\n    }\n\n    /// @notice Update reward variables of the given pool.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @return pool Returns the pool that was updated.\n    function updatePool(uint256 pid) public returns (PoolInfo memory pool) {\n        pool = poolInfo[pid];\n        if (block.number > pool.lastRewardBlock) {\n            uint256 lpSupply = lpToken[pid].balanceOf(address(this));\n            if (lpSupply > 0) {\n                uint256 blocks = block.number.sub(pool.lastRewardBlock);\n                uint256 sushiReward = blocks.mul(sushiPerBlock()).mul(pool.allocPoint) / totalAllocPoint;\n                pool.accSushiPerShare = pool.accSushiPerShare.add((sushiReward.mul(ACC_SUSHI_PRECISION) / lpSupply).to128());\n            }\n            pool.lastRewardBlock = block.number.to64();\n            poolInfo[pid] = pool;\n            emit LogUpdatePool(pid, pool.lastRewardBlock, lpSupply, pool.accSushiPerShare);\n        }\n    }\n\n    /// @notice Deposit LP tokens to MCV2 for SUSHI allocation.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @param amount LP token amount to deposit.\n    /// @param to The receiver of `amount` deposit benefit.\n    function deposit(uint256 pid, uint256 amount, address to) public {\n        PoolInfo memory pool = updatePool(pid);\n        UserInfo storage user = userInfo[pid][to];\n\n        // Effects\n        user.amount = user.amount.add(amount);\n        user.rewardDebt = user.rewardDebt.add(int256(amount.mul(pool.accSushiPerShare) / ACC_SUSHI_PRECISION));\n\n        // Interactions\n        IRewarder _rewarder = rewarder[pid];\n        if (address(_rewarder) != address(0)) {\n            _rewarder.onSushiReward(pid, to, to, 0, user.amount);\n        }\n\n        lpToken[pid].safeTransferFrom(msg.sender, address(this), amount);\n\n        emit Deposit(msg.sender, pid, amount, to);\n    }\n\n    /// @notice Withdraw LP tokens from MCV2.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @param amount LP token amount to withdraw.\n    /// @param to Receiver of the LP tokens.\n    function withdraw(uint256 pid, uint256 amount, address to) public {\n        PoolInfo memory pool = updatePool(pid);\n        UserInfo storage user = userInfo[pid][msg.sender];\n\n        // Effects\n        user.rewardDebt = user.rewardDebt.sub(int256(amount.mul(pool.accSushiPerShare) / ACC_SUSHI_PRECISION));\n        user.amount = user.amount.sub(amount);\n\n        // Interactions\n        IRewarder _rewarder = rewarder[pid];\n        if (address(_rewarder) != address(0)) {\n            _rewarder.onSushiReward(pid, msg.sender, to, 0, user.amount);\n        }\n        \n        lpToken[pid].safeTransfer(to, amount);\n\n        emit Withdraw(msg.sender, pid, amount, to);\n    }\n\n    /// @notice Harvest proceeds for transaction sender to `to`.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @param to Receiver of SUSHI rewards.\n    function harvest(uint256 pid, address to) public {\n        PoolInfo memory pool = updatePool(pid);\n        UserInfo storage user = userInfo[pid][msg.sender];\n        int256 accumulatedSushi = int256(user.amount.mul(pool.accSushiPerShare) / ACC_SUSHI_PRECISION);\n        uint256 _pendingSushi = accumulatedSushi.sub(user.rewardDebt).toUInt256();\n\n        // Effects\n        user.rewardDebt = accumulatedSushi;\n\n        // Interactions\n        if (_pendingSushi != 0) {\n            SUSHI.safeTransfer(to, _pendingSushi);\n        }\n        \n        IRewarder _rewarder = rewarder[pid];\n        if (address(_rewarder) != address(0)) {\n            _rewarder.onSushiReward( pid, msg.sender, to, _pendingSushi, user.amount);\n        }\n\n        emit Harvest(msg.sender, pid, _pendingSushi);\n    }\n    \n    /// @notice Withdraw LP tokens from MCV2 and harvest proceeds for transaction sender to `to`.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @param amount LP token amount to withdraw.\n    /// @param to Receiver of the LP tokens and SUSHI rewards.\n    function withdrawAndHarvest(uint256 pid, uint256 amount, address to) public {\n        PoolInfo memory pool = updatePool(pid);\n        UserInfo storage user = userInfo[pid][msg.sender];\n        int256 accumulatedSushi = int256(user.amount.mul(pool.accSushiPerShare) / ACC_SUSHI_PRECISION);\n        uint256 _pendingSushi = accumulatedSushi.sub(user.rewardDebt).toUInt256();\n\n        // Effects\n        user.rewardDebt = accumulatedSushi.sub(int256(amount.mul(pool.accSushiPerShare) / ACC_SUSHI_PRECISION));\n        user.amount = user.amount.sub(amount);\n        \n        // Interactions\n        SUSHI.safeTransfer(to, _pendingSushi);\n\n        IRewarder _rewarder = rewarder[pid];\n        if (address(_rewarder) != address(0)) {\n            _rewarder.onSushiReward(pid, msg.sender, to, _pendingSushi, user.amount);\n        }\n\n        lpToken[pid].safeTransfer(to, amount);\n\n        emit Withdraw(msg.sender, pid, amount, to);\n        emit Harvest(msg.sender, pid, _pendingSushi);\n    }\n\n    /// @notice Harvests SUSHI from `MASTER_CHEF` MCV1 and pool `MASTER_PID` to this MCV2 contract.\n    function harvestFromMasterChef() public {\n        MASTER_CHEF.deposit(MASTER_PID, 0);\n    }\n\n    /// @notice Withdraw without caring about rewards. EMERGENCY ONLY.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @param to Receiver of the LP tokens.\n    function emergencyWithdraw(uint256 pid, address to) public {\n        UserInfo storage user = userInfo[pid][msg.sender];\n        uint256 amount = user.amount;\n        user.amount = 0;\n        user.rewardDebt = 0;\n\n        IRewarder _rewarder = rewarder[pid];\n        if (address(_rewarder) != address(0)) {\n            _rewarder.onSushiReward(pid, msg.sender, to, 0, 0);\n        }\n\n        // Note: transfer can fail or succeed if `amount` is zero.\n        lpToken[pid].safeTransfer(to, amount);\n        emit EmergencyWithdraw(msg.sender, pid, amount, to);\n    }\n}\n"
    },
    "contracts/mocks/ComplexRewarder.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\nimport \"../interfaces/IRewarder.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\nimport \"../MasterChefV2.sol\";\n\n/// @author @0xKeno\ncontract ComplexRewarder is IRewarder,  BoringOwnable{\n    using BoringMath for uint256;\n    using BoringMath128 for uint128;\n    using BoringERC20 for IERC20;\n\n    IERC20 private immutable rewardToken;\n\n    /// @notice Info of each MCV2 user.\n    /// `amount` LP token amount the user has provided.\n    /// `rewardDebt` The amount of SUSHI entitled to the user.\n    struct UserInfo {\n        uint256 amount;\n        uint256 rewardDebt;\n    }\n\n    /// @notice Info of each MCV2 pool.\n    /// `allocPoint` The amount of allocation points assigned to the pool.\n    /// Also known as the amount of SUSHI to distribute per block.\n    struct PoolInfo {\n        uint128 accSushiPerShare;\n        uint64 lastRewardBlock;\n        uint64 allocPoint;\n    }\n\n    /// @notice Info of each pool.\n    mapping (uint256 => PoolInfo) public poolInfo;\n\n    uint256[] public poolIds;\n\n    /// @notice Info of each user that stakes LP tokens.\n    mapping (uint256 => mapping (address => UserInfo)) public userInfo;\n    /// @dev Total allocation points. Must be the sum of all allocation points in all pools.\n    uint256 totalAllocPoint;\n\n    uint256 public tokenPerBlock;\n    uint256 private constant ACC_TOKEN_PRECISION = 1e12;\n\n    address private immutable MASTERCHEF_V2;\n\n    event LogOnReward(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n    event LogPoolAddition(uint256 indexed pid, uint256 allocPoint);\n    event LogSetPool(uint256 indexed pid, uint256 allocPoint);\n    event LogUpdatePool(uint256 indexed pid, uint64 lastRewardBlock, uint256 lpSupply, uint256 accSushiPerShare);\n    event LogInit();\n\n    constructor (IERC20 _rewardToken, uint256 _tokenPerBlock, address _MASTERCHEF_V2) public {\n        rewardToken = _rewardToken;\n        tokenPerBlock = _tokenPerBlock;\n        MASTERCHEF_V2 = _MASTERCHEF_V2;\n    }\n\n\n    function onSushiReward (uint256 pid, address _user, address to, uint256, uint256 lpToken) onlyMCV2 override external {\n        PoolInfo memory pool = updatePool(pid);\n        UserInfo storage user = userInfo[pid][_user];\n        uint256 pending;\n        if (user.amount > 0) {\n            pending =\n                (user.amount.mul(pool.accSushiPerShare) / ACC_TOKEN_PRECISION).sub(\n                    user.rewardDebt\n                );\n            rewardToken.safeTransfer(to, pending);\n        }\n        user.amount = lpToken;\n        user.rewardDebt = lpToken.mul(pool.accSushiPerShare) / ACC_TOKEN_PRECISION;\n        emit LogOnReward(_user, pid, pending, to);\n    }\n    \n    function pendingTokens(uint256 pid, address user, uint256) override external view returns (IERC20[] memory rewardTokens, uint256[] memory rewardAmounts) {\n        IERC20[] memory _rewardTokens = new IERC20[](1);\n        _rewardTokens[0] = (rewardToken);\n        uint256[] memory _rewardAmounts = new uint256[](1);\n        _rewardAmounts[0] = pendingToken(pid, user);\n        return (_rewardTokens, _rewardAmounts);\n    }\n\n    modifier onlyMCV2 {\n        require(\n            msg.sender == MASTERCHEF_V2,\n            \"Only MCV2 can call this function.\"\n        );\n        _;\n    }\n\n    /// @notice Returns the number of MCV2 pools.\n    function poolLength() public view returns (uint256 pools) {\n        pools = poolIds.length;\n    }\n\n    /// @notice Add a new LP to the pool.  Can only be called by the owner.\n    /// DO NOT add the same LP token more than once. Rewards will be messed up if you do.\n    /// @param allocPoint AP of the new pool.\n    /// @param _pid Pid on MCV2\n    function add(uint256 allocPoint, uint256 _pid) public onlyOwner {\n        require(poolInfo[_pid].lastRewardBlock == 0, \"Pool already exists\");\n        uint256 lastRewardBlock = block.number;\n        totalAllocPoint = totalAllocPoint.add(allocPoint);\n\n        poolInfo[_pid] = PoolInfo({\n            allocPoint: allocPoint.to64(),\n            lastRewardBlock: lastRewardBlock.to64(),\n            accSushiPerShare: 0\n        });\n        poolIds.push(_pid);\n        emit LogPoolAddition(_pid, allocPoint);\n    }\n\n    /// @notice Update the given pool's SUSHI allocation point and `IRewarder` contract. Can only be called by the owner.\n    /// @param _pid The index of the pool. See `poolInfo`.\n    /// @param _allocPoint New AP of the pool.\n    function set(uint256 _pid, uint256 _allocPoint) public onlyOwner {\n        totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint);\n        poolInfo[_pid].allocPoint = _allocPoint.to64();\n        emit LogSetPool(_pid, _allocPoint);\n    }\n\n    /// @notice View function to see pending Token\n    /// @param _pid The index of the pool. See `poolInfo`.\n    /// @param _user Address of user.\n    /// @return pending SUSHI reward for a given user.\n    function pendingToken(uint256 _pid, address _user) public view returns (uint256 pending) {\n        PoolInfo memory pool = poolInfo[_pid];\n        UserInfo storage user = userInfo[_pid][_user];\n        uint256 accSushiPerShare = pool.accSushiPerShare;\n        uint256 lpSupply = MasterChefV2(MASTERCHEF_V2).lpToken(_pid).balanceOf(MASTERCHEF_V2);\n        if (block.number > pool.lastRewardBlock && lpSupply != 0) {\n            uint256 blocks = block.number.sub(pool.lastRewardBlock);\n            uint256 sushiReward = blocks.mul(tokenPerBlock).mul(pool.allocPoint) / totalAllocPoint;\n            accSushiPerShare = accSushiPerShare.add(sushiReward.mul(ACC_TOKEN_PRECISION) / lpSupply);\n        }\n        pending = (user.amount.mul(accSushiPerShare) / ACC_TOKEN_PRECISION).sub(user.rewardDebt);\n    }\n\n    /// @notice Update reward variables for all pools. Be careful of gas spending!\n    /// @param pids Pool IDs of all to be updated. Make sure to update all active pools.\n    function massUpdatePools(uint256[] calldata pids) external {\n        uint256 len = pids.length;\n        for (uint256 i = 0; i < len; ++i) {\n            updatePool(pids[i]);\n        }\n    }\n\n    /// @notice Update reward variables of the given pool.\n    /// @param pid The index of the pool. See `poolInfo`.\n    /// @return pool Returns the pool that was updated.\n    function updatePool(uint256 pid) public returns (PoolInfo memory pool) {\n        pool = poolInfo[pid];\n        require(pool.lastRewardBlock != 0, \"Pool does not exist\");\n        if (block.number > pool.lastRewardBlock) {\n            uint256 lpSupply = MasterChefV2(MASTERCHEF_V2).lpToken(pid).balanceOf(MASTERCHEF_V2);\n\n            if (lpSupply > 0) {\n                uint256 blocks = block.number.sub(pool.lastRewardBlock);\n                uint256 sushiReward = blocks.mul(tokenPerBlock).mul(pool.allocPoint) / totalAllocPoint;\n                pool.accSushiPerShare = pool.accSushiPerShare.add((sushiReward.mul(ACC_TOKEN_PRECISION) / lpSupply).to128());\n            }\n            pool.lastRewardBlock = block.number.to64();\n            poolInfo[pid] = pool;\n            emit LogUpdatePool(pid, pool.lastRewardBlock, lpSupply, pool.accSushiPerShare);\n        }\n    }\n\n}\n"
    },
    "contracts/mocks/RewarderBrokenMock.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"../interfaces/IRewarder.sol\";\n\n\ncontract RewarderBrokenMock is IRewarder {\n\n    function onSushiReward (uint256, address, address, uint256, uint256) override external {\n        revert();\n    }\n\n    function pendingTokens(uint256 pid, address user, uint256 sushiAmount) override external view returns (IERC20[] memory rewardTokens, uint256[] memory rewardAmounts){\n        revert();\n    }\n  \n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "storageLayout",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    },
    "metadata": {
      "useLiteralContent": true
    },
    "libraries": {
      "": {
        "__CACHE_BREAKER__": "0x00000000d41867734bbee4c6863d9255b2b06ac1"
      }
    }
  }
}