creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "/contracts/ExtraRewardStashV3.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.6.12;\r\n\r\nimport \"./Interfaces.sol\";\r\nimport \"./interfaces/IRewardHook.sol\";\r\nimport \"./interfaces/IProxyFactory.sol\";\r\nimport \"./interfaces/IStashTokenWrapper.sol\";\r\nimport '@openzeppelin/contracts/math/SafeMath.sol';\r\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\r\nimport '@openzeppelin/contracts/utils/Address.sol';\r\nimport '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';\r\n\r\n\r\n//Stash v3: support for curve gauge reward redirect\r\n//v3.1: support for arbitrary token rewards outside of gauge rewards\r\n//      add reward hook to pull rewards during claims\r\n//v3.2: move constuctor to init function for proxy creation\r\n//v3.3: add extra checks and restrictions, wrap reward tokens\r\n\r\ncontract ExtraRewardStashV3 {\r\n    using SafeERC20 for IERC20;\r\n    using Address for address;\r\n    using SafeMath for uint256;\r\n\r\n    address public constant crv = address(0xD533a949740bb3306d119CC777fa900bA034cd52);\r\n    address public constant cvx = address(0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B);\r\n    uint256 private constant maxRewards = 8;\r\n    uint256 private constant maxTotalRewards = 12;\r\n    address public constant proxyFactory = address(0x66807B5598A848602734B82E432dD88DBE13fC8f);\r\n\r\n    address public immutable tokenWrapperImplementation;\r\n\r\n    uint256 public pid;\r\n    address public operator;\r\n    address public staker;\r\n    address public gauge;\r\n    address public rewardFactory;\r\n   \r\n    mapping(address => uint256) public historicalRewards;\r\n    bool public hasRedirected;\r\n    bool public hasCurveRewards;\r\n\r\n    struct TokenInfo {\r\n        address token;\r\n        address rewardAddress;\r\n        address wrapperAddress;\r\n    }\r\n\r\n    //use mapping+array so that we dont have to loop check each time setToken is called\r\n    mapping(address => TokenInfo) public tokenInfo;\r\n    address[] public tokenList;\r\n\r\n    //address to call for reward pulls\r\n    address public rewardHook;\r\n\r\n    constructor(address _wrapperImplementation) public {\r\n        tokenWrapperImplementation = _wrapperImplementation;\r\n    }\r\n\r\n    function initialize(uint256 _pid, address _operator, address _staker, address _gauge, address _rFactory) external {\r\n        require(gauge == address(0),\"!init\");\r\n        pid = _pid;\r\n        operator = _operator;\r\n        staker = _staker;\r\n        gauge = _gauge;\r\n        rewardFactory = _rFactory;\r\n    }\r\n\r\n    function getName() external pure returns (string memory) {\r\n        return \"ExtraRewardStashV3.4\";\r\n    }\r\n\r\n    function tokenCount() external view returns (uint256){\r\n        return tokenList.length;\r\n    }\r\n\r\n    //try claiming if there are reward tokens registered\r\n    function claimRewards() external returns (bool) {\r\n        require(msg.sender == operator, \"!operator\");\r\n        uint256 boosterCrv = IERC20(crv).balanceOf(operator);\r\n\r\n        //this is updateable from v2 gauges now so must check each time.\r\n        checkForNewRewardTokens();\r\n\r\n        //make sure we're redirected\r\n        if(!hasRedirected){\r\n            IDeposit(operator).setGaugeRedirect(pid);\r\n            hasRedirected = true;\r\n\r\n            //always make sure cvx is added as well\r\n            setToken(cvx);\r\n        }\r\n\r\n        if(hasCurveRewards){\r\n            //claim rewards on gauge for staker\r\n            //using reward_receiver so all rewards will be moved to this stash\r\n            IDeposit(operator).claimRewards(pid,gauge);\r\n        }\r\n\r\n        //hook for reward pulls\r\n        if(rewardHook != address(0)){\r\n            try IRewardHook(rewardHook).onRewardClaim(){\r\n            }catch{}\r\n        }\r\n\r\n        require(boosterCrv == IERC20(crv).balanceOf(operator),\"crvChange\");\r\n        return true;\r\n    }\r\n   \r\n\r\n    //check if gauge rewards have changed\r\n    function checkForNewRewardTokens() internal {\r\n        for(uint256 i = 0; i < maxRewards; i++){\r\n            address token = ICurveGauge(gauge).reward_tokens(i);\r\n            if (token == address(0)) {\r\n                break;\r\n            }\r\n            if(!hasCurveRewards){\r\n                hasCurveRewards = true;\r\n            }\r\n            setToken(token);\r\n        }\r\n    }\r\n\r\n    //register an extra reward token to be handled\r\n    // (any new incentive that is not directly on curve gauges)\r\n    function setExtraReward(address _token) external{\r\n        //owner of booster can set extra rewards\r\n        require(IDeposit(operator).owner() == msg.sender, \"!owner\");\r\n        require(tokenList.length < maxTotalRewards,\"rwd cnt\");\r\n\r\n        setToken(_token);\r\n    }\r\n\r\n    function setRewardHook(address _hook) external{\r\n        //owner of booster can set reward hook\r\n        require(IDeposit(operator).owner() == msg.sender, \"!owner\");\r\n\r\n        rewardHook = _hook;\r\n    }\r\n\r\n\r\n    //replace a token on token list\r\n    function setToken(address _token) internal {\r\n        TokenInfo storage t = tokenInfo[_token];\r\n\r\n        if(t.token == address(0)){\r\n            //set token address\r\n            t.token = _token;\r\n\r\n            //check if crv\r\n            if(_token != crv){\r\n                //create new wrapper\r\n                address tokenwrapper = IProxyFactory(proxyFactory).clone(tokenWrapperImplementation);\r\n                \r\n                //create new reward contract (for NON-crv tokens only)\r\n                (,,,address mainRewardContract,,) = IDeposit(operator).poolInfo(pid);\r\n                address rewardContract = IRewardFactory(rewardFactory).CreateTokenRewards(\r\n                    tokenwrapper,//add the wrapper as reward token\r\n                    mainRewardContract,\r\n                    address(this));\r\n                \r\n                t.rewardAddress = rewardContract;\r\n                t.wrapperAddress = tokenwrapper;\r\n\r\n                //init wrapper\r\n                IStashTokenWrapper(tokenwrapper).init(_token, rewardContract);\r\n            }\r\n            //add token to list of known rewards\r\n            tokenList.push(_token);\r\n        }\r\n    }\r\n\r\n    //pull assigned tokens from staker to stash\r\n    function stashRewards() external pure returns(bool){\r\n\r\n        //after depositing/withdrawing, extra incentive tokens are claimed\r\n        //but from v3 this is default to off, and this stash is the reward receiver too.\r\n\r\n        return true;\r\n    }\r\n\r\n    //send all extra rewards to their reward contracts\r\n    function processStash() external returns(bool){\r\n        require(msg.sender == operator, \"!operator\");\r\n\r\n        uint256 tCount = tokenList.length;\r\n        for(uint i=0; i < tCount; i++){\r\n            TokenInfo storage t = tokenInfo[tokenList[i]];\r\n            address token = t.token;\r\n            if(token == address(0)) continue;\r\n\r\n            if(token == crv){\r\n                //if crv, send back to booster to distribute\r\n                IERC20(token).safeTransfer(operator, IERC20(token).balanceOf(address(this)));\r\n                continue;\r\n            }\r\n            \r\n            address wrapper = t.wrapperAddress;\r\n            if(IStashTokenWrapper(wrapper).isInvalid()) continue;\r\n\r\n            uint256 amount = IERC20(token).balanceOf(address(this));\r\n\r\n            if (amount > 0 && amount < 1e30) {\r\n                historicalRewards[token] = historicalRewards[token].add(amount);\r\n            \t//add to wrapper, which is allocated to reward contract\r\n            \taddress rewards = t.rewardAddress;\r\n            \tif(rewards == address(0)) continue;\r\n            \tIERC20(token).safeTransfer(wrapper, amount);\r\n            \tIRewards(rewards).queueNewRewards(amount);\r\n            }\r\n        }\r\n        return true;\r\n    }\r\n\r\n}"
      },
      "/contracts/interfaces/IStashTokenWrapper.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.6.12;\r\n\r\ninterface IStashTokenWrapper {\r\n    function init(address _token, address _rewardpool) external;\r\n    function isInvalid() external returns(bool);\r\n    function setInvalid(bool _isInvalid) external;\r\n}"
      },
      "/contracts/interfaces/IRewardHook.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\n\r\npragma solidity 0.6.12;\r\n\r\ninterface IRewardHook {\r\n    function onRewardClaim() external;\r\n}"
      },
      "/contracts/interfaces/IProxyFactory.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.6.12;\r\n\r\ninterface IProxyFactory {\r\n    function clone(address _target) external returns(address);\r\n}"
      },
      "/contracts/Interfaces.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.6.12;\r\n\r\n\r\n\r\ninterface ICurveGauge {\r\n    function deposit(uint256) external;\r\n    function balanceOf(address) external view returns (uint256);\r\n    function withdraw(uint256) external;\r\n    function claim_rewards() external;\r\n    function reward_tokens(uint256) external view returns(address);//v2\r\n    function rewarded_token() external view returns(address);//v1\r\n    function lp_token() external view returns(address);\r\n    function is_killed() external view returns(bool);\r\n}\r\n\r\ninterface ICurveVoteEscrow {\r\n    function create_lock(uint256, uint256) external;\r\n    function increase_amount(uint256) external;\r\n    function increase_unlock_time(uint256) external;\r\n    function withdraw() external;\r\n    function smart_wallet_checker() external view returns (address);\r\n}\r\n\r\ninterface IWalletChecker {\r\n    function check(address) external view returns (bool);\r\n}\r\n\r\ninterface IVoting{\r\n    function vote(uint256, bool, bool) external; //voteId, support, executeIfDecided\r\n    function getVote(uint256) external view returns(bool,bool,uint64,uint64,uint64,uint64,uint256,uint256,uint256,bytes memory); \r\n    function vote_for_gauge_weights(address,uint256) external;\r\n}\r\n\r\ninterface IMinter{\r\n    function mint(address) external;\r\n}\r\n\r\ninterface IRegistry{\r\n    function get_registry() external view returns(address);\r\n    function get_address(uint256 _id) external view returns(address);\r\n    function gauge_controller() external view returns(address);\r\n    function get_lp_token(address) external view returns(address);\r\n    function get_gauges(address) external view returns(address[10] memory,uint128[10] memory);\r\n}\r\n\r\ninterface IStaker{\r\n    function deposit(address, address) external;\r\n    function withdraw(address) external;\r\n    function withdraw(address, address, uint256) external;\r\n    function withdrawAll(address, address) external;\r\n    function createLock(uint256, uint256) external;\r\n    function increaseAmount(uint256) external;\r\n    function increaseTime(uint256) external;\r\n    function release() external;\r\n    function claimCrv(address) external returns (uint256);\r\n    function claimRewards(address) external;\r\n    function claimFees(address,address) external;\r\n    function setStashAccess(address, bool) external;\r\n    function vote(uint256,address,bool) external;\r\n    function voteGaugeWeight(address,uint256) external;\r\n    function balanceOfPool(address) external view returns (uint256);\r\n    function operator() external view returns (address);\r\n    function execute(address _to, uint256 _value, bytes calldata _data) external returns (bool, bytes memory);\r\n}\r\n\r\ninterface IRewards{\r\n    function stake(address, uint256) external;\r\n    function stakeFor(address, uint256) external;\r\n    function withdraw(address, uint256) external;\r\n    function exit(address) external;\r\n    function getReward(address) external;\r\n    function queueNewRewards(uint256) external;\r\n    function notifyRewardAmount(uint256) external;\r\n    function addExtraReward(address) external;\r\n    function stakingToken() external view returns (address);\r\n    function rewardToken() external view returns(address);\r\n    function earned(address account) external view returns (uint256);\r\n}\r\n\r\ninterface IStash{\r\n    function stashRewards() external returns (bool);\r\n    function processStash() external returns (bool);\r\n    function claimRewards() external returns (bool);\r\n    function initialize(uint256 _pid, address _operator, address _staker, address _gauge, address _rewardFactory) external;\r\n    function setExtraReward(address _token) external;\r\n    function setRewardHook(address _hook) external;\r\n    function tokenCount() external view returns (uint256);\r\n}\r\n\r\ninterface IFeeDistro{\r\n    function claim() external;\r\n    function token() external view returns(address);\r\n}\r\n\r\ninterface ITokenMinter{\r\n    function mint(address,uint256) external;\r\n    function burn(address,uint256) external;\r\n}\r\n\r\ninterface IDeposit{\r\n    function isShutdown() external view returns(bool);\r\n    function balanceOf(address _account) external view returns(uint256);\r\n    function totalSupply() external view returns(uint256);\r\n    function poolInfo(uint256) external view returns(address,address,address,address,address, bool);\r\n    function rewardClaimed(uint256,address,uint256) external;\r\n    function withdrawTo(uint256,uint256,address) external;\r\n    function claimRewards(uint256,address) external returns(bool);\r\n    function rewardArbitrator() external returns(address);\r\n    function setGaugeRedirect(uint256 _pid) external returns(bool);\r\n    function owner() external returns(address);\r\n}\r\n\r\ninterface ICrvDeposit{\r\n    function deposit(uint256, bool) external;\r\n    function lockIncentive() external view returns(uint256);\r\n}\r\n\r\ninterface IRewardFactory{\r\n    function setAccess(address,bool) external;\r\n    function CreateCrvRewards(uint256,address) external returns(address);\r\n    function CreateTokenRewards(address,address,address) external returns(address);\r\n    function activeRewardCount(address) external view returns(uint256);\r\n    function addActiveReward(address,uint256) external returns(bool);\r\n    function removeActiveReward(address,uint256) external returns(bool);\r\n}\r\n\r\ninterface IStashFactory{\r\n    function CreateStash(uint256,address,address,uint256) external returns(address);\r\n    function setImplementation(address _v1, address _v2, address _v3) external;\r\n}\r\n\r\ninterface ITokenFactory{\r\n    function CreateDepositToken(address) external returns(address);\r\n}\r\n\r\ninterface IPools{\r\n    function addPool(address _lptoken, address _gauge, uint256 _stashVersion) external returns(bool);\r\n    function forceAddPool(address _lptoken, address _gauge, uint256 _stashVersion) external returns(bool);\r\n    function shutdownPool(uint256 _pid) external returns(bool);\r\n    function poolInfo(uint256) external view returns(address,address,address,address,address,bool);\r\n    function poolLength() external view returns (uint256);\r\n    function gaugeMap(address) external view returns(bool);\r\n    function setPoolManager(address _poolM) external;\r\n}\r\n\r\ninterface IVestedEscrow{\r\n    function fund(address[] calldata _recipient, uint256[] calldata _amount) external returns(bool);\r\n}\r\n\r\n\r\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize, which returns 0 for contracts in\n        // construction, since the code is only stored at the end of the\n        // constructor execution.\n\n        uint256 size;\n        // solhint-disable-next-line no-inline-assembly\n        assembly { size := extcodesize(account) }\n        return size > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n        (bool success, ) = recipient.call{ value: amount }(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain`call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n      return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\n        return _verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return _verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return _verifyCallResult(success, returndata, errorMessage);\n    }\n\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                // solhint-disable-next-line no-inline-assembly\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using SafeMath for uint256;\n    using Address for address;\n\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        // solhint-disable-next-line max-line-length\n        require((value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 newAllowance = token.allowance(address(this), spender).add(value);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) { // Return data is optional\n            // solhint-disable-next-line max-line-length\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
      },
      "@openzeppelin/contracts/math/SafeMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        uint256 c = a + b;\n        if (c < a) return (false, 0);\n        return (true, c);\n    }\n\n    /**\n     * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        if (b > a) return (false, 0);\n        return (true, a - b);\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\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) return (true, 0);\n        uint256 c = a * b;\n        if (c / a != b) return (false, 0);\n        return (true, c);\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        if (b == 0) return (false, 0);\n        return (true, a / b);\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        if (b == 0) return (false, 0);\n        return (true, a % b);\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     *\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        uint256 c = a + b;\n        require(c >= a, \"SafeMath: addition overflow\");\n        return c;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b <= a, \"SafeMath: subtraction overflow\");\n        return a - b;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     *\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (a == 0) return 0;\n        uint256 c = a * b;\n        require(c / a == b, \"SafeMath: multiplication overflow\");\n        return c;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting 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(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b > 0, \"SafeMath: division by zero\");\n        return a / b;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        require(b > 0, \"SafeMath: modulo by zero\");\n        return a % b;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n     * overflow (when the result is negative).\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {trySub}.\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b <= a, errorMessage);\n        return a - b;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n     * division by zero. The result is rounded towards zero.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryDiv}.\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(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b > 0, errorMessage);\n        return a / b;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting with custom message when dividing by zero.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryMod}.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b > 0, errorMessage);\n        return a % b;\n    }\n}\n"
      }
    },
    "settings": {
      "remappings": [],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "evmVersion": "istanbul",
      "libraries": {},
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      }
    }
  }}