creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/TrustSetup.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.25;\n\nimport {SafeERC20} from \"openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol\";\nimport {IERC20} from \"openzeppelin-contracts/token/ERC20/IERC20.sol\";\n\nimport {FixedPointMathLib} from \"solady/FixedPointMathLib.sol\";\n\nimport {IOracle} from \"./interfaces/IOracle.sol\";\nimport {IWeightedPool} from \"./interfaces/IWeightedPool.sol\";\nimport {IGauge} from \"./interfaces/IGauge.sol\";\nimport {IGoldComp} from \"./interfaces/IGoldComp.sol\";\n\nimport {IAsset} from \"./interfaces/IAsset.sol\";\nimport {IBalancerVault} from \"./interfaces/IBalancerVault.sol\";\n\n/// @title TrustSetup\n/// @author GoldenBoyz\n/// @notice Allows to invest and divest from the strategy outlined in the Compound's governance proposal in a trustless fashion\ncontract TrustSetup {\n    using SafeERC20 for IERC20;\n\n    ///////////////////////////// Data Types ///////////////////////////////\n    enum Phase {\n        NEUTRAL, // 0: no action is allowed\n        ALLOW_INVESTMENT, // 1: allows the multisig to call the invest method\n        ALLOW_DIVESTMENT // 2: allows the multisig to call the divestment methods\n\n    }\n\n    ///////////////////////////// Constants ///////////////////////////////\n    uint256 constant ORACLE_DECIMALS_BASE = 1e8;\n    uint256 constant BASE_ORACLE_DIFF_PRECISION = 1e10;\n\n    uint256 constant BASE_PRECISION = 1e18;\n    uint256 constant BASE_PRECISION_TWOFOLD = 1e36;\n\n    uint256 constant MIN_SLIPPAGE_VALUE = 9_100;\n    uint256 constant BPS = 10_000;\n\n    address public constant GOLD_MSIG = 0x941dcEA21101A385b979286CC6D6A9Bf435EB1C2;\n    address public constant COMPOUND_TIMELOCK = 0x6d903f6003cca6255D85CcA4D3B5E5146dC33925;\n    address public constant COMPTROLLER = 0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B;\n\n    IERC20 constant GOLD = IERC20(0x9DeB0fc809955b79c85e82918E8586d3b7d2695a);\n    IERC20 constant COMP = IERC20(0xc00e94Cb662C3520282E6f5717214004A7f26888);\n    IERC20 constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n\n    IGoldComp public constant GOLD_COMP = IGoldComp(0x939CED8875d1Cd75D8b9aca439e6526e9A822A48);\n\n    IWeightedPool public constant BPT = IWeightedPool(0x56bc9d9987edeC2fC6e1990e27AF4A0987b53096);\n    uint256 constant GOLD_COMP_NORMALIZED_WEIGHT = 990000000000000000;\n    uint256 constant WETH_NORMALIZED_WEIGHT = 10000000000000000;\n    uint256 constant BPT_INVARIANT_RATIO = 300000000000000000;\n\n    IGauge public constant GAUGE = IGauge(0x4DcfB8105C663F199c1a640549FC3579db4E3e65);\n\n    IOracle public constant ORACLE_COMP_ETH = IOracle(0x1B39Ee86Ec5979ba5C322b826B3ECb8C79991699);\n    uint256 constant ORACLE_COMP_ETH_HEART_BEAT = 24 hours;\n\n    IOracle public constant ORACLE_COMP_USD = IOracle(0xdbd020CAeF83eFd542f4De03e3cF0C28A4428bd5);\n    uint256 constant ORACLE_COMP_USD_HEART_BEAT = 1 hours;\n\n    IOracle public constant ORACLE_ETH_USD = IOracle(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);\n    uint256 constant ORACLE_ETH_USD_HEART_BEAT = 1 hours;\n\n    IBalancerVault public constant BALANCER_VAULT = IBalancerVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8);\n    bytes32 public constant GOLD_COMP_WETH_POOL_ID = 0x56bc9d9987edec2fc6e1990e27af4a0987b53096000200000000000000000686;\n    bytes32 public constant GOLD_POOL_ID = 0x0ec120ed63212a4cb018795b43c0b03c5919042400010000000000000000068f;\n\n    /////////////////////////////// Storage ////////////////////////////////\n    bool public divestmentQueued;\n\n    uint256 public slippageMinOut;\n\n    uint256 public wethCompOracleSwapFee;\n\n    Phase public currentPhase;\n\n    /////////////////////////////// Errors ////////////////////////////////\n    error NotCompTimelock();\n    error NotGoldenBoyzMultisig();\n\n    error NotCompBalance();\n    error NothingStakedInGauge();\n    error DivestmentGreaterThanBalance();\n    error DisproportionateExit();\n    error NoDivestmentQueued();\n\n    error MinBptLowerThanExpected();\n    error MinGoldCompLowerThanExpected();\n\n    error MisconfiguredSlippage();\n    error MisconfiguredOracleFee();\n\n    error NegativeOracleAnswer();\n    error StaleOracle();\n\n    error BuyerProtectionTriggered();\n\n    error PhaseNotMatching();\n\n    /////////////////////////////// Events ////////////////////////////////\n    event CompInvested(uint256 compAmount, uint256 bptReceived, uint256 timestampt);\n    event CompDivestedQueue(uint256 compAmount, uint256 bptWithdrawn, uint256 timestampt);\n    event CompDivestedCompleted(uint256 compAmount, uint256 timestampt);\n\n    event RewardSwapped(uint256 goldBalance, uint256 wethReceived, uint256 timestampt);\n    event WethBoughtWithComp(address indexed buyer, uint256 compAmount, uint256 wethAmount);\n\n    /////////////////////////////// Modifiers ////////////////////////////////\n    /// @notice Restricts the invocation of methods exclusively to the Compound Timelock\n    modifier onlyCompTimelock() {\n        if (msg.sender != COMPOUND_TIMELOCK) revert NotCompTimelock();\n        _;\n    }\n\n    /// @notice Restricts the invocation of methods exclusively to the GoldenBoyz multisig\n    modifier onlyGoldenBoyzMultisig() {\n        if (msg.sender != GOLD_MSIG) revert NotGoldenBoyzMultisig();\n        _;\n    }\n\n    /// @notice Verifies that Compound Timelock actually granted rights to the GoldenBoyz multisig target action\n    modifier CheckPhase(Phase expectedPhase) {\n        if (expectedPhase != currentPhase) revert PhaseNotMatching();\n        _;\n    }\n\n    /// @notice Grants unlimited approvals at deployment time to facilitate internal operations for trusted contracts\n    constructor() {\n        COMP.approve(address(GOLD_COMP), type(uint256).max);\n\n        GOLD.approve(address(BALANCER_VAULT), type(uint256).max);\n        GOLD_COMP.approve(address(BALANCER_VAULT), type(uint256).max);\n\n        BPT.approve(address(GAUGE), type(uint256).max);\n\n        // default value at deployment, it can be modified by the Compound Timelock\n        // to avoid funds being frozen on periods on high volatility\n        slippageMinOut = 9_400;\n\n        // default value at deployment is 2% given the oracle deviation threshold\n        wethCompOracleSwapFee = 10_200;\n    }\n\n    /////////////////////////////// External methods ////////////////////////////////\n\n    /// @notice Updates the current phase of the contract and grants different right to the GoldenBoyz multisig\n    /// @param _phase The new phase to be set\n    function grantPhase(Phase _phase) external onlyCompTimelock {\n        currentPhase = _phase;\n    }\n\n    /// @notice Allocates the entire idle balance of COMP within the contract into the invesment strategy\n    /// @param _expectedMinBptOffchain The minimum amount of BPT expected calculated offchain\n    function invest(uint256 _expectedMinBptOffchain)\n        external\n        onlyGoldenBoyzMultisig\n        CheckPhase(Phase.ALLOW_INVESTMENT)\n    {\n        uint256 compBalance = COMP.balanceOf(address(this));\n        if (compBalance == 0) revert NotCompBalance();\n\n        // 1:1 ratio (COMP:GOLDCOMP)\n        GOLD_COMP.deposit(compBalance);\n\n        _depositInBalancerPool(compBalance);\n\n        uint256 bptBalance = BPT.balanceOf(address(this));\n        if (bptBalance < _expectedMinBptOffchain) revert MinBptLowerThanExpected();\n\n        GAUGE.deposit(bptBalance);\n\n        emit CompInvested(compBalance, bptBalance, block.timestamp);\n    }\n\n    /// @notice Divest partial or all positions from Balancer and queue withdrawal into GOLDCOMP\n    /// @dev Given the constrainst determined by the Balancer V2 pool, at once no more than 30% of the supply should be withdrawn\n    /// @param _bptToDivest Amount of BPT to divest from the strategy\n    /// @param _minGoldCompExpected The minimum amount of GOLDCOMP expected\n    function commenceDivestment(uint256 _bptToDivest, uint256 _minGoldCompExpected)\n        external\n        onlyGoldenBoyzMultisig\n        CheckPhase(Phase.ALLOW_DIVESTMENT)\n    {\n        // strict input checks since transaction is going via Compound's Timelock\n        uint256 bptStaked = GAUGE.balanceOf(address(this));\n        if (bptStaked == 0) revert NothingStakedInGauge();\n        if (_bptToDivest > bptStaked) revert DivestmentGreaterThanBalance();\n\n        // avoids BAL#306: otherwise could bricked the divestment process\n        uint256 invariantRatio = _bptToDivest * BASE_PRECISION / BPT.getActualSupply();\n        if (invariantRatio >= BPT_INVARIANT_RATIO) revert DisproportionateExit();\n\n        // 1:1 ratio\n        GAUGE.withdraw(_bptToDivest);\n\n        _withdrawFromBalancerPool(_bptToDivest);\n\n        uint256 goldCompBalance = GOLD_COMP.balanceOf(address(this));\n        if (goldCompBalance < _minGoldCompExpected) revert MinGoldCompLowerThanExpected();\n\n        GOLD_COMP.queueWithdraw(goldCompBalance);\n\n        divestmentQueued = true;\n        emit CompDivestedQueue(goldCompBalance, _bptToDivest, block.timestamp);\n    }\n\n    /// @notice Completes the divestment by withdrawing from GOLDCOMP vault and sending COMP to the comptroller\n    /// @dev This method should be called only after commence divest method has been executed and the cooldown period has passed\n    function completeDivestment() external onlyGoldenBoyzMultisig CheckPhase(Phase.ALLOW_DIVESTMENT) {\n        if (!divestmentQueued) revert NoDivestmentQueued();\n\n        GOLD_COMP.withdraw();\n\n        uint256 compBalance = COMP.balanceOf(address(this));\n        // COMP is sent directly into comptroller\n        COMP.safeTransfer(COMPTROLLER, compBalance);\n\n        divestmentQueued = false;\n        emit CompDivestedCompleted(compBalance, block.timestamp);\n    }\n\n    /// @notice Sets the slippage for the Balancer pool operations\n    /// @param _slippageMinOut The new slippage margin\n    function setSlippageMinOut(uint256 _slippageMinOut) external onlyCompTimelock {\n        if (_slippageMinOut > BPS || _slippageMinOut < MIN_SLIPPAGE_VALUE) {\n            revert MisconfiguredSlippage();\n        }\n        slippageMinOut = _slippageMinOut;\n    }\n\n    /// @notice Sets the fee for the WETH/COMP oracle swap. Only callable by the GoldenBoyz multisig for operational speed\n    /// @param _wethCompOracleSwapFee The new fee for the swap\n    function setWethCompOracleSwapFee(uint256 _wethCompOracleSwapFee) external onlyGoldenBoyzMultisig {\n        // allows for max 2% fee\n        if (_wethCompOracleSwapFee > 12_000 || _wethCompOracleSwapFee < BPS) revert MisconfiguredOracleFee();\n        // whenever is set to 10_000, it translates to basically not having any fee for that swap operation\n        wethCompOracleSwapFee = _wethCompOracleSwapFee;\n    }\n\n    /// @notice Swaps gauge rewards for WETH. Only callable by the GoldenBoyz multisig, primarily intended to safeguard the minimum amount expected\n    /// @dev The multisig should simulate the swap and ensure the minimum amount of WETH expected is well protected calling offchain querySwap method\n    /// @param _minWethOut The minimum amount of WETH expected, calculated offchain\n    function swapRewardsForWeth(uint256 _minWethOut) external onlyGoldenBoyzMultisig {\n        GAUGE.claim_rewards();\n\n        // assumes only GOLD as reward as per specifications\n        uint256 goldBalance = GOLD.balanceOf(address(this));\n        uint256 wethReceived = _swapRewardForWeth(goldBalance, _minWethOut);\n\n        emit RewardSwapped(goldBalance, wethReceived, block.timestamp);\n    }\n\n    /// @notice The caller is swapping a specific amount of COMP tokens at the oracle price (COMP/ETH) for WETH. Permissionless\n    /// @param _compAmount The amount of COMP token being sent into the contract\n    /// @param _minOut The minimum amount of WETH expected\n    function buyWethWithComp(uint256 _compAmount, uint256 _minOut) external {\n        uint256 wethAmount = _compToWethRatio(_compAmount) * wethCompOracleSwapFee / BPS;\n        if (wethAmount < _minOut) revert BuyerProtectionTriggered();\n\n        // COMP is sent directly into comptroller\n        COMP.safeTransferFrom(msg.sender, COMPTROLLER, _compAmount);\n        WETH.safeTransfer(msg.sender, wethAmount);\n\n        emit WethBoughtWithComp(msg.sender, _compAmount, wethAmount);\n    }\n\n    /// @notice Public helper method for buying COMP with WETH and being aware of oracle latest answer\n    /// @param _compAmount The amount of COMP token to be converted into WETH\n    function getCompToWethRatio(uint256 _compAmount) public returns (uint256) {\n        return _compToWethRatio(_compAmount);\n    }\n\n    /////////////////////////////// Internal methods ////////////////////////////////\n\n    /// @param _oracle The oracle contract to be queried\n    /// @param _heartBeat Amount of seconds that can pass between oracle updates in a healthy environment\n    /// @return The latest oracle answer casted as uint256\n    function _oracleHelper(IOracle _oracle, uint256 _heartBeat) internal returns (uint256) {\n        (, int256 answer,, uint256 updatedAt,) = _oracle.latestRoundData();\n\n        if (answer < 0) revert NegativeOracleAnswer();\n        if (block.timestamp - updatedAt > _heartBeat) revert StaleOracle();\n\n        return uint256(answer);\n    }\n\n    /// @notice Internally checks the latest oracle price and convert the COMP amount into WETH ratio to facilitate the swap\n    /// @param _compAmount The amount of COMP token\n    /// @return The amount of WETH expected given the COMP amount and current oracle latest answer\n    function _compToWethRatio(uint256 _compAmount) internal returns (uint256) {\n        // COMP / ETH oracle has 18 decimals\n        return (_compAmount * _oracleHelper(ORACLE_COMP_ETH, ORACLE_COMP_ETH_HEART_BEAT)) / BASE_PRECISION;\n    }\n\n    /// @return The pool assets in the 99goldCOMP-1WETH Balancer pool\n    function _poolAssets() internal pure returns (address[] memory) {\n        address[] memory poolAssets = new address[](2);\n        poolAssets[0] = address(GOLD_COMP);\n        poolAssets[1] = address(WETH);\n\n        return poolAssets;\n    }\n\n    /// @param _goldCompBalance The amount of GOLDCOMP to be deposit into the pool\n    function _depositInBalancerPool(uint256 _goldCompBalance) internal {\n        // single sided deposit\n        uint256[] memory amountsIn = new uint256[](2);\n        amountsIn[0] = _goldCompBalance;\n\n        BALANCER_VAULT.joinPool(\n            GOLD_COMP_WETH_POOL_ID,\n            address(this),\n            address(this),\n            IBalancerVault.JoinPoolRequest({\n                assets: _poolAssets(),\n                maxAmountsIn: amountsIn,\n                userData: abi.encode(\n                    IBalancerVault.JoinKind.EXACT_TOKENS_IN_FOR_BPT_OUT, amountsIn, _calcMinBpt(_goldCompBalance)\n                ),\n                fromInternalBalance: false\n            })\n        );\n    }\n\n    /// @param _bptBalance The amount of BPT to be withdraw from the pool\n    function _withdrawFromBalancerPool(uint256 _bptBalance) internal {\n        uint256[] memory minAmountsOut = new uint256[](2);\n        // index 0 is the minimum amount of COMP expected\n        minAmountsOut[0] = _minCompOut(_bptBalance);\n\n        BALANCER_VAULT.exitPool(\n            GOLD_COMP_WETH_POOL_ID,\n            address(this),\n            address(this),\n            IBalancerVault.ExitPoolRequest({\n                assets: _poolAssets(),\n                minAmountsOut: minAmountsOut,\n                userData: abi.encode(IBalancerVault.ExitKind.EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, _bptBalance, 0),\n                toInternalBalance: false\n            })\n        );\n    }\n\n    /// @param _goldAmount The amount of GOLD to be swapped for WETH\n    /// @param _minWethOut The minimum amount of WETH expected\n    /// @return The amount of WETH received\n    function _swapRewardForWeth(uint256 _goldAmount, uint256 _minWethOut) internal returns (uint256) {\n        // only pool in mainnet with GOLD liquidity\n        // GIVEN_IN type of swap, internally in balancer vault _getAmounts returns amountOut\n        return BALANCER_VAULT.swap(\n            IBalancerVault.SingleSwap({\n                poolId: GOLD_POOL_ID,\n                kind: IBalancerVault.SwapKind.GIVEN_IN,\n                assetIn: IAsset(address(GOLD)),\n                assetOut: IAsset(address(WETH)),\n                amount: _goldAmount,\n                userData: new bytes(0)\n            }),\n            IBalancerVault.FundManagement({\n                sender: address(this),\n                fromInternalBalance: false,\n                recipient: payable(address(this)),\n                toInternalBalance: false\n            }),\n            _minWethOut,\n            block.timestamp\n        );\n    }\n\n    /// @dev Explanation at: https://docs.balancer.fi/concepts/advanced/valuing-bpt/valuing-bpt.html#weighted-pools\n    /// @return The ratio of COMP/BPT\n    function _ratioCompBpt() internal returns (uint256) {\n        // 1:1 ratio (COMP:GOLDCOMP). COMP / USD oracle has 8 decimals\n        uint256 compToUsd = _oracleHelper(ORACLE_COMP_USD, ORACLE_COMP_USD_HEART_BEAT);\n        // 1:1 ratio (ETH:WETH). ETH / USD oracle has 8 decimals\n        uint256 ethToUsd = _oracleHelper(ORACLE_ETH_USD, ORACLE_ETH_USD_HEART_BEAT);\n\n        uint256 invariantDivSupply = (BPT.getInvariant() * BASE_PRECISION) / BPT.getActualSupply();\n        uint256 productSequenceOne = uint256(\n            FixedPointMathLib.powWad(\n                int256((compToUsd * BASE_PRECISION / GOLD_COMP_NORMALIZED_WEIGHT) * BASE_ORACLE_DIFF_PRECISION),\n                int256(GOLD_COMP_NORMALIZED_WEIGHT)\n            )\n        );\n        uint256 productSequenceTwo = uint256(\n            FixedPointMathLib.powWad(\n                int256((ethToUsd * BASE_PRECISION / WETH_NORMALIZED_WEIGHT) * BASE_ORACLE_DIFF_PRECISION),\n                int256(WETH_NORMALIZED_WEIGHT)\n            )\n        );\n\n        // formula summary: bpt = invariantDivSupply * productSequenceOne * productSequenceTwo\n        uint256 bptToUsd = (invariantDivSupply * productSequenceOne * productSequenceTwo) / BASE_PRECISION_TWOFOLD;\n        return compToUsd * BASE_PRECISION / bptToUsd;\n    }\n\n    /// @param _goldCompBalance The amount of GOLDCOMP to be converted into minimum BPT expected\n    /// @return The minimum amount of BPT expected\n    function _calcMinBpt(uint256 _goldCompBalance) internal returns (uint256) {\n        uint256 ratio = _ratioCompBpt();\n        uint256 minBpt = (_goldCompBalance * ratio) / ORACLE_DECIMALS_BASE;\n\n        // use of fixed point arithmetic and the powWad operation introduces a loss of precision, causing productSequenceTwo to be slightly higher than its theoretical value.\n        // to mitigate this, we apply a more aggressive slippage margin, ensuring the minimum expected output amount is protected\n        return minBpt * slippageMinOut / BPS;\n    }\n\n    /// @param _bptBalance The amount of BPT to be converted into minimum COMP out expected\n    /// @return The minimum amount of COMP expected\n    function _minCompOut(uint256 _bptBalance) internal returns (uint256) {\n        uint256 ratio = _ratioCompBpt();\n        uint256 minComp = (_bptBalance * ORACLE_DECIMALS_BASE) / ratio;\n\n        // use of fixed point arithmetic and the powWad operation introduces a loss of precision, causing productSequenceTwo to be slightly higher than its theoretical value.\n        // to mitigate this, we apply a more aggressive slippage margin, ensuring the minimum expected output amount is protected\n        return minComp * slippageMinOut / BPS;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\nimport {IERC1363} from \"../../../interfaces/IERC1363.sol\";\nimport {Address} from \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC-20 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 Address for address;\n\n    /**\n     * @dev An operation with an ERC-20 token failed.\n     */\n    error SafeERC20FailedOperation(address token);\n\n    /**\n     * @dev Indicates a failed `decreaseAllowance` request.\n     */\n    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        forceApprove(token, spender, oldAllowance + value);\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\n     * value, non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\n        unchecked {\n            uint256 currentAllowance = token.allowance(address(this), spender);\n            if (currentAllowance < requestedDecrease) {\n                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\n            }\n            forceApprove(token, spender, currentAllowance - requestedDecrease);\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            safeTransfer(token, to, value);\n        } else if (!token.transferAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\n     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function transferFromAndCallRelaxed(\n        IERC1363 token,\n        address from,\n        address to,\n        uint256 value,\n        bytes memory data\n    ) internal {\n        if (to.code.length == 0) {\n            safeTransferFrom(token, from, to, value);\n        } else if (!token.transferFromAndCall(from, to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\n    }\n\n    /**\n     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\n     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\n     * targeting contracts.\n     *\n     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\n     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\n     * once without retrying, and relies on the returned value to be true.\n     *\n     * Reverts if the returned value is other than `true`.\n     */\n    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\n        if (to.code.length == 0) {\n            forceApprove(token, to, value);\n        } else if (!token.approveAndCall(to, value, data)) {\n            revert SafeERC20FailedOperation(address(token));\n        }\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);\n        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {\n            revert SafeERC20FailedOperation(address(token));\n        }\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     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\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 cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\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    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\n     * 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 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` 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 from, address to, uint256 value) external returns (bool);\n}\n"
      },
      "lib/solady/src/utils/FixedPointMathLib.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)\nlibrary FixedPointMathLib {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       CUSTOM ERRORS                        */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The operation failed, as the output exceeds the maximum value of uint256.\n    error ExpOverflow();\n\n    /// @dev The operation failed, as the output exceeds the maximum value of uint256.\n    error FactorialOverflow();\n\n    /// @dev The operation failed, due to an overflow.\n    error RPowOverflow();\n\n    /// @dev The mantissa is too big to fit.\n    error MantissaOverflow();\n\n    /// @dev The operation failed, due to an multiplication overflow.\n    error MulWadFailed();\n\n    /// @dev The operation failed, due to an multiplication overflow.\n    error SMulWadFailed();\n\n    /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero.\n    error DivWadFailed();\n\n    /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero.\n    error SDivWadFailed();\n\n    /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero.\n    error MulDivFailed();\n\n    /// @dev The division failed, as the denominator is zero.\n    error DivFailed();\n\n    /// @dev The full precision multiply-divide operation failed, either due\n    /// to the result being larger than 256 bits, or a division by a zero.\n    error FullMulDivFailed();\n\n    /// @dev The output is undefined, as the input is less-than-or-equal to zero.\n    error LnWadUndefined();\n\n    /// @dev The input outside the acceptable domain.\n    error OutOfDomain();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         CONSTANTS                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The scalar of ETH and most ERC20s.\n    uint256 internal constant WAD = 1e18;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*              SIMPLIFIED FIXED POINT OPERATIONS             */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded down.\n    function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.\n            if mul(y, gt(x, div(not(0), y))) {\n                mstore(0x00, 0xbac65e5b) // `MulWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := div(mul(x, y), WAD)\n        }\n    }\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded down.\n    function sMulWad(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mul(x, y)\n            // Equivalent to `require((x == 0 || z / x == y) && !(x == -1 && y == type(int256).min))`.\n            if iszero(gt(or(iszero(x), eq(sdiv(z, x), y)), lt(not(x), eq(y, shl(255, 1))))) {\n                mstore(0x00, 0xedcd4dd4) // `SMulWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := sdiv(z, WAD)\n        }\n    }\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded down, but without overflow checks.\n    function rawMulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := div(mul(x, y), WAD)\n        }\n    }\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded down, but without overflow checks.\n    function rawSMulWad(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := sdiv(mul(x, y), WAD)\n        }\n    }\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded up.\n    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.\n            if mul(y, gt(x, div(not(0), y))) {\n                mstore(0x00, 0xbac65e5b) // `MulWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))\n        }\n    }\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded up, but without overflow checks.\n    function rawMulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded down.\n    function divWad(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.\n            if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {\n                mstore(0x00, 0x7c5f487d) // `DivWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := div(mul(x, WAD), y)\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded down.\n    function sDivWad(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mul(x, WAD)\n            // Equivalent to `require(y != 0 && ((x * WAD) / WAD == x))`.\n            if iszero(and(iszero(iszero(y)), eq(sdiv(z, WAD), x))) {\n                mstore(0x00, 0x5c43740d) // `SDivWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := sdiv(mul(x, WAD), y)\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded down, but without overflow and divide by zero checks.\n    function rawDivWad(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := div(mul(x, WAD), y)\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded down, but without overflow and divide by zero checks.\n    function rawSDivWad(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := sdiv(mul(x, WAD), y)\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded up.\n    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.\n            if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {\n                mstore(0x00, 0x7c5f487d) // `DivWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y))\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded up, but without overflow and divide by zero checks.\n    function rawDivWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y))\n        }\n    }\n\n    /// @dev Equivalent to `x` to the power of `y`.\n    /// because `x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)`.\n    function powWad(int256 x, int256 y) internal pure returns (int256) {\n        // Using `ln(x)` means `x` must be greater than 0.\n        return expWad((lnWad(x) * y) / int256(WAD));\n    }\n\n    /// @dev Returns `exp(x)`, denominated in `WAD`.\n    /// Credit to Remco Bloemen under MIT license: https://2π.com/22/exp-ln\n    function expWad(int256 x) internal pure returns (int256 r) {\n        unchecked {\n            // When the result is less than 0.5 we return zero.\n            // This happens when `x <= (log(1e-18) * 1e18) ~ -4.15e19`.\n            if (x <= -41446531673892822313) return r;\n\n            /// @solidity memory-safe-assembly\n            assembly {\n                // When the result is greater than `(2**255 - 1) / 1e18` we can not represent it as\n                // an int. This happens when `x >= floor(log((2**255 - 1) / 1e18) * 1e18) ≈ 135`.\n                if iszero(slt(x, 135305999368893231589)) {\n                    mstore(0x00, 0xa37bfec9) // `ExpOverflow()`.\n                    revert(0x1c, 0x04)\n                }\n            }\n\n            // `x` is now in the range `(-42, 136) * 1e18`. Convert to `(-42, 136) * 2**96`\n            // for more intermediate precision and a binary basis. This base conversion\n            // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.\n            x = (x << 78) / 5 ** 18;\n\n            // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers\n            // of two such that exp(x) = exp(x') * 2**k, where k is an integer.\n            // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).\n            int256 k = ((x << 96) / 54916777467707473351141471128 + 2 ** 95) >> 96;\n            x = x - k * 54916777467707473351141471128;\n\n            // `k` is in the range `[-61, 195]`.\n\n            // Evaluate using a (6, 7)-term rational approximation.\n            // `p` is made monic, we'll multiply by a scale factor later.\n            int256 y = x + 1346386616545796478920950773328;\n            y = ((y * x) >> 96) + 57155421227552351082224309758442;\n            int256 p = y + x - 94201549194550492254356042504812;\n            p = ((p * y) >> 96) + 28719021644029726153956944680412240;\n            p = p * x + (4385272521454847904659076985693276 << 96);\n\n            // We leave `p` in `2**192` basis so we don't need to scale it back up for the division.\n            int256 q = x - 2855989394907223263936484059900;\n            q = ((q * x) >> 96) + 50020603652535783019961831881945;\n            q = ((q * x) >> 96) - 533845033583426703283633433725380;\n            q = ((q * x) >> 96) + 3604857256930695427073651918091429;\n            q = ((q * x) >> 96) - 14423608567350463180887372962807573;\n            q = ((q * x) >> 96) + 26449188498355588339934803723976023;\n\n            /// @solidity memory-safe-assembly\n            assembly {\n                // Div in assembly because solidity adds a zero check despite the unchecked.\n                // The q polynomial won't have zeros in the domain as all its roots are complex.\n                // No scaling is necessary because p is already `2**96` too large.\n                r := sdiv(p, q)\n            }\n\n            // r should be in the range `(0.09, 0.25) * 2**96`.\n\n            // We now need to multiply r by:\n            // - The scale factor `s ≈ 6.031367120`.\n            // - The `2**k` factor from the range reduction.\n            // - The `1e18 / 2**96` factor for base conversion.\n            // We do this all at once, with an intermediate result in `2**213`\n            // basis, so the final right shift is always by a positive amount.\n            r = int256(\n                (uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)\n            );\n        }\n    }\n\n    /// @dev Returns `ln(x)`, denominated in `WAD`.\n    /// Credit to Remco Bloemen under MIT license: https://2π.com/22/exp-ln\n    function lnWad(int256 x) internal pure returns (int256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // We want to convert `x` from `10**18` fixed point to `2**96` fixed point.\n            // We do this by multiplying by `2**96 / 10**18`. But since\n            // `ln(x * C) = ln(x) + ln(C)`, we can simply do nothing here\n            // and add `ln(2**96 / 10**18)` at the end.\n\n            // Compute `k = log2(x) - 96`, `r = 159 - k = 255 - log2(x) = 255 ^ log2(x)`.\n            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffff, shr(r, x))))\n            r := or(r, shl(3, lt(0xff, shr(r, x))))\n            // We place the check here for more optimal stack operations.\n            if iszero(sgt(x, 0)) {\n                mstore(0x00, 0x1615e638) // `LnWadUndefined()`.\n                revert(0x1c, 0x04)\n            }\n            // forgefmt: disable-next-item\n            r := xor(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),\n                0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff))\n\n            // Reduce range of x to (1, 2) * 2**96\n            // ln(2^k * x) = k * ln(2) + ln(x)\n            x := shr(159, shl(r, x))\n\n            // Evaluate using a (8, 8)-term rational approximation.\n            // `p` is made monic, we will multiply by a scale factor later.\n            // forgefmt: disable-next-item\n            let p := sub( // This heavily nested expression is to avoid stack-too-deep for via-ir.\n                sar(96, mul(add(43456485725739037958740375743393,\n                sar(96, mul(add(24828157081833163892658089445524,\n                sar(96, mul(add(3273285459638523848632254066296,\n                    x), x))), x))), x)), 11111509109440967052023855526967)\n            p := sub(sar(96, mul(p, x)), 45023709667254063763336534515857)\n            p := sub(sar(96, mul(p, x)), 14706773417378608786704636184526)\n            p := sub(mul(p, x), shl(96, 795164235651350426258249787498))\n            // We leave `p` in `2**192` basis so we don't need to scale it back up for the division.\n\n            // `q` is monic by convention.\n            let q := add(5573035233440673466300451813936, x)\n            q := add(71694874799317883764090561454958, sar(96, mul(x, q)))\n            q := add(283447036172924575727196451306956, sar(96, mul(x, q)))\n            q := add(401686690394027663651624208769553, sar(96, mul(x, q)))\n            q := add(204048457590392012362485061816622, sar(96, mul(x, q)))\n            q := add(31853899698501571402653359427138, sar(96, mul(x, q)))\n            q := add(909429971244387300277376558375, sar(96, mul(x, q)))\n\n            // `p / q` is in the range `(0, 0.125) * 2**96`.\n\n            // Finalization, we need to:\n            // - Multiply by the scale factor `s = 5.549…`.\n            // - Add `ln(2**96 / 10**18)`.\n            // - Add `k * ln(2)`.\n            // - Multiply by `10**18 / 2**96 = 5**18 >> 78`.\n\n            // The q polynomial is known not to have zeros in the domain.\n            // No scaling required because p is already `2**96` too large.\n            p := sdiv(p, q)\n            // Multiply by the scaling factor: `s * 5**18 * 2**96`, base is now `5**18 * 2**192`.\n            p := mul(1677202110996718588342820967067443963516166, p)\n            // Add `ln(2) * k * 5**18 * 2**192`.\n            // forgefmt: disable-next-item\n            p := add(mul(16597577552685614221487285958193947469193820559219878177908093499208371, sub(159, r)), p)\n            // Add `ln(2**96 / 10**18) * 5**18 * 2**192`.\n            p := add(600920179829731861736702779321621459595472258049074101567377883020018308, p)\n            // Base conversion: mul `2**18 / 2**192`.\n            r := sar(174, p)\n        }\n    }\n\n    /// @dev Returns `W_0(x)`, denominated in `WAD`.\n    /// See: https://en.wikipedia.org/wiki/Lambert_W_function\n    /// a.k.a. Product log function. This is an approximation of the principal branch.\n    function lambertW0Wad(int256 x) internal pure returns (int256 w) {\n        // forgefmt: disable-next-item\n        unchecked {\n            if ((w = x) <= -367879441171442322) revert OutOfDomain(); // `x` less than `-1/e`.\n            int256 wad = int256(WAD);\n            int256 p = x;\n            uint256 c; // Whether we need to avoid catastrophic cancellation.\n            uint256 i = 4; // Number of iterations.\n            if (w <= 0x1ffffffffffff) {\n                if (-0x4000000000000 <= w) {\n                    i = 1; // Inputs near zero only take one step to converge.\n                } else if (w <= -0x3ffffffffffffff) {\n                    i = 32; // Inputs near `-1/e` take very long to converge.\n                }\n            } else if (w >> 63 == 0) {\n                /// @solidity memory-safe-assembly\n                assembly {\n                    // Inline log2 for more performance, since the range is small.\n                    let v := shr(49, w)\n                    let l := shl(3, lt(0xff, v))\n                    l := add(or(l, byte(and(0x1f, shr(shr(l, v), 0x8421084210842108cc6318c6db6d54be)),\n                        0x0706060506020504060203020504030106050205030304010505030400000000)), 49)\n                    w := sdiv(shl(l, 7), byte(sub(l, 31), 0x0303030303030303040506080c13))\n                    c := gt(l, 60)\n                    i := add(2, add(gt(l, 53), c))\n                }\n            } else {\n                int256 ll = lnWad(w = lnWad(w));\n                /// @solidity memory-safe-assembly\n                assembly {\n                    // `w = ln(x) - ln(ln(x)) + b * ln(ln(x)) / ln(x)`.\n                    w := add(sdiv(mul(ll, 1023715080943847266), w), sub(w, ll))\n                    i := add(3, iszero(shr(68, x)))\n                    c := iszero(shr(143, x))\n                }\n                if (c == 0) {\n                    do { // If `x` is big, use Newton's so that intermediate values won't overflow.\n                        int256 e = expWad(w);\n                        /// @solidity memory-safe-assembly\n                        assembly {\n                            let t := mul(w, div(e, wad))\n                            w := sub(w, sdiv(sub(t, x), div(add(e, t), wad)))\n                        }\n                        if (p <= w) break;\n                        p = w;\n                    } while (--i != 0);\n                    /// @solidity memory-safe-assembly\n                    assembly {\n                        w := sub(w, sgt(w, 2))\n                    }\n                    return w;\n                }\n            }\n            do { // Otherwise, use Halley's for faster convergence.\n                int256 e = expWad(w);\n                /// @solidity memory-safe-assembly\n                assembly {\n                    let t := add(w, wad)\n                    let s := sub(mul(w, e), mul(x, wad))\n                    w := sub(w, sdiv(mul(s, wad), sub(mul(e, t), sdiv(mul(add(t, wad), s), add(t, t)))))\n                }\n                if (p <= w) break;\n                p = w;\n            } while (--i != c);\n            /// @solidity memory-safe-assembly\n            assembly {\n                w := sub(w, sgt(w, 2))\n            }\n            // For certain ranges of `x`, we'll use the quadratic-rate recursive formula of\n            // R. Iacono and J.P. Boyd for the last iteration, to avoid catastrophic cancellation.\n            if (c != 0) {\n                int256 t = w | 1;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    x := sdiv(mul(x, wad), t)\n                }\n                x = (t * (wad + lnWad(x)));\n                /// @solidity memory-safe-assembly\n                assembly {\n                    w := sdiv(x, add(wad, t))\n                }\n            }\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                  GENERAL NUMBER UTILITIES                  */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Calculates `floor(x * y / d)` with full precision.\n    /// Throws if result overflows a uint256 or when `d` is zero.\n    /// Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv\n    function fullMulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // 512-bit multiply `[p1 p0] = x * y`.\n            // Compute the product mod `2**256` and mod `2**256 - 1`\n            // then use the Chinese Remainder Theorem to reconstruct\n            // the 512 bit result. The result is stored in two 256\n            // variables such that `product = p1 * 2**256 + p0`.\n\n            // Temporarily use `result` as `p0` to save gas.\n            result := mul(x, y) // Lower 256 bits of `x * y`.\n            for {} 1 {} {\n                // If overflows.\n                if iszero(mul(or(iszero(x), eq(div(result, x), y)), d)) {\n                    let mm := mulmod(x, y, not(0))\n                    let p1 := sub(mm, add(result, lt(mm, result))) // Upper 256 bits of `x * y`.\n\n                    /*------------------- 512 by 256 division --------------------*/\n\n                    // Make division exact by subtracting the remainder from `[p1 p0]`.\n                    let r := mulmod(x, y, d) // Compute remainder using mulmod.\n                    let t := and(d, sub(0, d)) // The least significant bit of `d`. `t >= 1`.\n                    // Make sure the result is less than `2**256`. Also prevents `d == 0`.\n                    // Placing the check here seems to give more optimal stack operations.\n                    if iszero(gt(d, p1)) {\n                        mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.\n                        revert(0x1c, 0x04)\n                    }\n                    d := div(d, t) // Divide `d` by `t`, which is a power of two.\n                    // Invert `d mod 2**256`\n                    // Now that `d` is an odd number, it has an inverse\n                    // modulo `2**256` such that `d * inv = 1 mod 2**256`.\n                    // Compute the inverse by starting with a seed that is correct\n                    // correct for four bits. That is, `d * inv = 1 mod 2**4`.\n                    let inv := xor(2, mul(3, d))\n                    // Now use Newton-Raphson iteration to improve the precision.\n                    // Thanks to Hensel's lifting lemma, this also works in modular\n                    // arithmetic, doubling the correct bits in each step.\n                    inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**8\n                    inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**16\n                    inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**32\n                    inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**64\n                    inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**128\n                    result :=\n                        mul(\n                            // Divide [p1 p0] by the factors of two.\n                            // Shift in bits from `p1` into `p0`. For this we need\n                            // to flip `t` such that it is `2**256 / t`.\n                            or(\n                                mul(sub(p1, gt(r, result)), add(div(sub(0, t), t), 1)),\n                                div(sub(result, r), t)\n                            ),\n                            mul(sub(2, mul(d, inv)), inv) // inverse mod 2**256\n                        )\n                    break\n                }\n                result := div(result, d)\n                break\n            }\n        }\n    }\n\n    /// @dev Calculates `floor(x * y / d)` with full precision, rounded up.\n    /// Throws if result overflows a uint256 or when `d` is zero.\n    /// Credit to Uniswap-v3-core under MIT license:\n    /// https://github.com/Uniswap/v3-core/blob/main/contracts/libraries/FullMath.sol\n    function fullMulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {\n        result = fullMulDiv(x, y, d);\n        /// @solidity memory-safe-assembly\n        assembly {\n            if mulmod(x, y, d) {\n                result := add(result, 1)\n                if iszero(result) {\n                    mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.\n                    revert(0x1c, 0x04)\n                }\n            }\n        }\n    }\n\n    /// @dev Returns `floor(x * y / d)`.\n    /// Reverts if `x * y` overflows, or `d` is zero.\n    function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mul(x, y)\n            // Equivalent to `require(d != 0 && (y == 0 || x <= type(uint256).max / y))`.\n            if iszero(mul(or(iszero(x), eq(div(z, x), y)), d)) {\n                mstore(0x00, 0xad251c27) // `MulDivFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := div(z, d)\n        }\n    }\n\n    /// @dev Returns `ceil(x * y / d)`.\n    /// Reverts if `x * y` overflows, or `d` is zero.\n    function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mul(x, y)\n            // Equivalent to `require(d != 0 && (y == 0 || x <= type(uint256).max / y))`.\n            if iszero(mul(or(iszero(x), eq(div(z, x), y)), d)) {\n                mstore(0x00, 0xad251c27) // `MulDivFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := add(iszero(iszero(mod(z, d))), div(z, d))\n        }\n    }\n\n    /// @dev Returns `ceil(x / d)`.\n    /// Reverts if `d` is zero.\n    function divUp(uint256 x, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(d) {\n                mstore(0x00, 0x65244e4e) // `DivFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := add(iszero(iszero(mod(x, d))), div(x, d))\n        }\n    }\n\n    /// @dev Returns `max(0, x - y)`.\n    function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mul(gt(x, y), sub(x, y))\n        }\n    }\n\n    /// @dev Exponentiate `x` to `y` by squaring, denominated in base `b`.\n    /// Reverts if the computation overflows.\n    function rpow(uint256 x, uint256 y, uint256 b) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mul(b, iszero(y)) // `0 ** 0 = 1`. Otherwise, `0 ** n = 0`.\n            if x {\n                z := xor(b, mul(xor(b, x), and(y, 1))) // `z = isEven(y) ? scale : x`\n                let half := shr(1, b) // Divide `b` by 2.\n                // Divide `y` by 2 every iteration.\n                for { y := shr(1, y) } y { y := shr(1, y) } {\n                    let xx := mul(x, x) // Store x squared.\n                    let xxRound := add(xx, half) // Round to the nearest number.\n                    // Revert if `xx + half` overflowed, or if `x ** 2` overflows.\n                    if or(lt(xxRound, xx), shr(128, x)) {\n                        mstore(0x00, 0x49f7642b) // `RPowOverflow()`.\n                        revert(0x1c, 0x04)\n                    }\n                    x := div(xxRound, b) // Set `x` to scaled `xxRound`.\n                    // If `y` is odd:\n                    if and(y, 1) {\n                        let zx := mul(z, x) // Compute `z * x`.\n                        let zxRound := add(zx, half) // Round to the nearest number.\n                        // If `z * x` overflowed or `zx + half` overflowed:\n                        if or(xor(div(zx, x), z), lt(zxRound, zx)) {\n                            // Revert if `x` is non-zero.\n                            if iszero(iszero(x)) {\n                                mstore(0x00, 0x49f7642b) // `RPowOverflow()`.\n                                revert(0x1c, 0x04)\n                            }\n                        }\n                        z := div(zxRound, b) // Return properly scaled `zxRound`.\n                    }\n                }\n            }\n        }\n    }\n\n    /// @dev Returns the square root of `x`.\n    function sqrt(uint256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`.\n            z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n            // Let `y = x / 2**r`. We check `y >= 2**(k + 8)`\n            // but shift right by `k` bits to ensure that if `x >= 256`, then `y >= 256`.\n            let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffffff, shr(r, x))))\n            z := shl(shr(1, r), z)\n\n            // Goal was to get `z*z*y` within a small factor of `x`. More iterations could\n            // get y in a tighter range. Currently, we will have y in `[256, 256*(2**16))`.\n            // We ensured `y >= 256` so that the relative difference between `y` and `y+1` is small.\n            // That's not possible if `x < 256` but we can just verify those cases exhaustively.\n\n            // Now, `z*z*y <= x < z*z*(y+1)`, and `y <= 2**(16+8)`, and either `y >= 256`, or `x < 256`.\n            // Correctness can be checked exhaustively for `x < 256`, so we assume `y >= 256`.\n            // Then `z*sqrt(y)` is within `sqrt(257)/sqrt(256)` of `sqrt(x)`, or about 20bps.\n\n            // For `s` in the range `[1/256, 256]`, the estimate `f(s) = (181/1024) * (s+1)`\n            // is in the range `(1/2.84 * sqrt(s), 2.84 * sqrt(s))`,\n            // with largest error when `s = 1` and when `s = 256` or `1/256`.\n\n            // Since `y` is in `[256, 256*(2**16))`, let `a = y/65536`, so that `a` is in `[1/256, 256)`.\n            // Then we can estimate `sqrt(y)` using\n            // `sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2**18`.\n\n            // There is no overflow risk here since `y < 2**136` after the first branch above.\n            z := shr(18, mul(z, add(shr(r, x), 65536))) // A `mul()` is saved from starting `z` at 181.\n\n            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n\n            // If `x+1` is a perfect square, the Babylonian method cycles between\n            // `floor(sqrt(x))` and `ceil(sqrt(x))`. This statement ensures we return floor.\n            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n            z := sub(z, lt(div(x, z), z))\n        }\n    }\n\n    /// @dev Returns the cube root of `x`.\n    /// Credit to bout3fiddy and pcaversaccio under AGPLv3 license:\n    /// https://github.com/pcaversaccio/snekmate/blob/main/src/utils/Math.vy\n    function cbrt(uint256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffff, shr(r, x))))\n            r := or(r, shl(3, lt(0xff, shr(r, x))))\n\n            z := div(shl(div(r, 3), shl(lt(0xf, shr(r, x)), 0xf)), xor(7, mod(r, 3)))\n\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n\n            z := sub(z, lt(div(x, mul(z, z)), z))\n        }\n    }\n\n    /// @dev Returns the square root of `x`, denominated in `WAD`.\n    function sqrtWad(uint256 x) internal pure returns (uint256 z) {\n        unchecked {\n            z = 10 ** 9;\n            if (x <= type(uint256).max / 10 ** 36 - 1) {\n                x *= 10 ** 18;\n                z = 1;\n            }\n            z *= sqrt(x);\n        }\n    }\n\n    /// @dev Returns the cube root of `x`, denominated in `WAD`.\n    function cbrtWad(uint256 x) internal pure returns (uint256 z) {\n        unchecked {\n            z = 10 ** 12;\n            if (x <= (type(uint256).max / 10 ** 36) * 10 ** 18 - 1) {\n                if (x >= type(uint256).max / 10 ** 36) {\n                    x *= 10 ** 18;\n                    z = 10 ** 6;\n                } else {\n                    x *= 10 ** 36;\n                    z = 1;\n                }\n            }\n            z *= cbrt(x);\n        }\n    }\n\n    /// @dev Returns the factorial of `x`.\n    function factorial(uint256 x) internal pure returns (uint256 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(lt(x, 58)) {\n                mstore(0x00, 0xaba0f2a2) // `FactorialOverflow()`.\n                revert(0x1c, 0x04)\n            }\n            for { result := 1 } x { x := sub(x, 1) } { result := mul(result, x) }\n        }\n    }\n\n    /// @dev Returns the log2 of `x`.\n    /// Equivalent to computing the index of the most significant bit (MSB) of `x`.\n    /// Returns 0 if `x` is zero.\n    function log2(uint256 x) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffff, shr(r, x))))\n            r := or(r, shl(3, lt(0xff, shr(r, x))))\n            // forgefmt: disable-next-item\n            r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),\n                0x0706060506020504060203020504030106050205030304010505030400000000))\n        }\n    }\n\n    /// @dev Returns the log2 of `x`, rounded up.\n    /// Returns 0 if `x` is zero.\n    function log2Up(uint256 x) internal pure returns (uint256 r) {\n        r = log2(x);\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := add(r, lt(shl(r, 1), x))\n        }\n    }\n\n    /// @dev Returns the log10 of `x`.\n    /// Returns 0 if `x` is zero.\n    function log10(uint256 x) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(lt(x, 100000000000000000000000000000000000000)) {\n                x := div(x, 100000000000000000000000000000000000000)\n                r := 38\n            }\n            if iszero(lt(x, 100000000000000000000)) {\n                x := div(x, 100000000000000000000)\n                r := add(r, 20)\n            }\n            if iszero(lt(x, 10000000000)) {\n                x := div(x, 10000000000)\n                r := add(r, 10)\n            }\n            if iszero(lt(x, 100000)) {\n                x := div(x, 100000)\n                r := add(r, 5)\n            }\n            r := add(r, add(gt(x, 9), add(gt(x, 99), add(gt(x, 999), gt(x, 9999)))))\n        }\n    }\n\n    /// @dev Returns the log10 of `x`, rounded up.\n    /// Returns 0 if `x` is zero.\n    function log10Up(uint256 x) internal pure returns (uint256 r) {\n        r = log10(x);\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := add(r, lt(exp(10, r), x))\n        }\n    }\n\n    /// @dev Returns the log256 of `x`.\n    /// Returns 0 if `x` is zero.\n    function log256(uint256 x) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffff, shr(r, x))))\n            r := or(shr(3, r), lt(0xff, shr(r, x)))\n        }\n    }\n\n    /// @dev Returns the log256 of `x`, rounded up.\n    /// Returns 0 if `x` is zero.\n    function log256Up(uint256 x) internal pure returns (uint256 r) {\n        r = log256(x);\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := add(r, lt(shl(shl(3, r), 1), x))\n        }\n    }\n\n    /// @dev Returns the scientific notation format `mantissa * 10 ** exponent` of `x`.\n    /// Useful for compressing prices (e.g. using 25 bit mantissa and 7 bit exponent).\n    function sci(uint256 x) internal pure returns (uint256 mantissa, uint256 exponent) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mantissa := x\n            if mantissa {\n                if iszero(mod(mantissa, 1000000000000000000000000000000000)) {\n                    mantissa := div(mantissa, 1000000000000000000000000000000000)\n                    exponent := 33\n                }\n                if iszero(mod(mantissa, 10000000000000000000)) {\n                    mantissa := div(mantissa, 10000000000000000000)\n                    exponent := add(exponent, 19)\n                }\n                if iszero(mod(mantissa, 1000000000000)) {\n                    mantissa := div(mantissa, 1000000000000)\n                    exponent := add(exponent, 12)\n                }\n                if iszero(mod(mantissa, 1000000)) {\n                    mantissa := div(mantissa, 1000000)\n                    exponent := add(exponent, 6)\n                }\n                if iszero(mod(mantissa, 10000)) {\n                    mantissa := div(mantissa, 10000)\n                    exponent := add(exponent, 4)\n                }\n                if iszero(mod(mantissa, 100)) {\n                    mantissa := div(mantissa, 100)\n                    exponent := add(exponent, 2)\n                }\n                if iszero(mod(mantissa, 10)) {\n                    mantissa := div(mantissa, 10)\n                    exponent := add(exponent, 1)\n                }\n            }\n        }\n    }\n\n    /// @dev Convenience function for packing `x` into a smaller number using `sci`.\n    /// The `mantissa` will be in bits [7..255] (the upper 249 bits).\n    /// The `exponent` will be in bits [0..6] (the lower 7 bits).\n    /// Use `SafeCastLib` to safely ensure that the `packed` number is small\n    /// enough to fit in the desired unsigned integer type:\n    /// ```\n    ///     uint32 packed = SafeCastLib.toUint32(FixedPointMathLib.packSci(777 ether));\n    /// ```\n    function packSci(uint256 x) internal pure returns (uint256 packed) {\n        (x, packed) = sci(x); // Reuse for `mantissa` and `exponent`.\n        /// @solidity memory-safe-assembly\n        assembly {\n            if shr(249, x) {\n                mstore(0x00, 0xce30380c) // `MantissaOverflow()`.\n                revert(0x1c, 0x04)\n            }\n            packed := or(shl(7, x), packed)\n        }\n    }\n\n    /// @dev Convenience function for unpacking a packed number from `packSci`.\n    function unpackSci(uint256 packed) internal pure returns (uint256 unpacked) {\n        unchecked {\n            unpacked = (packed >> 7) * 10 ** (packed & 0x7f);\n        }\n    }\n\n    /// @dev Returns the average of `x` and `y`.\n    function avg(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        unchecked {\n            z = (x & y) + ((x ^ y) >> 1);\n        }\n    }\n\n    /// @dev Returns the average of `x` and `y`.\n    function avg(int256 x, int256 y) internal pure returns (int256 z) {\n        unchecked {\n            z = (x >> 1) + (y >> 1) + (x & y & 1);\n        }\n    }\n\n    /// @dev Returns the absolute value of `x`.\n    function abs(int256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(sar(255, x), add(sar(255, x), x))\n        }\n    }\n\n    /// @dev Returns the absolute distance between `x` and `y`.\n    function dist(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(mul(xor(sub(y, x), sub(x, y)), gt(x, y)), sub(y, x))\n        }\n    }\n\n    /// @dev Returns the absolute distance between `x` and `y`.\n    function dist(int256 x, int256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(mul(xor(sub(y, x), sub(x, y)), sgt(x, y)), sub(y, x))\n        }\n    }\n\n    /// @dev Returns the minimum of `x` and `y`.\n    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, y), lt(y, x)))\n        }\n    }\n\n    /// @dev Returns the minimum of `x` and `y`.\n    function min(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, y), slt(y, x)))\n        }\n    }\n\n    /// @dev Returns the maximum of `x` and `y`.\n    function max(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, y), gt(y, x)))\n        }\n    }\n\n    /// @dev Returns the maximum of `x` and `y`.\n    function max(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, y), sgt(y, x)))\n        }\n    }\n\n    /// @dev Returns `x`, bounded to `minValue` and `maxValue`.\n    function clamp(uint256 x, uint256 minValue, uint256 maxValue)\n        internal\n        pure\n        returns (uint256 z)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, minValue), gt(minValue, x)))\n            z := xor(z, mul(xor(z, maxValue), lt(maxValue, z)))\n        }\n    }\n\n    /// @dev Returns `x`, bounded to `minValue` and `maxValue`.\n    function clamp(int256 x, int256 minValue, int256 maxValue) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, minValue), sgt(minValue, x)))\n            z := xor(z, mul(xor(z, maxValue), slt(maxValue, z)))\n        }\n    }\n\n    /// @dev Returns greatest common divisor of `x` and `y`.\n    function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            for { z := x } y {} {\n                let t := y\n                y := mod(z, y)\n                z := t\n            }\n        }\n    }\n\n    /// @dev Returns `a + (b - a) * (t - begin) / (end - begin)`,\n    /// with `t` clamped between `begin` and `end` (inclusive).\n    /// Agnostic to the order of (`a`, `b`) and (`end`, `begin`).\n    /// Reverts if `begin` equals `end` (due to division by zero).\n    function lerp(uint256 a, uint256 b, uint256 t, uint256 begin, uint256 end)\n        internal\n        pure\n        returns (uint256)\n    {\n        if (begin >= end) {\n            t = ~t;\n            begin = ~begin;\n            end = ~end;\n        }\n        if (t <= begin) return a;\n        if (t >= end) return b;\n        unchecked {\n            if (b >= a) return a + fullMulDiv(b - a, t - begin, end - begin);\n            return a - fullMulDiv(a - b, t - begin, end - begin);\n        }\n    }\n\n    /// @dev Returns `a + (b - a) * (t - begin) / (end - begin)`.\n    /// with `t` clamped between `begin` and `end` (inclusive).\n    /// Agnostic to the order of (`a`, `b`) and (`end`, `begin`).\n    /// Reverts if `begin` equals `end` (due to division by zero).\n    function lerp(int256 a, int256 b, int256 t, int256 begin, int256 end)\n        internal\n        pure\n        returns (int256)\n    {\n        if (begin >= end) {\n            t = int256(~uint256(t));\n            begin = int256(~uint256(begin));\n            end = int256(~uint256(end));\n        }\n        if (t <= begin) return a;\n        if (t >= end) return b;\n        // forgefmt: disable-next-item\n        unchecked {\n            if (b >= a) return int256(uint256(a) + fullMulDiv(uint256(b) - uint256(a),\n                uint256(t) - uint256(begin), uint256(end) - uint256(begin)));\n            return int256(uint256(a) - fullMulDiv(uint256(a) - uint256(b),\n                uint256(t) - uint256(begin), uint256(end) - uint256(begin)));\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   RAW NUMBER OPERATIONS                    */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns `x + y`, without checking for overflow.\n    function rawAdd(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        unchecked {\n            z = x + y;\n        }\n    }\n\n    /// @dev Returns `x + y`, without checking for overflow.\n    function rawAdd(int256 x, int256 y) internal pure returns (int256 z) {\n        unchecked {\n            z = x + y;\n        }\n    }\n\n    /// @dev Returns `x - y`, without checking for underflow.\n    function rawSub(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        unchecked {\n            z = x - y;\n        }\n    }\n\n    /// @dev Returns `x - y`, without checking for underflow.\n    function rawSub(int256 x, int256 y) internal pure returns (int256 z) {\n        unchecked {\n            z = x - y;\n        }\n    }\n\n    /// @dev Returns `x * y`, without checking for overflow.\n    function rawMul(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        unchecked {\n            z = x * y;\n        }\n    }\n\n    /// @dev Returns `x * y`, without checking for overflow.\n    function rawMul(int256 x, int256 y) internal pure returns (int256 z) {\n        unchecked {\n            z = x * y;\n        }\n    }\n\n    /// @dev Returns `x / y`, returning 0 if `y` is zero.\n    function rawDiv(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := div(x, y)\n        }\n    }\n\n    /// @dev Returns `x / y`, returning 0 if `y` is zero.\n    function rawSDiv(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := sdiv(x, y)\n        }\n    }\n\n    /// @dev Returns `x % y`, returning 0 if `y` is zero.\n    function rawMod(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mod(x, y)\n        }\n    }\n\n    /// @dev Returns `x % y`, returning 0 if `y` is zero.\n    function rawSMod(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := smod(x, y)\n        }\n    }\n\n    /// @dev Returns `(x + y) % d`, return 0 if `d` if zero.\n    function rawAddMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := addmod(x, y, d)\n        }\n    }\n\n    /// @dev Returns `(x * y) % d`, return 0 if `d` if zero.\n    function rawMulMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mulmod(x, y, d)\n        }\n    }\n}\n"
      },
      "src/interfaces/IOracle.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.25;\n\ninterface IOracle {\n    function latestRoundData() external returns (uint80, int256, uint256, uint256, uint80);\n}\n"
      },
      "src/interfaces/IWeightedPool.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.25;\n\nimport {IERC20} from \"openzeppelin-contracts/token/ERC20/IERC20.sol\";\n\ninterface IWeightedPool is IERC20 {\n    function getInvariant() external view returns (uint256);\n\n    function getActualSupply() external view returns (uint256);\n}\n"
      },
      "src/interfaces/IGauge.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.25;\n\ninterface IGauge {\n    function balanceOf(address) external returns (uint256);\n\n    function claimable_reward(address, address) external view returns (uint256);\n\n    function claim_rewards() external;\n\n    function deposit(uint256) external;\n\n    function totalSupply() external returns (uint256);\n\n    function withdraw(uint256) external;\n}\n"
      },
      "src/interfaces/IGoldComp.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.25;\n\ninterface IGoldComp {\n    function approve(address, uint256) external;\n\n    function balanceOf(address) external returns (uint256);\n\n    function daysToWait() external view returns (uint256);\n\n    function deposit(uint256) external;\n\n    function queueWithdraw(uint256 _amount) external;\n\n    function queuedWithdrawals(address, uint256)\n        external\n        view\n        returns (uint256 amount, uint256 timestamp, uint256 releaseTimestamp, bool withdrawn);\n\n    function withdraw() external;\n}\n"
      },
      "src/interfaces/IAsset.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.25;\n\ninterface IAsset {}\n"
      },
      "src/interfaces/IBalancerVault.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.25;\n\nimport {IAsset} from \"./IAsset.sol\";\n\ninterface IBalancerVault {\n    enum JoinKind {\n        INIT,\n        EXACT_TOKENS_IN_FOR_BPT_OUT,\n        TOKEN_IN_FOR_EXACT_BPT_OUT,\n        ALL_TOKENS_IN_FOR_EXACT_BPT_OUT\n    }\n\n    enum ExitKind {\n        EXACT_BPT_IN_FOR_ONE_TOKEN_OUT\n    }\n\n    enum SwapKind {\n        GIVEN_IN,\n        GIVEN_OUT\n    }\n\n    struct SingleSwap {\n        bytes32 poolId;\n        SwapKind kind;\n        IAsset assetIn;\n        IAsset assetOut;\n        uint256 amount;\n        bytes userData;\n    }\n\n    struct FundManagement {\n        address sender;\n        bool fromInternalBalance;\n        address payable recipient;\n        bool toInternalBalance;\n    }\n\n    struct JoinPoolRequest {\n        address[] assets;\n        uint256[] maxAmountsIn;\n        bytes userData;\n        bool fromInternalBalance;\n    }\n\n    struct ExitPoolRequest {\n        address[] assets;\n        uint256[] minAmountsOut;\n        bytes userData;\n        bool toInternalBalance;\n    }\n\n    function joinPool(bytes32 poolId, address sender, address recipient, JoinPoolRequest memory request) external;\n\n    function exitPool(bytes32 poolId, address sender, address recipient, ExitPoolRequest memory request) external;\n\n    function swap(SingleSwap memory singleSwap, FundManagement memory funds, uint256 limit, uint256 deadline)\n        external\n        returns (uint256 amountCalculated);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1363.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @title IERC1363\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\n *\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\n */\ninterface IERC1363 is IERC20, IERC165 {\n    /*\n     * Note: the ERC-165 identifier for this interface is 0xb0202a11.\n     * 0xb0202a11 ===\n     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\n     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^\n     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\n     */\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\n     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\n     * @param from The address which you want to send tokens from.\n     * @param to The address which you want to transfer to.\n     * @param value The amount of tokens to be transferred.\n     * @param data Additional data with no specified format, sent in call to `to`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\n     * @param spender The address which will spend the funds.\n     * @param value The amount of tokens to be spent.\n     * @param data Additional data with no specified format, sent in call to `spender`.\n     * @return A boolean value indicating whether the operation succeeded unless throwing.\n     */\n    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\n\npragma solidity ^0.8.20;\n\nimport {Errors} from \"./Errors.sol\";\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev There's no code at `target` (it is not a contract).\n     */\n    error AddressEmptyCode(address target);\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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        if (address(this).balance < amount) {\n            revert Errors.InsufficientBalance(address(this).balance, amount);\n        }\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        if (!success) {\n            revert Errors.FailedCall();\n        }\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 or custom error, it is bubbled\n     * up by this function (like regular Solidity function calls). However, if\n     * the call reverted with no returned reason, this function reverts with a\n     * {Errors.FailedCall} error.\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    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0);\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    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        if (address(this).balance < value) {\n            revert Errors.InsufficientBalance(address(this).balance, value);\n        }\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n     * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\n     * of an unsuccessful call.\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata\n    ) internal view returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            // only check if target is a contract if the call was successful and the return data is empty\n            // otherwise we already know that it was a contract\n            if (returndata.length == 0 && target.code.length == 0) {\n                revert AddressEmptyCode(target);\n            }\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n     * revert reason or with a default {Errors.FailedCall} error.\n     */\n    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n        if (!success) {\n            _revert(returndata);\n        } else {\n            return returndata;\n        }\n    }\n\n    /**\n     * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\n     */\n    function _revert(bytes memory returndata) private pure {\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            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert Errors.FailedCall();\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../token/ERC20/IERC20.sol\";\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Errors.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Collection of common custom errors used in multiple contracts\n *\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\n * It is recommended to avoid relying on the error API for critical functionality.\n */\nlibrary Errors {\n    /**\n     * @dev The ETH balance of the account is not enough to perform the operation.\n     */\n    error InsufficientBalance(uint256 balance, uint256 needed);\n\n    /**\n     * @dev A call to an address target failed. The target may have reverted.\n     */\n    error FailedCall();\n\n    /**\n     * @dev The deployment failed.\n     */\n    error FailedDeployment();\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "forge-std/=lib/forge-std/src/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
        "solady/=lib/solady/src/utils/",
        "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
        "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": false,
      "libraries": {}
    }
  }}