creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/FarmBooster.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin-4.5.0/contracts/access/Ownable.sol\";\nimport \"@openzeppelin-4.5.0/contracts/token/ERC20/IERC20.sol\";\nimport \"./libraries/IterateMapping.sol\";\nimport \"./interfaces/IVECake.sol\";\nimport \"./interfaces/IWrapper.sol\";\n\ncontract FarmBooster is Ownable {\n    using IterableMapping for ItMap;\n\n    /// @notice Each wrapper will have one smart contract, so we define one wrapper as one pool.\n    struct PoolInfo {\n        uint256 poolId; // Pool id , start from 1\n        address wrapper; // Wrapper smart contract address\n        address stakedToken; // staked token address in wrapper\n        address rewardToken; // reward token address in wrapper\n    }\n\n    /// @notice Pool length\n    uint256 public poolLength;\n\n    /// @notice Wrapper smart contract pool id\n    /// @notice wrapperPoolIds[Wrapper address] => pool id\n    mapping(address => uint256) public wrapperPoolIds;\n\n    /// @notice pools[pool id] => PoolInfo\n    mapping(uint256 => PoolInfo) public pools;\n\n    /// @notice VECake.\n    address public immutable VECake;\n    /// @notice VECake caller, this smart contract will trigger depositFor and unlock.\n    address public VECakeCaller;\n\n    /// @notice limit max boost\n    uint256 public cA;\n    /// @notice include 1e4\n    uint256 public constant MIN_CA = 1e4;\n    /// @notice include 1e5\n    uint256 public constant MAX_CA = 1e5;\n    /// @notice cA precision\n    uint256 public constant CA_PRECISION = 1e5;\n    /// @notice controls difficulties\n    uint256 public cB;\n    /// @notice not include 0\n    uint256 public constant MIN_CB = 0;\n    /// @notice include 50\n    uint256 public constant MAX_CB = 1e8;\n    /// @notice cB precision\n    uint256 public constant CB_PRECISION = 1e4;\n    /// @notice MCV3 basic boost factor, none boosted user\"s boost factor\n    uint256 public constant BOOST_PRECISION = 100 * 1e10;\n    /// @notice MCV3 Hard limit for maximum boost factor\n    uint256 public constant MAX_BOOST_PRECISION = 300 * 1e10;\n\n    /// @notice Override global cB for special pool pid.\n    mapping(uint256 => uint256) public cBOverride;\n\n    /// @notice The whitelist of pools allowed for farm boosting.\n    mapping(uint256 => bool) public whiteList;\n\n    /// @notice Record whether the farm booster has been turned on, in order to save gas.\n    mapping(uint256 => bool) public everBoosted;\n\n    /// @notice Info of each pool user.\n    mapping(address => ItMap) public userInfo;\n\n    event UpdateCA(uint256 oldCA, uint256 newCA);\n    event UpdateCB(uint256 oldCB, uint256 newCB);\n    event UpdateCBOverride(uint256 indexed pid, uint256 oldCB, uint256 newCB);\n    event UpdateBoostFarms(uint256 indexed pid, address wrapper, bool status);\n    event NewPool(uint256 indexed pid, address indexed wrapper, address indexed stakedToken, address rewardToken);\n    event UpdatePoolBoostMultiplier(\n        address indexed user,\n        uint256 indexed pid,\n        address indexed wrapper,\n        uint256 oldMultiplier,\n        uint256 newMultiplier\n    );\n    event UpdateVECakeCaller(address VECakeCaller);\n\n    /// @param _VECake VECake contract address.\n    /// @param _cA Limit max boost.\n    /// @param _cB Controls difficulties.\n    constructor(\n        address _VECake,\n        uint256 _cA,\n        uint256 _cB\n    ) {\n        require(_cA >= MIN_CA && _cA <= MAX_CA && _cB > MIN_CB && _cB <= MAX_CB, \"Invalid parameter\");\n        VECake = _VECake;\n        cA = _cA;\n        cB = _cB;\n    }\n\n    /// @notice Checks if the msg.sender is the vecake caller.\n    modifier onlyVECakeCaller() {\n        require(msg.sender == VECakeCaller, \"Not vecake caller\");\n        _;\n    }\n\n    /// @notice set VECake caller.\n    /// @param _VECakeCaller VECake caller.\n    function setVECakeCaller(address _VECakeCaller) external onlyOwner {\n        VECakeCaller = _VECakeCaller;\n        emit UpdateVECakeCaller(_VECakeCaller);\n    }\n\n    struct BoosterWrapperConfig {\n        address wrapper;\n        bool status;\n    }\n\n    /// @notice Only allow whitelisted wrapper for farm boosting.\n    /// @param _boosterWrappers Booster wrappers config\n    function setBoosterFarms(BoosterWrapperConfig[] calldata _boosterWrappers) external onlyOwner {\n        for (uint256 i = 0; i < _boosterWrappers.length; i++) {\n            BoosterWrapperConfig memory wrapperInfo = _boosterWrappers[i];\n\n            uint256 poolId = wrapperPoolIds[wrapperInfo.wrapper];\n            // if pool id is 0 , we need to add pool\n            if (poolId == 0) {\n                // Pool id start from 1\n                poolLength++;\n\n                wrapperPoolIds[wrapperInfo.wrapper] = poolLength;\n                PoolInfo storage pool = pools[poolLength];\n                pool.poolId = poolLength;\n                pool.wrapper = wrapperInfo.wrapper;\n                // If wrapper smart contract do not have stakedToken and rewardToken , will revert.\n                // Use this to check if it is a valid wrapper address\n                pool.stakedToken = IWrapper(wrapperInfo.wrapper).stakedToken();\n                pool.rewardToken = IWrapper(wrapperInfo.wrapper).rewardToken();\n\n                poolId = poolLength;\n                emit NewPool(poolId, pool.wrapper, pool.stakedToken, pool.rewardToken);\n            }\n            if (wrapperInfo.status && !everBoosted[poolId]) everBoosted[poolId] = true;\n            whiteList[poolId] = wrapperInfo.status;\n            emit UpdateBoostFarms(poolId, wrapperInfo.wrapper, wrapperInfo.status);\n        }\n    }\n\n    /// @notice Limit max boost.\n    /// @param _cA Max boost.\n    function setCA(uint256 _cA) external onlyOwner {\n        require(_cA >= MIN_CA && _cA <= MAX_CA, \"Invalid cA\");\n        uint256 temp = cA;\n        cA = _cA;\n        emit UpdateCA(temp, cA);\n    }\n\n    /// @notice Controls difficulties.\n    /// @param _cB Difficulties.\n    function setCB(uint256 _cB) external onlyOwner {\n        require(_cB > MIN_CB && _cB <= MAX_CB, \"Invalid cB\");\n        uint256 temp = cB;\n        cB = _cB;\n        emit UpdateCB(temp, cB);\n    }\n\n    /// @notice Set cBOverride.\n    /// @param _poolId Pool pid.\n    /// @param _cB Difficulties.\n    function setCBOverride(uint256 _poolId, uint256 _cB) external onlyOwner {\n        // Can set cBOverride[pid] 0 when need to remove override value.\n        require((_cB > MIN_CB && _cB <= MAX_CB) || _cB == 0, \"Invalid cB\");\n        uint256 temp = cB;\n        cBOverride[_poolId] = _cB;\n        emit UpdateCBOverride(_poolId, temp, cB);\n    }\n\n    /// @notice Update user boost multiplier\n    /// @dev Only whitelist wrapper can call this function, if not , will return BOOST_PRECISION\n    /// @param _user User address\n    function updatePositionBoostMultiplier(address _user) external returns (uint256 _multiplier) {\n        address wrapper = msg.sender;\n        uint256 poolId = wrapperPoolIds[wrapper];\n        // will return BOOST_PRECISION when pool does not exist\n        if (poolId == 0) {\n            return BOOST_PRECISION;\n        }\n\n        // Set the default multiplier\n        _multiplier = BOOST_PRECISION;\n        // In order to save gas, do not need to check the pools that have never been boosted.\n        if (everBoosted[poolId]) {\n            ItMap storage itmap = userInfo[_user];\n            uint256 prevMultiplier = itmap.data[poolId];\n\n            // if userStakedAmount is zero, it means the user withdraw all token from wrapper smart contract , we will remove the pool id\n            (uint256 userStakedAmount, , , , ) = IWrapper(wrapper).userInfo(_user);\n            if (!whiteList[poolId] || userStakedAmount == 0) {\n                if (itmap.contains(poolId)) {\n                    itmap.remove(poolId);\n                }\n            } else {\n                _multiplier = _boostCalculate(_user, poolId);\n                itmap.insert(poolId, _multiplier);\n            }\n            emit UpdatePoolBoostMultiplier(_user, poolId, wrapper, prevMultiplier, _multiplier);\n        }\n    }\n\n    /// @notice VECake operation(deposit/withdraw) automatically call this function.\n    /// @param _for User address.\n    /// @param _amount The amount to deposit\n    /// @param _unlockTime New time to unlock Cake. Pass 0 if no change.\n    /// @param _prevLockedAmount Existed locks[_for].amount\n    /// @param _prevLockedEnd Existed locks[_for].end\n    /// @param _actionType The action that user did as this internal function shared among\n    /// @param _isCakePoolUser This user is cake pool user or not\n    function depositFor(\n        address _for,\n        uint256 _amount,\n        uint256 _unlockTime,\n        int128 _prevLockedAmount,\n        uint256 _prevLockedEnd,\n        uint256 _actionType,\n        bool _isCakePoolUser\n    ) external onlyVECakeCaller {\n        _updateUserAllBoostMultiplier(_for);\n    }\n\n    /// @notice Function to perform withdraw and unlock Cake for a user\n    /// @param _user The address to be unlocked\n    /// @param _prevLockedAmount Existed locks[_user].amount\n    /// @param _prevLockedEnd Existed locks[_user].end\n    /// @param _withdrawAmount Cake amount\n    function unlock(\n        address _user,\n        int128 _prevLockedAmount,\n        uint256 _prevLockedEnd,\n        uint256 _withdrawAmount\n    ) external onlyVECakeCaller {\n        _updateUserAllBoostMultiplier(_user);\n    }\n\n    function _updateUserAllBoostMultiplier(address _user) internal {\n        ItMap storage itmap = userInfo[_user];\n        uint256 length = itmap.keys.length;\n        if (length > 0) {\n            for (uint256 i = 0; i < length; i++) {\n                uint256 poolId = itmap.keys[i];\n                _updateBoostMultiplier(itmap, _user, poolId);\n            }\n        }\n    }\n\n    /// @param _user user address.\n    /// @param _poolId pool id.\n    function _updateBoostMultiplier(\n        ItMap storage itmap,\n        address _user,\n        uint256 _poolId\n    ) internal {\n        PoolInfo memory pool = pools[_poolId];\n        // Used to be boosted farm pool and current is not, remove from mapping\n        if (!whiteList[_poolId]) {\n            if (itmap.data[_poolId] > BOOST_PRECISION) {\n                // reset to BOOST_PRECISION\n                IWrapper(pool.wrapper).updateBoostMultiplier(_user, BOOST_PRECISION);\n            }\n            itmap.remove(_poolId);\n            return;\n        }\n\n        (, , uint256 prevMultiplier, , ) = IWrapper(pool.wrapper).userInfo(_user);\n        uint256 multiplier = _boostCalculate(_user, _poolId);\n\n        if (multiplier < BOOST_PRECISION) {\n            multiplier = BOOST_PRECISION;\n        } else if (multiplier > MAX_BOOST_PRECISION) {\n            multiplier = MAX_BOOST_PRECISION;\n        }\n\n        // Update multiplier in pool wrapper\n        if (multiplier != prevMultiplier) {\n            IWrapper(pool.wrapper).updateBoostMultiplier(_user, multiplier);\n        }\n        itmap.insert(_poolId, multiplier);\n\n        emit UpdatePoolBoostMultiplier(_user, _poolId, pool.wrapper, prevMultiplier, multiplier);\n    }\n\n    /// @notice Whether position boosted specific farm pool.\n    /// @param _user user address.\n    /// @param _poolId pool id.\n    function isBoostedPool(address _user, uint256 _poolId) external view returns (bool) {\n        return userInfo[_user].contains(_poolId);\n    }\n\n    /// @notice Whether position boosted specific wrapper smart contract.\n    /// @param _user user address.\n    /// @param _wrapper wrapper address.\n    function isBoostedWrapper(address _user, address _wrapper) external view returns (bool) {\n        return userInfo[_user].contains(wrapperPoolIds[_wrapper]);\n    }\n\n    /// @notice Whether the wrapper is in whiteList.\n    /// @param _wrapper wrapper address.\n    function whiteListWrapper(address _wrapper) external view returns (bool) {\n        return whiteList[wrapperPoolIds[_wrapper]];\n    }\n\n    /// @notice Get PoolInfo by wrapper address.\n    /// @param _wrapper wrapper address.\n    function wrapperPools(address _wrapper) external view returns (PoolInfo memory) {\n        return pools[wrapperPoolIds[_wrapper]];\n    }\n\n    /// @notice Actived pool list.\n    /// @param _user user address.\n    function activedPools(address _user)\n        external\n        view\n        returns (uint256[] memory poolList, address[] memory wrapperList)\n    {\n        ItMap storage itmap = userInfo[_user];\n        uint256 len = itmap.keys.length;\n        if (len == 0) return (poolList, wrapperList);\n\n        poolList = new uint256[](len);\n        wrapperList = new address[](len);\n        // solidity for-loop not support multiple variables initialized by \",\" separate.\n        for (uint256 index = 0; index < len; index++) {\n            uint256 poolId = itmap.keys[index];\n            poolList[index] = poolId;\n            wrapperList[index] = pools[poolId].wrapper;\n        }\n    }\n\n    /// @notice Anyone can call this function, if you find some guys effected multiplier is not fair\n    /// for other users, just call \"updateBoostMultiplierByUser\" function in wrapper.\n    /// @param _user user address.\n    /// @param _poolId pool id.\n    /// @dev If return value not in range [BOOST_PRECISION, MAX_BOOST_PRECISION]\n    /// the actual effected multiplier will be the close to side boundry value.\n    function getUserMultiplier(address _user, uint256 _poolId) external view returns (uint256) {\n        if (!whiteList[_poolId] || _poolId == 0) {\n            return BOOST_PRECISION;\n        } else {\n            return _boostCalculate(_user, _poolId);\n        }\n    }\n\n    /// @notice Anyone can call this function, if you find some guys effected multiplier is not fair\n    /// for other users, just call \"updateBoostMultiplierByUser\" function in wrapper.\n    /// @param _user user address.\n    /// @param _wrapper wrapper address.\n    /// @dev If return value not in range [BOOST_PRECISION, MAX_BOOST_PRECISION]\n    /// the actual effected multiplier will be the close to side boundry value.\n    function getUserMultiplierByWrapper(address _user, address _wrapper) external view returns (uint256) {\n        uint256 poolId = wrapperPoolIds[_wrapper];\n        if (!whiteList[poolId] || poolId == 0) {\n            return BOOST_PRECISION;\n        } else {\n            return _boostCalculate(_user, poolId);\n        }\n    }\n\n    /// @param _user user address.\n    /// @param _poolId pool id.\n    function _boostCalculate(address _user, uint256 _poolId) internal view returns (uint256) {\n        PoolInfo memory pool = pools[_poolId];\n        (uint256 userStakedAmount, , , , ) = IWrapper(pool.wrapper).userInfo(_user);\n\n        uint256 dB = (cA * userStakedAmount) / CA_PRECISION;\n        // dB == 0 means _liquidity close to 0\n        if (dB == 0) return BOOST_PRECISION;\n\n        uint256 totalLiquidity = IERC20(pool.stakedToken).balanceOf(pool.wrapper);\n\n        // will use cBOverride[pid] If cBOverride[pid] is greater than 0 , or will use global cB.\n        uint256 realCB = cBOverride[_poolId] > 0 ? cBOverride[_poolId] : cB;\n        uint256 totalSupplyInVECake = IVECake(VECake).totalSupply();\n        if (totalSupplyInVECake == 0) return BOOST_PRECISION;\n        uint256 aB = (totalLiquidity * IVECake(VECake).balanceOf(_user) * realCB) / totalSupplyInVECake / CB_PRECISION;\n        return ((userStakedAmount <= (dB + aB) ? userStakedAmount : (dB + aB)) * BOOST_PRECISION) / dB;\n    }\n}\n"
      },
      "@openzeppelin-4.5.0/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n        _;\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "@openzeppelin-4.5.0/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^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 `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, 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 `from` to `to` 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(\n        address from,\n        address to,\n        uint256 amount\n    ) 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"
      },
      "contracts/libraries/IterateMapping.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nstruct ItMap {\n    // pid => boost\n    mapping(uint256 => uint256) data;\n    // pid => index\n    mapping(uint256 => uint256) indexs;\n    // array of pid\n    uint256[] keys;\n    // never use it, just for keep compile success.\n    uint256 size;\n}\n\nlibrary IterableMapping {\n    function insert(\n        ItMap storage self,\n        uint256 key,\n        uint256 value\n    ) internal {\n        uint256 keyIndex = self.indexs[key];\n        self.data[key] = value;\n        if (keyIndex > 0) return;\n        else {\n            self.indexs[key] = self.keys.length + 1;\n            self.keys.push(key);\n            return;\n        }\n    }\n\n    function remove(ItMap storage self, uint256 key) internal {\n        uint256 index = self.indexs[key];\n        if (index == 0) return;\n        uint256 lastKey = self.keys[self.keys.length - 1];\n        if (key != lastKey) {\n            self.keys[index - 1] = lastKey;\n            self.indexs[lastKey] = index;\n        }\n        delete self.data[key];\n        delete self.indexs[key];\n        self.keys.pop();\n    }\n\n    function contains(ItMap storage self, uint256 key) internal view returns (bool) {\n        return self.indexs[key] > 0;\n    }\n}\n"
      },
      "contracts/interfaces/IVECake.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\ninterface IVECake {\n    function userInfo(address user)\n        external\n        view\n        returns (\n            address cakePoolProxy, // Proxy Smart Contract for users who had locked in cake pool.\n            uint128 cakeAmount, //  Cake amount locked in cake pool.\n            uint48 lockEndTime, // Record the lockEndTime in cake pool.\n            uint48 migrationTime, // Record the migration time.\n            uint16 cakePoolType, // 1: Migration, 2: Delegation.\n            uint16 withdrawFlag // 0: Not withdraw, 1 : withdrew.\n        );\n\n    function isCakePoolProxy(address _user) external view returns (bool);\n\n    /// @dev Return the max epoch of the given \"_user\"\n    function userPointEpoch(address _user) external view returns (uint256);\n\n    /// @dev Return the max global epoch\n    function epoch() external view returns (uint256);\n\n    /// @dev Trigger global check point\n    function checkpoint() external;\n\n    /// @notice Return the proxy balance of VECake at a given \"_blockNumber\"\n    /// @param _user The proxy owner address to get a balance of VECake\n    /// @param _blockNumber The speicific block number that you want to check the balance of VECake\n    function balanceOfAtForProxy(address _user, uint256 _blockNumber) external view returns (uint256);\n\n    /// @notice Return the balance of VECake at a given \"_blockNumber\"\n    /// @param _user The address to get a balance of VECake\n    /// @param _blockNumber The speicific block number that you want to check the balance of VECake\n    function balanceOfAt(address _user, uint256 _blockNumber) external view returns (uint256);\n\n    /// @notice Return the voting weight of a givne user's proxy\n    /// @param _user The address of a user\n    function balanceOfForProxy(address _user) external view returns (uint256);\n\n    /// @notice Return the voting weight of a givne user\n    /// @param _user The address of a user\n    function balanceOf(address _user) external view returns (uint256);\n\n    /// @notice Calculate total supply of VECake (voting power)\n    function totalSupply() external view returns (uint256);\n}\n"
      },
      "contracts/interfaces/IWrapper.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ninterface IWrapper {\n    function stakedToken() external view returns (address);\n\n    function rewardToken() external view returns (address);\n\n    /*\n    struct UserInfo {\n        uint256 amount; // How many staked tokens the user has provided\n        uint256 rewardDebt;\n        uint256 boostMultiplier; // currently active multiplier\n        uint256 boostedAmount; // combined boosted amount\n        uint256 unsettledRewards; // rewards haven't been transferred to users but already accounted in rewardDebt\n    }\n    */\n\n    function userInfo(address user)\n        external\n        view\n        returns (\n            uint256,\n            uint256,\n            uint256,\n            uint256,\n            uint256\n        );\n\n    /// @notice Update user boost factor from boost contract.\n    /// @param _userAddress The user address for boost factor updates.\n    /// @param _newMultiplier The multiplier update to user.\n    function updateBoostMultiplier(address _userAddress, uint256 _newMultiplier) external;\n}\n"
      },
      "@openzeppelin-4.5.0/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 99999
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}