creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/cauldrons/PrivilegedCauldronV4.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >=0.8.0;\n\nimport {IERC20} from \"BoringSolidity/interfaces/IERC20.sol\";\nimport {IBentoBoxV1} from \"interfaces/IBentoBoxV1.sol\";\nimport {CauldronV4} from \"cauldrons/CauldronV4.sol\";\nimport {RebaseLibrary, Rebase} from \"BoringSolidity/libraries/BoringRebase.sol\";\n\ncontract PrivilegedCauldronV4 is CauldronV4 {\n    using RebaseLibrary for Rebase;\n\n    constructor(IBentoBoxV1 bentoBox_, IERC20 magicInternetMoney_) CauldronV4(bentoBox_, magicInternetMoney_) {}\n\n    /// @dev masterContract Owner should call updateExchangeRate() before single or multiple call to this function\n    function addBorrowPosition(address to, uint256 amount) external onlyMasterContractOwner returns (uint256 part) {\n        (totalBorrow, part) = totalBorrow.add(amount, true);\n\n        userBorrowPart[to] = userBorrowPart[to] + part;\n\n        emit LogBorrow(msg.sender, to, amount, part);\n\n        require(_isSolvent(to, exchangeRate), \"Cauldron: user insolvent\");\n    }\n}\n"
      },
      "lib/BoringSolidity/contracts/interfaces/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IERC20 {\n    // transfer and tranferFrom have been removed, because they don't work on all tokens (some aren't ERC20 complaint).\n    // By removing them you can't accidentally use them.\n    // name, symbol and decimals have been removed, because they are optional and sometimes wrongly implemented (MKR).\n    // Use BoringERC20 with `using BoringERC20 for IERC20` and call `safeTransfer`, `safeTransferFrom`, etc instead.\n    function totalSupply() external view returns (uint256);\n\n    function balanceOf(address account) external view returns (uint256);\n\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    event Transfer(address indexed from, address indexed to, uint256 value);\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /// @notice EIP 2612\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n}\n\ninterface IStrictERC20 {\n    // This is the strict ERC20 interface. Don't use this, certainly not if you don't control the ERC20 token you're calling.\n    function name() external view returns (string memory);\n    function symbol() external view returns (string memory);\n    function decimals() external view returns (uint8);\n    function totalSupply() external view returns (uint256);\n    function balanceOf(address _owner) external view returns (uint256 balance);\n    function transfer(address _to, uint256 _value) external returns (bool success);\n    function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);\n    function approve(address _spender, uint256 _value) external returns (bool success);\n    function allowance(address _owner, address _spender) external view returns (uint256 remaining);\n\n    event Transfer(address indexed from, address indexed to, uint256 value);\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /// @notice EIP 2612\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n}\n"
      },
      "src/interfaces/IBentoBoxV1.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\nimport {IERC20} from \"BoringSolidity/interfaces/IERC20.sol\";\nimport {Rebase} from \"BoringSolidity/libraries/BoringRebase.sol\";\nimport {IStrategy} from \"interfaces/IStrategy.sol\";\n\ninterface IFlashBorrower {\n    /// @notice The flashloan callback. `amount` + `fee` needs to repayed to msg.sender before this call returns.\n    /// @param sender The address of the invoker of this flashloan.\n    /// @param token The address of the token that is loaned.\n    /// @param amount of the `token` that is loaned.\n    /// @param fee The fee that needs to be paid on top for this loan. Needs to be the same as `token`.\n    /// @param data Additional data that was passed to the flashloan function.\n    function onFlashLoan(\n        address sender,\n        IERC20 token,\n        uint256 amount,\n        uint256 fee,\n        bytes calldata data\n    ) external;\n}\n\ninterface IBatchFlashBorrower {\n    /// @notice The callback for batched flashloans. Every amount + fee needs to repayed to msg.sender before this call returns.\n    /// @param sender The address of the invoker of this flashloan.\n    /// @param tokens Array of addresses for ERC-20 tokens that is loaned.\n    /// @param amounts A one-to-one map to `tokens` that is loaned.\n    /// @param fees A one-to-one map to `tokens` that needs to be paid on top for each loan. Needs to be the same token.\n    /// @param data Additional data that was passed to the flashloan function.\n    function onBatchFlashLoan(\n        address sender,\n        IERC20[] calldata tokens,\n        uint256[] calldata amounts,\n        uint256[] calldata fees,\n        bytes calldata data\n    ) external;\n}\n\ninterface IBentoBoxV1 {\n    function balanceOf(IERC20, address) external view returns (uint256);\n\n    function batch(bytes[] calldata calls, bool revertOnFail) external payable returns (bool[] memory successes, bytes[] memory results);\n\n    function batchFlashLoan(\n        IBatchFlashBorrower borrower,\n        address[] calldata receivers,\n        IERC20[] calldata tokens,\n        uint256[] calldata amounts,\n        bytes calldata data\n    ) external;\n\n    function claimOwnership() external;\n\n    function flashLoan(\n        IFlashBorrower borrower,\n        address receiver,\n        IERC20 token,\n        uint256 amount,\n        bytes calldata data\n    ) external;\n\n    function deploy(\n        address masterContract,\n        bytes calldata data,\n        bool useCreate2\n    ) external payable returns (address);\n\n    function deposit(\n        IERC20 token_,\n        address from,\n        address to,\n        uint256 amount,\n        uint256 share\n    ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n    function harvest(\n        IERC20 token,\n        bool balance,\n        uint256 maxChangeAmount\n    ) external;\n\n    function masterContractApproved(address, address) external view returns (bool);\n\n    function masterContractOf(address) external view returns (address);\n\n    function nonces(address) external view returns (uint256);\n\n    function owner() external view returns (address);\n\n    function pendingOwner() external view returns (address);\n\n    function pendingStrategy(IERC20) external view returns (IStrategy);\n\n    function permitToken(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 amount,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    function registerProtocol() external;\n\n    function setMasterContractApproval(\n        address user,\n        address masterContract,\n        bool approved,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    function setStrategy(IERC20 token, IStrategy newStrategy) external;\n\n    function setStrategyTargetPercentage(IERC20 token, uint64 targetPercentage_) external;\n\n    function strategy(IERC20) external view returns (IStrategy);\n\n    function strategyData(IERC20)\n        external\n        view\n        returns (\n            uint64 strategyStartDate,\n            uint64 targetPercentage,\n            uint128 balance\n        );\n\n    function toAmount(\n        IERC20 token,\n        uint256 share,\n        bool roundUp\n    ) external view returns (uint256 amount);\n\n    function toShare(\n        IERC20 token,\n        uint256 amount,\n        bool roundUp\n    ) external view returns (uint256 share);\n\n    function totals(IERC20) external view returns (Rebase memory totals_);\n\n    function transfer(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 share\n    ) external;\n\n    function transferMultiple(\n        IERC20 token,\n        address from,\n        address[] calldata tos,\n        uint256[] calldata shares\n    ) external;\n\n    function transferOwnership(\n        address newOwner,\n        bool direct,\n        bool renounce\n    ) external;\n\n    function whitelistMasterContract(address masterContract, bool approved) external;\n\n    function whitelistedMasterContracts(address) external view returns (bool);\n\n    function withdraw(\n        IERC20 token_,\n        address from,\n        address to,\n        uint256 amount,\n        uint256 share\n    ) external returns (uint256 amountOut, uint256 shareOut);\n}\n"
      },
      "src/cauldrons/CauldronV4.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\n// Cauldron\n\n//    (                (   (\n//    )\\      )    (   )\\  )\\ )  (\n//  (((_)  ( /(   ))\\ ((_)(()/(  )(    (    (\n//  )\\___  )(_)) /((_) _   ((_))(()\\   )\\   )\\ )\n// ((/ __|((_)_ (_))( | |  _| |  ((_) ((_) _(_/(\n//  | (__ / _` || || || |/ _` | | '_|/ _ \\| ' \\))\n//   \\___|\\__,_| \\_,_||_|\\__,_| |_|  \\___/|_||_|\n\npragma solidity >=0.8.0;\nimport {Owned} from \"solmate/auth/Owned.sol\";\nimport {IERC20} from \"BoringSolidity/interfaces/IERC20.sol\";\nimport {IOracle} from \"interfaces/IOracle.sol\";\nimport {ISwapperV2} from \"interfaces/ISwapperV2.sol\";\nimport {IBentoBoxV1} from \"interfaces/IBentoBoxV1.sol\";\nimport {IMasterContract} from \"BoringSolidity/interfaces/IMasterContract.sol\";\nimport {RebaseLibrary, Rebase} from \"BoringSolidity/libraries/BoringRebase.sol\";\nimport {BoringMath, BoringMath128} from \"BoringSolidity/libraries/BoringMath.sol\";\n\n// solhint-disable avoid-low-level-calls\n// solhint-disable no-inline-assembly\n\n/// @title Cauldron\n/// @dev This contract allows contract calls to any contract (except BentoBox)\n/// from arbitrary callers thus, don't trust calls from this contract in any circumstances.\ncontract CauldronV4 is Owned, IMasterContract {\n    using BoringMath for uint256;\n    using BoringMath128 for uint128;\n    using RebaseLibrary for Rebase;\n\n    event LogExchangeRate(uint256 rate);\n    event LogAccrue(uint128 accruedAmount);\n    event LogAddCollateral(address indexed from, address indexed to, uint256 share);\n    event LogRemoveCollateral(address indexed from, address indexed to, uint256 share);\n    event LogBorrow(address indexed from, address indexed to, uint256 amount, uint256 part);\n    event LogRepay(address indexed from, address indexed to, uint256 amount, uint256 part);\n    event LogFeeTo(address indexed newFeeTo);\n    event LogWithdrawFees(address indexed feeTo, uint256 feesEarnedFraction);\n    event LogInterestChange(uint64 oldInterestRate, uint64 newInterestRate);\n    event LogChangeBorrowLimit(uint128 newLimit, uint128 perAddressPart);\n    event LogChangeBlacklistedCallee(address indexed account, bool blacklisted);\n    event LogLiquidationMultiplierChanged(uint256 previous, uint256 current);\n    event LogBorrowOpeningFeeChanged(uint256 previous, uint256 current);\n    event LogCollateralizationRateChanged(uint256 previous, uint256 current);\n    \n    event LogLiquidation(\n        address indexed from,\n        address indexed user,\n        address indexed to,\n        uint256 collateralShare,\n        uint256 borrowAmount,\n        uint256 borrowPart\n    );\n\n    error ErrNotClone();\n\n    // Immutables (for MasterContract and all clones)\n    IBentoBoxV1 public immutable bentoBox;\n    CauldronV4 public immutable masterContract;\n    IERC20 public immutable magicInternetMoney;\n\n    // MasterContract variables\n    address public feeTo;\n\n    // Per clone variables\n    // Clone init settings\n    IERC20 public collateral;\n    IOracle public oracle;\n    bytes public oracleData;\n\n    struct BorrowCap {\n        uint128 total;\n        uint128 borrowPartPerAddress;\n    }\n\n    BorrowCap public borrowLimit;\n\n    // Total amounts\n    uint256 public totalCollateralShare; // Total collateral supplied\n    Rebase public totalBorrow; // elastic = Total token amount to be repayed by borrowers, base = Total parts of the debt held by borrowers\n\n    // User balances\n    mapping(address => uint256) public userCollateralShare;\n    mapping(address => uint256) public userBorrowPart;\n\n    // Callee restrictions\n    mapping(address => bool) public blacklistedCallees;\n\n    /// @notice Exchange and interest rate tracking.\n    /// This is 'cached' here because calls to Oracles can be very expensive.\n    uint256 public exchangeRate;\n\n    struct AccrueInfo {\n        uint64 lastAccrued;\n        uint128 feesEarned;\n        uint64 INTEREST_PER_SECOND;\n    }\n\n    AccrueInfo public accrueInfo;\n\n    uint64 internal constant ONE_PERCENT_RATE = 317097920;\n\n    // Settings\n    uint256 public COLLATERIZATION_RATE;\n    uint256 internal constant COLLATERIZATION_RATE_PRECISION = 1e5; // Must be less than EXCHANGE_RATE_PRECISION (due to optimization in math)\n\n    uint256 internal constant EXCHANGE_RATE_PRECISION = 1e18;\n\n    uint256 public LIQUIDATION_MULTIPLIER; \n    uint256 internal constant LIQUIDATION_MULTIPLIER_PRECISION = 1e5;\n\n    uint256 public BORROW_OPENING_FEE;\n    uint256 internal constant BORROW_OPENING_FEE_PRECISION = 1e5;\n\n    uint256 internal constant DISTRIBUTION_PART = 10;\n    uint256 internal constant DISTRIBUTION_PRECISION = 100;\n\n    modifier onlyMasterContractOwner() {\n        require(msg.sender == masterContract.owner(), \"Caller is not the owner\");\n        _;\n    }\n\n    modifier onlyClones() {\n        if (address(this) == address(masterContract)) {\n            revert ErrNotClone();\n        }\n        _;\n    }\n\n    /// @notice The constructor is only used for the initial master contract. Subsequent clones are initialised via `init`.\n    constructor(IBentoBoxV1 bentoBox_, IERC20 magicInternetMoney_) Owned(msg.sender) {\n        bentoBox = bentoBox_;\n        magicInternetMoney = magicInternetMoney_;\n        masterContract = this;\n        \n        blacklistedCallees[address(bentoBox)] = true;\n        blacklistedCallees[address(this)] = true;\n        blacklistedCallees[Owned(address(bentoBox)).owner()] = true;\n    }\n\n    /// @notice Serves as the constructor for clones, as clones can't have a regular constructor\n    /// @dev `data` is abi encoded in the format: (IERC20 collateral, IERC20 asset, IOracle oracle, bytes oracleData)\n    function init(bytes calldata data) public virtual onlyClones payable override {\n        require(address(collateral) == address(0), \"Cauldron: already initialized\");\n        (collateral, oracle, oracleData, accrueInfo.INTEREST_PER_SECOND, LIQUIDATION_MULTIPLIER, COLLATERIZATION_RATE, BORROW_OPENING_FEE) = abi.decode(data, (IERC20, IOracle, bytes, uint64, uint256, uint256, uint256));\n        borrowLimit = BorrowCap(type(uint128).max, type(uint128).max);\n        require(address(collateral) != address(0), \"Cauldron: bad pair\");\n\n        magicInternetMoney.approve(address(bentoBox), type(uint256).max);\n\n        blacklistedCallees[address(bentoBox)] = true;\n        blacklistedCallees[address(this)] = true;\n        blacklistedCallees[Owned(address(bentoBox)).owner()] = true;\n\n        (, exchangeRate) = oracle.get(oracleData);\n\n        accrue();\n    }\n\n    /// @notice Accrues the interest on the borrowed tokens and handles the accumulation of fees.\n    function accrue() public {\n        AccrueInfo memory _accrueInfo = accrueInfo;\n        // Number of seconds since accrue was called\n        uint256 elapsedTime = block.timestamp - _accrueInfo.lastAccrued;\n        if (elapsedTime == 0) {\n            return;\n        }\n        _accrueInfo.lastAccrued = uint64(block.timestamp);\n\n        Rebase memory _totalBorrow = totalBorrow;\n        if (_totalBorrow.base == 0) {\n            accrueInfo = _accrueInfo;\n            return;\n        }\n\n        // Accrue interest\n        uint128 extraAmount = (uint256(_totalBorrow.elastic).mul(_accrueInfo.INTEREST_PER_SECOND).mul(elapsedTime) / 1e18).to128();\n        _totalBorrow.elastic = _totalBorrow.elastic.add(extraAmount);\n\n        _accrueInfo.feesEarned = _accrueInfo.feesEarned.add(extraAmount);\n        totalBorrow = _totalBorrow;\n        accrueInfo = _accrueInfo;\n\n        emit LogAccrue(extraAmount);\n    }\n\n    /// @notice Concrete implementation of `isSolvent`. Includes a third parameter to allow caching `exchangeRate`.\n    /// @param _exchangeRate The exchange rate. Used to cache the `exchangeRate` between calls.\n    function _isSolvent(address user, uint256 _exchangeRate) virtual internal view returns (bool) {\n        // accrue must have already been called!\n        uint256 borrowPart = userBorrowPart[user];\n        if (borrowPart == 0) return true;\n        uint256 collateralShare = userCollateralShare[user];\n        if (collateralShare == 0) return false;\n\n        Rebase memory _totalBorrow = totalBorrow;\n\n        return\n            bentoBox.toAmount(\n                collateral,\n                collateralShare.mul(EXCHANGE_RATE_PRECISION / COLLATERIZATION_RATE_PRECISION).mul(COLLATERIZATION_RATE),\n                false\n            ) >=\n            // Moved exchangeRate here instead of dividing the other side to preserve more precision\n            borrowPart.mul(_totalBorrow.elastic).mul(_exchangeRate) / _totalBorrow.base;\n    }\n\n    function isSolvent(address user) public view returns (bool) {\n        return _isSolvent(user, exchangeRate);\n    }\n    \n    /// @dev Checks if the user is solvent in the closed liquidation case at the end of the function body.\n    modifier solvent() {\n        _;\n        (, uint256 _exchangeRate) = updateExchangeRate();\n        require(_isSolvent(msg.sender, _exchangeRate), \"Cauldron: user insolvent\");\n    }\n\n    /// @notice Gets the exchange rate. I.e how much collateral to buy 1e18 asset.\n    /// This function is supposed to be invoked if needed because Oracle queries can be expensive.\n    /// @return updated True if `exchangeRate` was updated.\n    /// @return rate The new exchange rate.\n    function updateExchangeRate() public returns (bool updated, uint256 rate) {\n        (updated, rate) = oracle.get(oracleData);\n\n        if (updated) {\n            exchangeRate = rate;\n            emit LogExchangeRate(rate);\n        } else {\n            // Return the old rate if fetching wasn't successful\n            rate = exchangeRate;\n        }\n    }\n\n    /// @dev Helper function to move tokens.\n    /// @param token The ERC-20 token.\n    /// @param share The amount in shares to add.\n    /// @param total Grand total amount to deduct from this contract's balance. Only applicable if `skim` is True.\n    /// Only used for accounting checks.\n    /// @param skim If True, only does a balance check on this contract.\n    /// False if tokens from msg.sender in `bentoBox` should be transferred.\n    function _addTokens(\n        IERC20 token,\n        uint256 share,\n        uint256 total,\n        bool skim\n    ) internal {\n        if (skim) {\n            require(share <= bentoBox.balanceOf(token, address(this)).sub(total), \"Cauldron: Skim too much\");\n        } else {\n            bentoBox.transfer(token, msg.sender, address(this), share);\n        }\n    }\n\n    function _afterAddCollateral(address user, uint256 collateralShare) internal virtual {}\n\n    /// @notice Adds `collateral` from msg.sender to the account `to`.\n    /// @param to The receiver of the tokens.\n    /// @param skim True if the amount should be skimmed from the deposit balance of msg.sender.x\n    /// False if tokens from msg.sender in `bentoBox` should be transferred.\n    /// @param share The amount of shares to add for `to`.\n    function addCollateral(\n        address to,\n        bool skim,\n        uint256 share\n    ) public virtual {\n        userCollateralShare[to] = userCollateralShare[to].add(share);\n        uint256 oldTotalCollateralShare = totalCollateralShare;\n        totalCollateralShare = oldTotalCollateralShare.add(share);\n        _addTokens(collateral, share, oldTotalCollateralShare, skim);\n        _afterAddCollateral(to, share);\n        emit LogAddCollateral(skim ? address(bentoBox) : msg.sender, to, share);\n    }\n\n    function _afterRemoveCollateral(address from, address to, uint256 collateralShare) internal virtual {}\n\n    /// @dev Concrete implementation of `removeCollateral`.\n    function _removeCollateral(address to, uint256 share) internal virtual {\n        userCollateralShare[msg.sender] = userCollateralShare[msg.sender].sub(share);\n        totalCollateralShare = totalCollateralShare.sub(share);\n        _afterRemoveCollateral(msg.sender, to, share);\n        emit LogRemoveCollateral(msg.sender, to, share);\n        bentoBox.transfer(collateral, address(this), to, share);\n    }\n\n    /// @notice Removes `share` amount of collateral and transfers it to `to`.\n    /// @param to The receiver of the shares.\n    /// @param share Amount of shares to remove.\n    function removeCollateral(address to, uint256 share) public solvent {\n        // accrue must be called because we check solvency\n        accrue();\n        _removeCollateral(to, share);\n    }\n\n    function _preBorrowAction(address to, uint256 amount, uint256 newBorrowPart, uint256 part) internal virtual {\n\n    }\n\n    /// @dev Concrete implementation of `borrow`.\n    function _borrow(address to, uint256 amount) internal returns (uint256 part, uint256 share) {\n        uint256 feeAmount = amount.mul(BORROW_OPENING_FEE) / BORROW_OPENING_FEE_PRECISION; // A flat % fee is charged for any borrow\n        (totalBorrow, part) = totalBorrow.add(amount.add(feeAmount), true);\n\n        BorrowCap memory cap =  borrowLimit;\n\n        require(totalBorrow.elastic <= cap.total, \"Borrow Limit reached\");\n\n        accrueInfo.feesEarned = accrueInfo.feesEarned.add(uint128(feeAmount));\n        \n        uint256 newBorrowPart = userBorrowPart[msg.sender].add(part);\n        require(newBorrowPart <= cap.borrowPartPerAddress, \"Borrow Limit reached\");\n        _preBorrowAction(to, amount, newBorrowPart, part);\n\n        userBorrowPart[msg.sender] = newBorrowPart;\n\n        // As long as there are tokens on this contract you can 'mint'... this enables limiting borrows\n        share = bentoBox.toShare(magicInternetMoney, amount, false);\n        bentoBox.transfer(magicInternetMoney, address(this), to, share);\n\n        emit LogBorrow(msg.sender, to, amount.add(feeAmount), part);\n    }\n\n    /// @notice Sender borrows `amount` and transfers it to `to`.\n    /// @return part Total part of the debt held by borrowers.\n    /// @return share Total amount in shares borrowed.\n    function borrow(address to, uint256 amount) public solvent returns (uint256 part, uint256 share) {\n        accrue();\n        (part, share) = _borrow(to, amount);\n    }\n\n    /// @dev Concrete implementation of `repay`.\n    function _repay(\n        address to,\n        bool skim,\n        uint256 part\n    ) internal returns (uint256 amount) {\n        (totalBorrow, amount) = totalBorrow.sub(part, true);\n        userBorrowPart[to] = userBorrowPart[to].sub(part);\n\n        uint256 share = bentoBox.toShare(magicInternetMoney, amount, true);\n        bentoBox.transfer(magicInternetMoney, skim ? address(bentoBox) : msg.sender, address(this), share);\n        emit LogRepay(skim ? address(bentoBox) : msg.sender, to, amount, part);\n    }\n\n    /// @notice Repays a loan.\n    /// @param to Address of the user this payment should go.\n    /// @param skim True if the amount should be skimmed from the deposit balance of msg.sender.\n    /// False if tokens from msg.sender in `bentoBox` should be transferred.\n    /// @param part The amount to repay. See `userBorrowPart`.\n    /// @return amount The total amount repayed.\n    function repay(\n        address to,\n        bool skim,\n        uint256 part\n    ) public returns (uint256 amount) {\n        accrue();\n        amount = _repay(to, skim, part);\n    }\n\n    // Functions that need accrue to be called\n    uint8 internal constant ACTION_REPAY = 2;\n    uint8 internal constant ACTION_REMOVE_COLLATERAL = 4;\n    uint8 internal constant ACTION_BORROW = 5;\n    uint8 internal constant ACTION_GET_REPAY_SHARE = 6;\n    uint8 internal constant ACTION_GET_REPAY_PART = 7;\n    uint8 internal constant ACTION_ACCRUE = 8;\n\n    // Functions that don't need accrue to be called\n    uint8 internal constant ACTION_ADD_COLLATERAL = 10;\n    uint8 internal constant ACTION_UPDATE_EXCHANGE_RATE = 11;\n\n    // Function on BentoBox\n    uint8 internal constant ACTION_BENTO_DEPOSIT = 20;\n    uint8 internal constant ACTION_BENTO_WITHDRAW = 21;\n    uint8 internal constant ACTION_BENTO_TRANSFER = 22;\n    uint8 internal constant ACTION_BENTO_TRANSFER_MULTIPLE = 23;\n    uint8 internal constant ACTION_BENTO_SETAPPROVAL = 24;\n\n    // Any external call (except to BentoBox)\n    uint8 internal constant ACTION_CALL = 30;\n    uint8 internal constant ACTION_LIQUIDATE = 31;\n\n    // Custom cook actions\n    uint8 internal constant ACTION_CUSTOM_START_INDEX = 100;\n\n    int256 internal constant USE_VALUE1 = -1;\n    int256 internal constant USE_VALUE2 = -2;\n\n    /// @dev Helper function for choosing the correct value (`value1` or `value2`) depending on `inNum`.\n    function _num(\n        int256 inNum,\n        uint256 value1,\n        uint256 value2\n    ) internal pure returns (uint256 outNum) {\n        outNum = inNum >= 0 ? uint256(inNum) : (inNum == USE_VALUE1 ? value1 : value2);\n    }\n\n    /// @dev Helper function for depositing into `bentoBox`.\n    function _bentoDeposit(\n        bytes memory data,\n        uint256 value,\n        uint256 value1,\n        uint256 value2\n    ) internal returns (uint256, uint256) {\n        (IERC20 token, address to, int256 amount, int256 share) = abi.decode(data, (IERC20, address, int256, int256));\n        amount = int256(_num(amount, value1, value2)); // Done this way to avoid stack too deep errors\n        share = int256(_num(share, value1, value2));\n        return bentoBox.deposit{value: value}(token, msg.sender, to, uint256(amount), uint256(share));\n    }\n\n    /// @dev Helper function to withdraw from the `bentoBox`.\n    function _bentoWithdraw(\n        bytes memory data,\n        uint256 value1,\n        uint256 value2\n    ) internal returns (uint256, uint256) {\n        (IERC20 token, address to, int256 amount, int256 share) = abi.decode(data, (IERC20, address, int256, int256));\n        return bentoBox.withdraw(token, msg.sender, to, _num(amount, value1, value2), _num(share, value1, value2));\n    }\n\n    /// @dev Helper function to perform a contract call and eventually extracting revert messages on failure.\n    /// Calls to `bentoBox` are not allowed for obvious security reasons.\n    /// This also means that calls made from this contract shall *not* be trusted.\n    function _call(\n        uint256 value,\n        bytes memory data,\n        uint256 value1,\n        uint256 value2\n    ) internal returns (bytes memory, uint8) {\n        (address callee, bytes memory callData, bool useValue1, bool useValue2, uint8 returnValues) =\n            abi.decode(data, (address, bytes, bool, bool, uint8));\n\n        if (useValue1 && !useValue2) {\n            callData = abi.encodePacked(callData, value1);\n        } else if (!useValue1 && useValue2) {\n            callData = abi.encodePacked(callData, value2);\n        } else if (useValue1 && useValue2) {\n            callData = abi.encodePacked(callData, value1, value2);\n        }\n\n        require(!blacklistedCallees[callee], \"Cauldron: can't call\");\n\n        (bool success, bytes memory returnData) = callee.call{value: value}(callData);\n        require(success, \"Cauldron: call failed\");\n        return (returnData, returnValues);\n    }\n\n    struct CookStatus {\n        bool needsSolvencyCheck;\n        bool hasAccrued;\n    }\n\n    function _additionalCookAction(uint8 action, CookStatus memory, uint256 value, bytes memory data, uint256 value1, uint256 value2) internal virtual returns (bytes memory, uint8, CookStatus memory) {}\n\n    /// @notice Executes a set of actions and allows composability (contract calls) to other contracts.\n    /// @param actions An array with a sequence of actions to execute (see ACTION_ declarations).\n    /// @param values A one-to-one mapped array to `actions`. ETH amounts to send along with the actions.\n    /// Only applicable to `ACTION_CALL`, `ACTION_BENTO_DEPOSIT`.\n    /// @param datas A one-to-one mapped array to `actions`. Contains abi encoded data of function arguments.\n    /// @return value1 May contain the first positioned return value of the last executed action (if applicable).\n    /// @return value2 May contain the second positioned return value of the last executed action which returns 2 values (if applicable).\n    function cook(\n        uint8[] calldata actions,\n        uint256[] calldata values,\n        bytes[] calldata datas\n    ) external payable returns (uint256 value1, uint256 value2) {\n        CookStatus memory status;\n\n        for (uint256 i = 0; i < actions.length; i++) {\n            uint8 action = actions[i];\n            if (!status.hasAccrued && action < 10) {\n                accrue();\n                status.hasAccrued = true;\n            }\n            if (action == ACTION_ADD_COLLATERAL) {\n                (int256 share, address to, bool skim) = abi.decode(datas[i], (int256, address, bool));\n                addCollateral(to, skim, _num(share, value1, value2));\n            } else if (action == ACTION_REPAY) {\n                (int256 part, address to, bool skim) = abi.decode(datas[i], (int256, address, bool));\n                _repay(to, skim, _num(part, value1, value2));\n            } else if (action == ACTION_REMOVE_COLLATERAL) {\n                (int256 share, address to) = abi.decode(datas[i], (int256, address));\n                _removeCollateral(to, _num(share, value1, value2));\n                status.needsSolvencyCheck = true;\n            } else if (action == ACTION_BORROW) {\n                (int256 amount, address to) = abi.decode(datas[i], (int256, address));\n                (value1, value2) = _borrow(to, _num(amount, value1, value2));\n                status.needsSolvencyCheck = true;\n            } else if (action == ACTION_UPDATE_EXCHANGE_RATE) {\n                (bool must_update, uint256 minRate, uint256 maxRate) = abi.decode(datas[i], (bool, uint256, uint256));\n                (bool updated, uint256 rate) = updateExchangeRate();\n                require((!must_update || updated) && rate > minRate && (maxRate == 0 || rate < maxRate), \"Cauldron: rate not ok\");\n            } else if (action == ACTION_BENTO_SETAPPROVAL) {\n                (address user, address _masterContract, bool approved, uint8 v, bytes32 r, bytes32 s) =\n                    abi.decode(datas[i], (address, address, bool, uint8, bytes32, bytes32));\n                bentoBox.setMasterContractApproval(user, _masterContract, approved, v, r, s);\n            } else if (action == ACTION_BENTO_DEPOSIT) {\n                (value1, value2) = _bentoDeposit(datas[i], values[i], value1, value2);\n            } else if (action == ACTION_BENTO_WITHDRAW) {\n                (value1, value2) = _bentoWithdraw(datas[i], value1, value2);\n            } else if (action == ACTION_BENTO_TRANSFER) {\n                (IERC20 token, address to, int256 share) = abi.decode(datas[i], (IERC20, address, int256));\n                bentoBox.transfer(token, msg.sender, to, _num(share, value1, value2));\n            } else if (action == ACTION_BENTO_TRANSFER_MULTIPLE) {\n                (IERC20 token, address[] memory tos, uint256[] memory shares) = abi.decode(datas[i], (IERC20, address[], uint256[]));\n                bentoBox.transferMultiple(token, msg.sender, tos, shares);\n            } else if (action == ACTION_CALL) {\n                (bytes memory returnData, uint8 returnValues) = _call(values[i], datas[i], value1, value2);\n\n                if (returnValues == 1) {\n                    (value1) = abi.decode(returnData, (uint256));\n                } else if (returnValues == 2) {\n                    (value1, value2) = abi.decode(returnData, (uint256, uint256));\n                }\n            } else if (action == ACTION_GET_REPAY_SHARE) {\n                int256 part = abi.decode(datas[i], (int256));\n                value1 = bentoBox.toShare(magicInternetMoney, totalBorrow.toElastic(_num(part, value1, value2), true), true);\n            } else if (action == ACTION_GET_REPAY_PART) {\n                int256 amount = abi.decode(datas[i], (int256));\n                value1 = totalBorrow.toBase(_num(amount, value1, value2), false);\n            } else if (action == ACTION_LIQUIDATE) {\n                _cookActionLiquidate(datas[i]);\n            } else {\n                (bytes memory returnData, uint8 returnValues, CookStatus memory returnStatus) = _additionalCookAction(action, status, values[i], datas[i], value1, value2);\n                status = returnStatus;\n                \n                if (returnValues == 1) {\n                    (value1) = abi.decode(returnData, (uint256));\n                } else if (returnValues == 2) {\n                    (value1, value2) = abi.decode(returnData, (uint256, uint256));\n                }\n            }\n        }\n\n        if (status.needsSolvencyCheck) {\n            (, uint256 _exchangeRate) = updateExchangeRate();\n            require(_isSolvent(msg.sender, _exchangeRate), \"Cauldron: user insolvent\");\n        }\n    }\n\n    function _cookActionLiquidate(bytes calldata data) internal {\n         (address[] memory users, uint256[] memory maxBorrowParts, address to, ISwapperV2 swapper, bytes memory swapperData) = abi.decode(data, (address[], uint256[], address, ISwapperV2, bytes));\n        liquidate(users, maxBorrowParts, to, swapper, swapperData);\n    }\n\n    function _beforeUsersLiquidated(address[] memory users, uint256[] memory maxBorrowPart) internal virtual {}\n\n    function _beforeUserLiquidated(address user, uint256 borrowPart, uint256 borrowAmount, uint256 collateralShare) internal virtual {}\n\n    function _afterUserLiquidated(address user, uint256 collateralShare) internal virtual {}\n\n    /// @notice Handles the liquidation of users' balances, once the users' amount of collateral is too low.\n    /// @param users An array of user addresses.\n    /// @param maxBorrowParts A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user.\n    /// @param to Address of the receiver in open liquidations if `swapper` is zero.\n    function liquidate(\n        address[] memory users,\n        uint256[] memory maxBorrowParts,\n        address to,\n        ISwapperV2 swapper,\n        bytes memory swapperData\n    ) public virtual {\n        // Oracle can fail but we still need to allow liquidations\n        (, uint256 _exchangeRate) = updateExchangeRate();\n        accrue();\n\n        uint256 allCollateralShare;\n        uint256 allBorrowAmount;\n        uint256 allBorrowPart;\n        Rebase memory bentoBoxTotals = bentoBox.totals(collateral);\n        _beforeUsersLiquidated(users, maxBorrowParts);\n\n        for (uint256 i = 0; i < users.length; i++) {\n            address user = users[i];\n            if (!_isSolvent(user, _exchangeRate)) {\n                uint256 borrowPart;\n                uint256 availableBorrowPart = userBorrowPart[user];\n                borrowPart = maxBorrowParts[i] > availableBorrowPart ? availableBorrowPart : maxBorrowParts[i];\n\n                uint256 borrowAmount = totalBorrow.toElastic(borrowPart, false);\n                uint256 collateralShare =\n                    bentoBoxTotals.toBase(\n                        borrowAmount.mul(LIQUIDATION_MULTIPLIER).mul(_exchangeRate) /\n                            (LIQUIDATION_MULTIPLIER_PRECISION * EXCHANGE_RATE_PRECISION),\n                        false\n                    );\n\n                _beforeUserLiquidated(user, borrowPart, borrowAmount, collateralShare);\n                userBorrowPart[user] = availableBorrowPart.sub(borrowPart);\n                userCollateralShare[user] = userCollateralShare[user].sub(collateralShare);\n                _afterUserLiquidated(user, collateralShare);\n\n                emit LogRemoveCollateral(user, to, collateralShare);\n                emit LogRepay(msg.sender, user, borrowAmount, borrowPart);\n                emit LogLiquidation(msg.sender, user, to, collateralShare, borrowAmount, borrowPart);\n\n                // Keep totals\n                allCollateralShare = allCollateralShare.add(collateralShare);\n                allBorrowAmount = allBorrowAmount.add(borrowAmount);\n                allBorrowPart = allBorrowPart.add(borrowPart);\n            }\n        }\n        require(allBorrowAmount != 0, \"Cauldron: all are solvent\");\n        totalBorrow.elastic = totalBorrow.elastic.sub(allBorrowAmount.to128());\n        totalBorrow.base = totalBorrow.base.sub(allBorrowPart.to128());\n        totalCollateralShare = totalCollateralShare.sub(allCollateralShare);\n\n        // Apply a percentual fee share to sSpell holders\n        \n        {\n            uint256 distributionAmount = (allBorrowAmount.mul(LIQUIDATION_MULTIPLIER) / LIQUIDATION_MULTIPLIER_PRECISION).sub(allBorrowAmount).mul(DISTRIBUTION_PART) / DISTRIBUTION_PRECISION; // Distribution Amount\n            allBorrowAmount = allBorrowAmount.add(distributionAmount);\n            accrueInfo.feesEarned = accrueInfo.feesEarned.add(distributionAmount.to128());\n        }\n\n        uint256 allBorrowShare = bentoBox.toShare(magicInternetMoney, allBorrowAmount, true);\n\n        // Swap using a swapper freely chosen by the caller\n        // Open (flash) liquidation: get proceeds first and provide the borrow after\n        bentoBox.transfer(collateral, address(this), to, allCollateralShare);\n        if (swapper != ISwapperV2(address(0))) {\n            swapper.swap(address(collateral), address(magicInternetMoney), msg.sender, allBorrowShare, allCollateralShare, swapperData);\n        }\n\n        allBorrowShare = bentoBox.toShare(magicInternetMoney, allBorrowAmount, true);\n        bentoBox.transfer(magicInternetMoney, msg.sender, address(this), allBorrowShare);\n    }\n\n    /// @notice Withdraws the fees accumulated.\n    function withdrawFees() public {\n        accrue();\n        address _feeTo = masterContract.feeTo();\n        uint256 _feesEarned = accrueInfo.feesEarned;\n        uint256 share = bentoBox.toShare(magicInternetMoney, _feesEarned, false);\n        bentoBox.transfer(magicInternetMoney, address(this), _feeTo, share);\n        accrueInfo.feesEarned = 0;\n\n        emit LogWithdrawFees(_feeTo, _feesEarned);\n    }\n\n    /// @notice Sets the beneficiary of interest accrued.\n    /// MasterContract Only Admin function.\n    /// @param newFeeTo The address of the receiver.\n    function setFeeTo(address newFeeTo) public onlyOwner {\n        feeTo = newFeeTo;\n        emit LogFeeTo(newFeeTo);\n    }\n\n    /// @notice reduces the supply of MIM\n    /// @param amount amount to reduce supply by\n    function reduceSupply(uint256 amount) public onlyMasterContractOwner {\n        uint256 maxAmount = bentoBox.toAmount(magicInternetMoney, bentoBox.balanceOf(magicInternetMoney, address(this)), false);\n        amount = maxAmount > amount ? amount : maxAmount;\n        bentoBox.withdraw(magicInternetMoney, address(this), msg.sender, amount, 0);\n    }\n\n    /// @notice allows to change the interest rate\n    /// @param newInterestRate new interest rate\n    function changeInterestRate(uint64 newInterestRate) public onlyMasterContractOwner {\n        accrue();\n        emit LogInterestChange(accrueInfo.INTEREST_PER_SECOND, newInterestRate);\n        accrueInfo.INTEREST_PER_SECOND = newInterestRate;\n    }\n\n    /// @notice allows to change the borrow limit\n    /// @param newBorrowLimit new borrow limit\n    /// @param perAddressPart new borrow limit per address\n    function changeBorrowLimit(uint128 newBorrowLimit, uint128 perAddressPart) public onlyMasterContractOwner {\n        borrowLimit = BorrowCap(newBorrowLimit, perAddressPart);\n        emit LogChangeBorrowLimit(newBorrowLimit, perAddressPart);\n    }\n\n    /// @notice allows to change blacklisted callees\n    /// @param callee callee to blacklist or not\n    /// @param blacklisted true when the callee cannot be used in call cook action\n    function setBlacklistedCallee(address callee, bool blacklisted) public onlyMasterContractOwner {\n        require(callee != address(bentoBox) && callee != address(this), \"invalid callee\");\n\n        blacklistedCallees[callee] = blacklisted;\n        emit LogChangeBlacklistedCallee(callee, blacklisted);\n    }\n\n    /// Allows to change the liquidation multiplier\n    /// @param _liquidationMultiplier new liquidation multiplier.\n    /// To convert from bips: liquidationFeeBips * 1e1 + 1e5\n    function setLiquidationMultiplier(uint256 _liquidationMultiplier) public onlyMasterContractOwner {\n        emit LogLiquidationMultiplierChanged(LIQUIDATION_MULTIPLIER, _liquidationMultiplier);\n        LIQUIDATION_MULTIPLIER = _liquidationMultiplier;\n    }\n\n    /// Allows to change the borrow opening fee\n    /// @param _borrowOpeningFee new borrow opening fee.\n    /// To convert from bips: borrowOpeningFeeBips * 1e1\n    function setBorrowOpeningFee(uint256 _borrowOpeningFee) public onlyMasterContractOwner {\n        emit LogBorrowOpeningFeeChanged(BORROW_OPENING_FEE, _borrowOpeningFee);\n        BORROW_OPENING_FEE = _borrowOpeningFee;\n    }\n\n    /// Allows to change the collateralization rate\n    /// @param _collateralizationRate new collateralization rate.\n    /// To convert from bips: collateralizationRateBips * 1e1\n    function setCollateralizationRate(uint256 _collateralizationRate) public onlyMasterContractOwner {\n        emit LogCollateralizationRateChanged(COLLATERIZATION_RATE, _collateralizationRate);\n        COLLATERIZATION_RATE = _collateralizationRate;\n    }\n}\n"
      },
      "lib/BoringSolidity/contracts/libraries/BoringRebase.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\nimport {BoringMath, BoringMath128} from \"./BoringMath.sol\";\n\nstruct Rebase {\n    uint128 elastic;\n    uint128 base;\n}\n\n/// @notice A rebasing library using overflow-/underflow-safe math.\nlibrary RebaseLibrary {\n    using BoringMath for uint256;\n    using BoringMath128 for uint128;\n\n    /// @notice Calculates the base value in relationship to `elastic` and `total`.\n    function toBase(\n        Rebase memory total,\n        uint256 elastic,\n        bool roundUp\n    ) internal pure returns (uint256 base) {\n        if (total.elastic == 0) {\n            base = elastic;\n        } else {\n            base = (elastic * total.base) / total.elastic;\n            if (roundUp && (base * total.elastic) / total.base < elastic) {\n                base++;\n            }\n        }\n    }\n\n    /// @notice Calculates the elastic value in relationship to `base` and `total`.\n    function toElastic(\n        Rebase memory total,\n        uint256 base,\n        bool roundUp\n    ) internal pure returns (uint256 elastic) {\n        if (total.base == 0) {\n            elastic = base;\n        } else {\n            elastic = (base * total.elastic) / total.base;\n            if (roundUp && (elastic * total.base) / total.elastic < base) {\n                elastic++;\n            }\n        }\n    }\n\n    /// @notice Add `elastic` to `total` and doubles `total.base`.\n    /// @return (Rebase) The new total.\n    /// @return base in relationship to `elastic`.\n    function add(\n        Rebase memory total,\n        uint256 elastic,\n        bool roundUp\n    ) internal pure returns (Rebase memory, uint256 base) {\n        base = toBase(total, elastic, roundUp);\n        total.elastic += elastic.to128();\n        total.base += base.to128();\n        return (total, base);\n    }\n\n    /// @notice Sub `base` from `total` and update `total.elastic`.\n    /// @return (Rebase) The new total.\n    /// @return elastic in relationship to `base`.\n    function sub(\n        Rebase memory total,\n        uint256 base,\n        bool roundUp\n    ) internal pure returns (Rebase memory, uint256 elastic) {\n        elastic = toElastic(total, base, roundUp);\n        total.elastic -= elastic.to128();\n        total.base -= base.to128();\n        return (total, elastic);\n    }\n\n    /// @notice Add `elastic` and `base` to `total`.\n    function add(\n        Rebase memory total,\n        uint256 elastic,\n        uint256 base\n    ) internal pure returns (Rebase memory) {\n        total.elastic += elastic.to128();\n        total.base += base.to128();\n        return total;\n    }\n\n    /// @notice Subtract `elastic` and `base` to `total`.\n    function sub(\n        Rebase memory total,\n        uint256 elastic,\n        uint256 base\n    ) internal pure returns (Rebase memory) {\n        total.elastic -= elastic.to128();\n        total.base -= base.to128();\n        return total;\n    }\n\n    /// @notice Add `elastic` to `total` and update storage.\n    /// @return newElastic Returns updated `elastic`.\n    function addElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) {\n        newElastic = total.elastic += elastic.to128();\n    }\n\n    /// @notice Subtract `elastic` from `total` and update storage.\n    /// @return newElastic Returns updated `elastic`.\n    function subElastic(Rebase storage total, uint256 elastic) internal returns (uint256 newElastic) {\n        newElastic = total.elastic -= elastic.to128();\n    }\n}\n"
      },
      "src/interfaces/IStrategy.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\ninterface IStrategy {\n    function skim(uint256 amount) external;\n\n    function harvest(uint256 balance, address sender) external returns (int256 amountAdded);\n\n    function withdraw(uint256 amount) external returns (uint256 actualAmount);\n\n    function exit(uint256 balance) external returns (int256 amountAdded);\n}\n"
      },
      "lib/solmate/src/auth/Owned.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Simple single owner authorization mixin.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)\nabstract contract Owned {\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event OwnershipTransferred(address indexed user, address indexed newOwner);\n\n    /*//////////////////////////////////////////////////////////////\n                            OWNERSHIP STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    address public owner;\n\n    modifier onlyOwner() virtual {\n        require(msg.sender == owner, \"UNAUTHORIZED\");\n\n        _;\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                               CONSTRUCTOR\n    //////////////////////////////////////////////////////////////*/\n\n    constructor(address _owner) {\n        owner = _owner;\n\n        emit OwnershipTransferred(address(0), _owner);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                             OWNERSHIP LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        owner = newOwner;\n\n        emit OwnershipTransferred(msg.sender, newOwner);\n    }\n}\n"
      },
      "src/interfaces/IOracle.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\ninterface IOracle {\n    function decimals() external view returns (uint8);\n\n    function get(bytes calldata data) external returns (bool success, uint256 rate);\n\n    function peek(bytes calldata data) external view returns (bool success, uint256 rate);\n\n    function peekSpot(bytes calldata data) external view returns (uint256 rate);\n\n    function symbol(bytes calldata data) external view returns (string memory);\n\n    function name(bytes calldata data) external view returns (string memory);\n}\n"
      },
      "src/interfaces/ISwapperV2.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\ninterface ISwapperV2 {\n    function swap(\n        address fromToken,\n        address toToken,\n        address recipient,\n        uint256 shareToMin,\n        uint256 shareFrom,\n        bytes calldata data\n    ) external returns (uint256 extraShare, uint256 shareReturned);\n}\n"
      },
      "lib/BoringSolidity/contracts/interfaces/IMasterContract.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IMasterContract {\n    /// @notice Init function that gets called from `BoringFactory.deploy`.\n    /// Also kown as the constructor for cloned contracts.\n    /// Any ETH send to `BoringFactory.deploy` ends up here.\n    /// @param data Can be abi encoded arguments or anything else.\n    function init(bytes calldata data) external payable;\n}\n"
      },
      "lib/BoringSolidity/contracts/libraries/BoringMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\nlibrary BoringMath {\n    error ErrOverflow();\n\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a + b;\n    }\n\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a - b;\n    }\n\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a * b;\n    }\n\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a / b;\n    }\n\n    function to32(uint256 a) internal pure returns (uint32) {\n        if (a > type(uint32).max) {\n            revert ErrOverflow();\n        }\n        return uint32(a);\n    }\n\n    function to40(uint256 a) internal pure returns (uint40) {\n        if (a > type(uint40).max) {\n            revert ErrOverflow();\n        }\n        return uint40(a);\n    }\n\n    function to64(uint256 a) internal pure returns (uint64) {\n        if (a > type(uint64).max) {\n            revert ErrOverflow();\n        }\n        return uint64(a);\n    }\n\n    function to112(uint256 a) internal pure returns (uint112) {\n        if (a > type(uint112).max) {\n            revert ErrOverflow();\n        }\n        return uint112(a);\n    }\n\n    function to128(uint256 a) internal pure returns (uint128) {\n        if (a > type(uint128).max) {\n            revert ErrOverflow();\n        }\n        return uint128(a);\n    }\n\n    function to208(uint256 a) internal pure returns (uint208) {\n        if (a > type(uint208).max) {\n            revert ErrOverflow();\n        }\n        return uint208(a);\n    }\n\n    function to216(uint256 a) internal pure returns (uint216) {\n        if (a > type(uint216).max) {\n            revert ErrOverflow();\n        }\n        return uint216(a);\n    }\n\n    function to224(uint256 a) internal pure returns (uint224) {\n        if (a > type(uint224).max) {\n            revert ErrOverflow();\n        }\n        return uint224(a);\n    }\n}\n\nlibrary BoringMath32 {\n    function add(uint32 a, uint32 b) internal pure returns (uint32) {\n        return a + b;\n    }\n\n    function sub(uint32 a, uint32 b) internal pure returns (uint32) {\n        return a - b;\n    }\n\n    function mul(uint32 a, uint32 b) internal pure returns (uint32) {\n        return a * b;\n    }\n\n    function div(uint32 a, uint32 b) internal pure returns (uint32) {\n        return a / b;\n    }\n}\n\nlibrary BoringMath64 {\n    function add(uint64 a, uint64 b) internal pure returns (uint64) {\n        return a + b;\n    }\n\n    function sub(uint64 a, uint64 b) internal pure returns (uint64) {\n        return a - b;\n    }\n\n    function mul(uint64 a, uint64 b) internal pure returns (uint64) {\n        return a * b;\n    }\n\n    function div(uint64 a, uint64 b) internal pure returns (uint64) {\n        return a / b;\n    }\n}\n\nlibrary BoringMath112 {\n    function add(uint112 a, uint112 b) internal pure returns (uint112) {\n        return a + b;\n    }\n\n    function sub(uint112 a, uint112 b) internal pure returns (uint112) {\n        return a - b;\n    }\n\n    function mul(uint112 a, uint112 b) internal pure returns (uint112) {\n        return a * b;\n    }\n\n    function div(uint112 a, uint112 b) internal pure returns (uint112) {\n        return a / b;\n    }\n}\n\nlibrary BoringMath128 {\n    function add(uint128 a, uint128 b) internal pure returns (uint128) {\n        return a + b;\n    }\n\n    function sub(uint128 a, uint128 b) internal pure returns (uint128) {\n        return a - b;\n    }\n\n    function mul(uint128 a, uint128 b) internal pure returns (uint128) {\n        return a * b;\n    }\n\n    function div(uint128 a, uint128 b) internal pure returns (uint128) {\n        return a / b;\n    }\n}\n\nlibrary BoringMath224 {\n    function add(uint224 a, uint224 b) internal pure returns (uint224) {\n        return a + b;\n    }\n\n    function sub(uint224 a, uint224 b) internal pure returns (uint224) {\n        return a - b;\n    }\n\n    function mul(uint224 a, uint224 b) internal pure returns (uint224) {\n        return a * b;\n    }\n\n    function div(uint224 a, uint224 b) internal pure returns (uint224) {\n        return a / b;\n    }\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "/=src/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
        "BoringSolidity/=lib/BoringSolidity/contracts/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/",
        "solmate/=lib/solmate/src/",
        "utils/=utils/",
        "libraries/=src/libraries/",
        "interfaces/=src/interfaces/",
        "cauldrons/=src/cauldrons/",
        "staking/=src/staking/",
        "swappers/=src/swappers/",
        "oracles/=src/oracles/",
        "strategies/=src/strategies/",
        "tokens/=src/tokens/",
        "periphery/=src/periphery/",
        "mixins/=src/mixins/",
        "lenses/=src/lenses/",
        "surl/=lib/surl/src/",
        "solady/=lib/solady/src/",
        "forge-deploy/=lib/forge-deploy/contracts/",
        "ExcessivelySafeCall/=lib/ExcessivelySafeCall/src/",
        "safe-contracts/=lib/safe-contracts/contracts/",
        "fuzzlib/=lib/fuzzlib/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 400
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "libraries": {}
    }
  }}